[Pkg-ofed-commits] [opensm] 01/07: Imported Upstream version 3.2.6-20090317

Ana Beatriz Guerrero López ana at moszumanska.debian.org
Tue Jul 1 07:19:49 UTC 2014


This is an automated email from the git hooks/post-receive script.

ana pushed a commit to branch master
in repository opensm.

commit 7c3d5c77595ca088e60dd0a781f07525a474254e
Author: Ana Guerrero López <ana at ekaia.org>
Date:   Mon Jun 30 22:55:32 2014 +0200

    Imported Upstream version 3.2.6-20090317
---
 AUTHORS                                         |     9 +
 COPYING                                         |    32 +
 ChangeLog                                       |    14 +
 INSTALL                                         |   231 +
 Makefile.am                                     |    32 +
 Makefile.in                                     |   763 ++
 NEWS                                            |     2 +
 README                                          |    25 +
 aclocal.m4                                      |   883 ++
 autogen.sh                                      |    57 +
 complib/ChangeLog                               |    96 +
 complib/Makefile.am                             |    81 +
 complib/Makefile.in                             |   726 +
 complib/cl_complib.c                            |    92 +
 complib/cl_dispatcher.c                         |   377 +
 complib/cl_event.c                              |   175 +
 complib/cl_event_wheel.c                        |   573 +
 complib/cl_list.c                               |   581 +
 complib/cl_log.c                                |   118 +
 complib/cl_map.c                                |  1636 +++
 complib/cl_nodenamemap.c                        |   192 +
 complib/cl_pool.c                               |   671 +
 complib/cl_ptr_vector.c                         |   319 +
 complib/cl_spinlock.c                           |    91 +
 complib/cl_statustext.c                         |    71 +
 complib/cl_thread.c                             |   141 +
 complib/cl_threadpool.c                         |   148 +
 complib/cl_timer.c                              |   446 +
 complib/cl_vector.c                             |   561 +
 complib/ib_statustext.c                         |   153 +
 complib/libosmcomp.map                          |   154 +
 complib/libosmcomp.ver                          |     9 +
 config/config.guess                             |  1548 +++
 config/config.sub                               |  1695 +++
 config/depcomp                                  |   589 +
 config/install-sh                               |   519 +
 config/libtool.m4                               |  7370 ++++++++++
 config/ltmain.sh                                |  8461 ++++++++++++
 config/ltoptions.m4                             |   368 +
 config/ltsugar.m4                               |   123 +
 config/ltversion.m4                             |    23 +
 config/lt~obsolete.m4                           |    92 +
 config/missing                                  |   367 +
 config/osmvsel.m4                               |   259 +
 config/ylwrap                                   |   223 +
 configure                                       | 15736 ++++++++++++++++++++++
 configure.in                                    |   232 +
 doc/QoS_management_in_OpenSM.txt                |   492 +
 doc/opensm_release_notes-3.2.txt                |   626 +
 doc/performance-manager-HOWTO.txt               |   153 +
 include/Makefile.am                             |    33 +
 include/Makefile.in                             |   587 +
 include/complib/cl_atomic.h                     |   196 +
 include/complib/cl_atomic_osd.h                 |   104 +
 include/complib/cl_byteswap.h                   |   524 +
 include/complib/cl_byteswap_osd.h               |    75 +
 include/complib/cl_comppool.h                   |   585 +
 include/complib/cl_debug.h                      |   594 +
 include/complib/cl_debug_osd.h                  |    92 +
 include/complib/cl_dispatcher.h                 |   631 +
 include/complib/cl_event.h                      |   279 +
 include/complib/cl_event_osd.h                  |    69 +
 include/complib/cl_event_wheel.h                |   457 +
 include/complib/cl_fleximap.h                   |   907 ++
 include/complib/cl_list.h                       |  1292 ++
 include/complib/cl_log.h                        |   142 +
 include/complib/cl_map.h                        |   846 ++
 include/complib/cl_math.h                       |   138 +
 include/complib/cl_nodenamemap.h                |    65 +
 include/complib/cl_packoff.h                    |    49 +
 include/complib/cl_packon.h                     |    83 +
 include/complib/cl_passivelock.h                |   323 +
 include/complib/cl_pool.h                       |   561 +
 include/complib/cl_ptr_vector.h                 |   825 ++
 include/complib/cl_qcomppool.h                  |   736 +
 include/complib/cl_qlist.h                      |  1702 +++
 include/complib/cl_qmap.h                       |   975 ++
 include/complib/cl_qpool.h                      |   606 +
 include/complib/cl_spinlock.h                   |   272 +
 include/complib/cl_spinlock_osd.h               |    61 +
 include/complib/cl_thread.h                     |   356 +
 include/complib/cl_thread_osd.h                 |    68 +
 include/complib/cl_threadpool.h                 |   248 +
 include/complib/cl_timer.h                      |   349 +
 include/complib/cl_timer_osd.h                  |    81 +
 include/complib/cl_types.h                      |   464 +
 include/complib/cl_types_osd.h                  |    88 +
 include/complib/cl_vector.h                     |   945 ++
 include/config.h.in                             |   157 +
 include/iba/ib_cm_types.h                       |   203 +
 include/iba/ib_types.h                          | 10720 +++++++++++++++
 include/opensm/osm_attrib_req.h                 |   108 +
 include/opensm/osm_base.h                       |   898 ++
 include/opensm/osm_config.h.in                  |    64 +
 include/opensm/osm_console.h                    |    51 +
 include/opensm/osm_console_io.h                 |    90 +
 include/opensm/osm_db.h                         |   427 +
 include/opensm/osm_db_pack.h                    |   243 +
 include/opensm/osm_errors.h                     |   176 +
 include/opensm/osm_event_plugin.h               |   192 +
 include/opensm/osm_helper.h                     |   550 +
 include/opensm/osm_inform.h                     |   238 +
 include/opensm/osm_lid_mgr.h                    |   289 +
 include/opensm/osm_log.h                        |   482 +
 include/opensm/osm_mad_pool.h                   |   372 +
 include/opensm/osm_madw.h                       |  1115 ++
 include/opensm/osm_mcast_tbl.h                  |   461 +
 include/opensm/osm_mcm_info.h                   |   136 +
 include/opensm/osm_mcm_port.h                   |   158 +
 include/opensm/osm_msgdef.h                     |   167 +
 include/opensm/osm_mtree.h                      |   274 +
 include/opensm/osm_multicast.h                  |   503 +
 include/opensm/osm_node.h                       |   679 +
 include/opensm/osm_opensm.h                     |   527 +
 include/opensm/osm_partition.h                  |   273 +
 include/opensm/osm_path.h                       |   250 +
 include/opensm/osm_perfmgr.h                    |   250 +
 include/opensm/osm_perfmgr_db.h                 |   209 +
 include/opensm/osm_pkey.h                       |   695 +
 include/opensm/osm_pkey_mgr.h                   |    80 +
 include/opensm/osm_port.h                       |  1591 +++
 include/opensm/osm_port_profile.h               |   207 +
 include/opensm/osm_prefix_route.h               |    63 +
 include/opensm/osm_qos_policy.h                 |   204 +
 include/opensm/osm_remote_sm.h                  |   198 +
 include/opensm/osm_router.h                     |   217 +
 include/opensm/osm_sa.h                         |   496 +
 include/opensm/osm_sa_mad_ctrl.h                |   338 +
 include/opensm/osm_service.h                    |   194 +
 include/opensm/osm_sm.h                         |   798 ++
 include/opensm/osm_sm_mad_ctrl.h                |   323 +
 include/opensm/osm_stats.h                      |   184 +
 include/opensm/osm_subnet.h                     |  1106 ++
 include/opensm/osm_switch.h                     |  1152 ++
 include/opensm/osm_ucast_cache.h                |   240 +
 include/opensm/osm_ucast_mgr.h                  |   308 +
 include/opensm/osm_version.h.in                 |    51 +
 include/opensm/osm_vl15intf.h                   |   367 +
 include/opensm/st.h                             |   102 +
 include/vendor/osm_mtl_bind.h                   |   136 +
 include/vendor/osm_pkt_randomizer.h             |   224 +
 include/vendor/osm_ts_useraccess.h              |    52 +
 include/vendor/osm_umadt.h                      |   137 +
 include/vendor/osm_vendor.h                     |    71 +
 include/vendor/osm_vendor_al.h                  |   348 +
 include/vendor/osm_vendor_api.h                 |   487 +
 include/vendor/osm_vendor_ibumad.h              |   181 +
 include/vendor/osm_vendor_mlx.h                 |    96 +
 include/vendor/osm_vendor_mlx_defs.h            |   103 +
 include/vendor/osm_vendor_mlx_dispatcher.h      |    70 +
 include/vendor/osm_vendor_mlx_hca.h             |    64 +
 include/vendor/osm_vendor_mlx_inout.h           |    76 +
 include/vendor/osm_vendor_mlx_rmpp_ctx.h        |   289 +
 include/vendor/osm_vendor_mlx_sar.h             |   116 +
 include/vendor/osm_vendor_mlx_sender.h          |   128 +
 include/vendor/osm_vendor_mlx_svc.h             |   201 +
 include/vendor/osm_vendor_mlx_transport.h       |    95 +
 include/vendor/osm_vendor_mlx_transport_anafa.h |    69 +
 include/vendor/osm_vendor_mlx_txn.h             |   380 +
 include/vendor/osm_vendor_mtl.h                 |   348 +
 include/vendor/osm_vendor_mtl_hca_guid.h        |   195 +
 include/vendor/osm_vendor_mtl_transaction_mgr.h |   299 +
 include/vendor/osm_vendor_sa_api.h              |   866 ++
 include/vendor/osm_vendor_test.h                |   123 +
 include/vendor/osm_vendor_ts.h                  |   410 +
 include/vendor/osm_vendor_umadt.h               |   130 +
 libvendor/ChangeLog                             |    64 +
 libvendor/Makefile.am                           |    86 +
 libvendor/Makefile.in                           |   862 ++
 libvendor/libosmvendor.map                      |    20 +
 libvendor/libosmvendor.ver                      |     9 +
 libvendor/osm_pkt_randomizer.c                  |   329 +
 libvendor/osm_vendor_ibumad.c                   |  1154 ++
 libvendor/osm_vendor_ibumad_sa.c                |   736 +
 libvendor/osm_vendor_mlx.c                      |   770 ++
 libvendor/osm_vendor_mlx_dispatcher.c           |   710 +
 libvendor/osm_vendor_mlx_hca.c                  |   524 +
 libvendor/osm_vendor_mlx_hca_sim.c              |   864 ++
 libvendor/osm_vendor_mlx_ibmgt.c                |   783 ++
 libvendor/osm_vendor_mlx_rmpp_ctx.c             |   361 +
 libvendor/osm_vendor_mlx_sa.c                   |   834 ++
 libvendor/osm_vendor_mlx_sar.c                  |   154 +
 libvendor/osm_vendor_mlx_sender.c               |   390 +
 libvendor/osm_vendor_mlx_sim.c                  |   439 +
 libvendor/osm_vendor_mlx_ts.c                   |   505 +
 libvendor/osm_vendor_mlx_txn.c                  |   675 +
 man/opensm.8.in                                 |  1012 ++
 man/osmtest.8                                   |   190 +
 opensm.spec.in                                  |   146 +
 opensm/ChangeLog                                |   115 +
 opensm/Makefile.am                              |   132 +
 opensm/Makefile.in                              |   816 ++
 opensm/libopensm.map                            |    59 +
 opensm/libopensm.ver                            |     9 +
 opensm/main.c                                   |  1027 ++
 opensm/osm_console.c                            |  1320 ++
 opensm/osm_console_io.c                         |   254 +
 opensm/osm_db_files.c                           |   723 +
 opensm/osm_db_pack.c                            |   157 +
 opensm/osm_drop_mgr.c                           |   516 +
 opensm/osm_dump.c                               |   642 +
 opensm/osm_event_plugin.c                       |   150 +
 opensm/osm_helper.c                             |  2333 ++++
 opensm/osm_inform.c                             |   615 +
 opensm/osm_lid_mgr.c                            |  1321 ++
 opensm/osm_lin_fwd_rcv.c                        |   101 +
 opensm/osm_link_mgr.c                           |   416 +
 opensm/osm_log.c                                |   337 +
 opensm/osm_mad_pool.c                           |   188 +
 opensm/osm_mcast_fwd_rcv.c                      |   121 +
 opensm/osm_mcast_mgr.c                          |  1267 ++
 opensm/osm_mcast_tbl.c                          |   284 +
 opensm/osm_mcm_info.c                           |    70 +
 opensm/osm_mcm_port.c                           |    76 +
 opensm/osm_mtree.c                              |   125 +
 opensm/osm_multicast.c                          |   302 +
 opensm/osm_node.c                               |   312 +
 opensm/osm_node_desc_rcv.c                      |   128 +
 opensm/osm_node_info_rcv.c                      |   866 ++
 opensm/osm_opensm.c                             |   497 +
 opensm/osm_perfmgr.c                            |  1311 ++
 opensm/osm_perfmgr_db.c                         |   807 ++
 opensm/osm_pkey.c                               |   505 +
 opensm/osm_pkey_mgr.c                           |   529 +
 opensm/osm_pkey_rcv.c                           |   145 +
 opensm/osm_port.c                               |   780 ++
 opensm/osm_port_info_rcv.c                      |   687 +
 opensm/osm_prtn.c                               |   392 +
 opensm/osm_prtn_config.c                        |   460 +
 opensm/osm_qos.c                                |   413 +
 opensm/osm_qos_parser_l.c                       |  2672 ++++
 opensm/osm_qos_parser_l.l                       |   394 +
 opensm/osm_qos_parser_y.c                       |  5177 +++++++
 opensm/osm_qos_parser_y.h                       |   208 +
 opensm/osm_qos_parser_y.y                       |  3063 +++++
 opensm/osm_qos_policy.c                         |  1091 ++
 opensm/osm_remote_sm.c                          |    79 +
 opensm/osm_req.c                                |   280 +
 opensm/osm_resp.c                               |   157 +
 opensm/osm_router.c                             |    75 +
 opensm/osm_sa.c                                 |  1123 ++
 opensm/osm_sa_class_port_info.c                 |   213 +
 opensm/osm_sa_guidinfo_record.c                 |   362 +
 opensm/osm_sa_informinfo.c                      |   624 +
 opensm/osm_sa_lft_record.c                      |   246 +
 opensm/osm_sa_link_record.c                     |   505 +
 opensm/osm_sa_mad_ctrl.c                        |   592 +
 opensm/osm_sa_mcmember_record.c                 |  1739 +++
 opensm/osm_sa_mft_record.c                      |   280 +
 opensm/osm_sa_multipath_record.c                |  1536 +++
 opensm/osm_sa_node_record.c                     |   355 +
 opensm/osm_sa_path_record.c                     |  1811 +++
 opensm/osm_sa_pkey_record.c                     |   347 +
 opensm/osm_sa_portinfo_record.c                 |   592 +
 opensm/osm_sa_service_record.c                  |   842 ++
 opensm/osm_sa_slvl_record.c                     |   319 +
 opensm/osm_sa_sminfo_record.c                   |   331 +
 opensm/osm_sa_sw_info_record.c                  |   273 +
 opensm/osm_sa_vlarb_record.c                    |   336 +
 opensm/osm_service.c                            |   166 +
 opensm/osm_slvl_map_rcv.c                       |   152 +
 opensm/osm_sm.c                                 |   671 +
 opensm/osm_sm_mad_ctrl.c                        |   874 ++
 opensm/osm_sm_state_mgr.c                       |   551 +
 opensm/osm_sminfo_rcv.c                         |   604 +
 opensm/osm_state_mgr.c                          |  1397 ++
 opensm/osm_subnet.c                             |  1719 +++
 opensm/osm_sw_info_rcv.c                        |   506 +
 opensm/osm_switch.c                             |   667 +
 opensm/osm_trap_rcv.c                           |   714 +
 opensm/osm_ucast_cache.c                        |  1095 ++
 opensm/osm_ucast_file.c                         |   396 +
 opensm/osm_ucast_ftree.c                        |  3669 +++++
 opensm/osm_ucast_lash.c                         |  1356 ++
 opensm/osm_ucast_mgr.c                          |   903 ++
 opensm/osm_ucast_updn.c                         |   686 +
 opensm/osm_vl15intf.c                           |   386 +
 opensm/osm_vl_arb_rcv.c                         |   154 +
 opensm/st.c                                     |   588 +
 osmeventplugin/Makefile.am                      |    34 +
 osmeventplugin/Makefile.in                      |   545 +
 osmeventplugin/libosmeventplugin.map            |     5 +
 osmeventplugin/libosmeventplugin.ver            |     9 +
 osmeventplugin/src/osmeventplugin.c             |   188 +
 osmtest/Makefile.am                             |    23 +
 osmtest/Makefile.in                             |   614 +
 osmtest/include/osmt_inform.h                   |    78 +
 osmtest/include/osmt_mtl_regular_qp.h           |   162 +
 osmtest/include/osmtest.h                       |   510 +
 osmtest/include/osmtest_base.h                  |    67 +
 osmtest/include/osmtest_subnet.h                |   326 +
 osmtest/main.c                                  |   623 +
 osmtest/osmt_inform.c                           |   767 ++
 osmtest/osmt_mtl_regular_qp.c                   |   469 +
 osmtest/osmt_multicast.c                        |  2707 ++++
 osmtest/osmt_service.c                          |  1616 +++
 osmtest/osmt_slvl_vl_arb.c                      |   528 +
 osmtest/osmtest.c                               |  7403 ++++++++++
 scripts/opensm.init.in                          |   133 +
 scripts/opensm.logrotate                        |     7 +
 scripts/opensm.sysconfig                        |     2 +
 scripts/redhat-opensm.init.in                   |   292 +
 scripts/sldd.sh.in                              |   246 +
 303 files changed, 192768 insertions(+)

diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..0106a07
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+
+By the chronological order of involvement:
+Steve King,          Intel
+Anil Keshavamurthy,  Intel
+Eitan Zahavi,        Mellanox Technologies,  eitan at mellanox.co.il
+Yael Kalka,          Mellanox Technologies,  yael at mellanox.co.il
+Shahar Frank,        Voltaire
+Hal Rosenstock,      Voltaire,               halr at voltaire.com
+Sasha Khapyorsky,    Voltaire,               sashak at voltaire.com
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..07e5ab0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,32 @@
+ Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ This software is available to you under a choice of one of two
+ licenses.  You may choose to be licensed under the terms of the GNU
+ General Public License (GPL) Version 2, available from the file
+ COPYING in the main directory of this source tree, or the
+ OpenIB.org BSD license below:
+
+     Redistribution and use in source and binary forms, with or
+     without modification, are permitted provided that the following
+     conditions are met:
+
+      - Redistributions of source code must retain the above
+        copyright notice, this list of conditions and the following
+        disclaimer.
+
+      - Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials
+        provided with the distribution.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..cb67d2b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,14 @@
+2005-09-12 Hal Rosenstock <halr at voltaire.com>
+
+	* Improved SA MCMemberRecord error messages
+
+2005-08-22 Yael Kalka <yael at mellanox.co.il>
+
+	* Merge of OpenSM 1.8.0 previously available only on Gen1
+
+2005-08-14  Eitan Zahavi  <eitan at mellanox.co.il>
+
+	* Provided a top level auto tools project so there is no need to
+	cd into each of the sub directories and do:
+	./autogen.sh && configure && make && make install
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..095b1eb
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,231 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..2287edd
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,32 @@
+
+# note that order matters: make the libs first then use them
+SUBDIRS = complib libvendor opensm osmtest include $(DEFAULT_EVENT_PLUGIN)
+DIST_SUBDIRS = complib libvendor opensm osmtest include osmeventplugin
+
+ACLOCAL_AMFLAGS = -I config
+
+# we should provide a hint for other apps about the build mode of this project
+install-exec-hook:
+	mkdir -p $(DESTDIR)/$(includedir)
+if DEBUG
+	echo "define osm_build_type \"debug\"" > $(DESTDIR)/$(includedir)/infiniband/opensm/osm_build_id.h
+else
+	echo "define osm_build_type \"free\"" > $(DESTDIR)/$(includedir)/infiniband/opensm/osm_build_id.h
+endif
+	$(top_srcdir)/config/install-sh -m 755 -d $(DESTDIR)/$(sysconfdir)/init.d
+	cp $(top_builddir)/scripts/opensm.init $(DESTDIR)/$(sysconfdir)/init.d/opensmd
+	chmod 755 $(DESTDIR)/$(sysconfdir)/init.d/opensmd
+
+
+man_MANS = man/opensm.8 man/osmtest.8
+
+various_scripts = $(wildcard scripts/*)
+docs = doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt \
+	doc/opensm_release_notes-3.2.txt
+
+EXTRA_DIST = autogen.sh opensm.spec $(various_scripts) $(man_MANS) $(docs)
+
+dist-hook: $(EXTRA_DIST)
+	if [ -x $(top_srcdir)/../gen_chlog.sh ] ; then \
+		cd $(top_srcdir)/.. ; ./gen_chlog.sh $(PACKAGE) > $(distdir)/ChangeLog ; cd - ; \
+	fi
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..d708faa
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,763 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/opensm.spec.in \
+	$(top_srcdir)/configure \
+	$(top_srcdir)/include/opensm/osm_config.h.in \
+	$(top_srcdir)/include/opensm/osm_version.h.in \
+	$(top_srcdir)/man/opensm.8.in \
+	$(top_srcdir)/scripts/opensm.init.in \
+	$(top_srcdir)/scripts/redhat-opensm.init.in \
+	$(top_srcdir)/scripts/sldd.sh.in AUTHORS COPYING ChangeLog \
+	INSTALL NEWS config/config.guess config/config.sub \
+	config/depcomp config/install-sh config/ltmain.sh \
+	config/missing config/ylwrap
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES = man/opensm.8 scripts/opensm.init \
+	scripts/redhat-opensm.init scripts/sldd.sh \
+	include/opensm/osm_version.h opensm.spec
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+man8dir = $(mandir)/man8
+am__installdirs = "$(DESTDIR)$(man8dir)"
+NROFF = nroff
+MANS = $(man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# note that order matters: make the libs first then use them
+SUBDIRS = complib libvendor opensm osmtest include $(DEFAULT_EVENT_PLUGIN)
+DIST_SUBDIRS = complib libvendor opensm osmtest include osmeventplugin
+ACLOCAL_AMFLAGS = -I config
+man_MANS = man/opensm.8 man/osmtest.8
+various_scripts = $(wildcard scripts/*)
+docs = doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt \
+	doc/opensm_release_notes-3.2.txt
+
+EXTRA_DIST = autogen.sh opensm.spec $(various_scripts) $(man_MANS) $(docs)
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+	      cd $(srcdir) && $(AUTOMAKE) --foreign  \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+include/opensm/osm_config.h: include/opensm/stamp-h2
+	@if test ! -f $@; then \
+	  rm -f include/opensm/stamp-h2; \
+	  $(MAKE) $(AM_MAKEFLAGS) include/opensm/stamp-h2; \
+	else :; fi
+
+include/opensm/stamp-h2: $(top_srcdir)/include/opensm/osm_config.h.in $(top_builddir)/config.status
+	@rm -f include/opensm/stamp-h2
+	cd $(top_builddir) && $(SHELL) ./config.status include/opensm/osm_config.h
+$(top_srcdir)/include/opensm/osm_config.h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f include/opensm/stamp-h2
+	touch $@
+
+distclean-hdr:
+	-rm -f include/opensm/osm_config.h include/opensm/stamp-h2
+man/opensm.8: $(top_builddir)/config.status $(top_srcdir)/man/opensm.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+scripts/opensm.init: $(top_builddir)/config.status $(top_srcdir)/scripts/opensm.init.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+scripts/redhat-opensm.init: $(top_builddir)/config.status $(top_srcdir)/scripts/redhat-opensm.init.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+scripts/sldd.sh: $(top_builddir)/config.status $(top_srcdir)/scripts/sldd.sh.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+include/opensm/osm_version.h: $(top_builddir)/config.status $(top_srcdir)/include/opensm/osm_version.h.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+opensm.spec: $(top_builddir)/config.status $(srcdir)/opensm.spec.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+install-man8: $(man8_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $$i; then file=$$i; \
+	  else file=$(srcdir)/$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d $(distdir) || mkdir $(distdir)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+	$(am__remove_distdir)
+
+dist-lzma: distdir
+	tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+	$(am__remove_distdir)
+
+dist-tarZ: distdir
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__remove_distdir)
+
+dist-shar: distdir
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lzma*) \
+	  unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && cd $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@cd $(distuninstallcheck_dir) \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(MANS)
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(man8dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+	distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man: install-man8
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-man
+
+uninstall-man: uninstall-man8
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-exec-am install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am am--refresh check check-am clean clean-generic \
+	clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
+	dist-gzip dist-hook dist-lzma dist-shar dist-tarZ dist-zip \
+	distcheck distclean distclean-generic distclean-hdr \
+	distclean-libtool distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-exec-hook \
+	install-html install-html-am install-info install-info-am \
+	install-man install-man8 install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-man uninstall-man8
+
+
+# we should provide a hint for other apps about the build mode of this project
+install-exec-hook:
+	mkdir -p $(DESTDIR)/$(includedir)
+ at DEBUG_TRUE@	echo "define osm_build_type \"debug\"" > $(DESTDIR)/$(includedir)/infiniband/opensm/osm_build_id.h
+ at DEBUG_FALSE@	echo "define osm_build_type \"free\"" > $(DESTDIR)/$(includedir)/infiniband/opensm/osm_build_id.h
+	$(top_srcdir)/config/install-sh -m 755 -d $(DESTDIR)/$(sysconfdir)/init.d
+	cp $(top_builddir)/scripts/opensm.init $(DESTDIR)/$(sysconfdir)/init.d/opensmd
+	chmod 755 $(DESTDIR)/$(sysconfdir)/init.d/opensmd
+
+dist-hook: $(EXTRA_DIST)
+	if [ -x $(top_srcdir)/../gen_chlog.sh ] ; then \
+		cd $(top_srcdir)/.. ; ./gen_chlog.sh $(PACKAGE) > $(distdir)/ChangeLog ; cd - ; \
+	fi
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..8887552
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
+
+This file will hold news about the OpenSM project.
diff --git a/README b/README
new file mode 100644
index 0000000..40556ba
--- /dev/null
+++ b/README
@@ -0,0 +1,25 @@
+OpenSM README:
+--------------
+
+OpenSM provides an implementation for an InfiniBand Subnet Manager and
+Administrator. Such a software entity is required to run for in order
+to initialize the InfiniBand hardware (at least one per each
+InfiniBand subnet).
+
+The full list of OpenSM features is described in the user manual
+provided in the doc sub directory.
+
+The installation of OpenSM includes:
+
+sbin/
+   opensm - the SM/SA executable
+   osmtest - a test program for the SM/SA
+lib/
+   libosmcomp.{a,so} - component library with generic services and containers
+   libopensm.{a,so} - opensm services for logs and mad buffer pool
+   libosmvendor.{a,so} - interface to the user mad service of the driver
+include/
+   iba/ib_types.h - IBA types header file
+   complib/ - component library includes
+   vendor/  - vendor library includes
+   opensm/  - public opensm library includes
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..0551697
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,883 @@
+# generated automatically by aclocal 1.10.2 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.63],,
+[m4_warning([this file was generated for autoconf 2.63.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.10.2], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.2])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 4
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[# Autoconf 2.62 quotes --file arguments for eval, but not when files
+# are listed without --file.  Let's play safe and only enable the eval
+# if we detect the quoting.
+case $CONFIG_FILES in
+*\'*) eval set x "$CONFIG_FILES" ;;
+*)   set x $CONFIG_FILES ;;
+esac
+shift
+for mf
+do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 13
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+	      		     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                  [_AM_DEPENDENCIES(OBJC)],
+                  [define([AC_PROG_OBJC],
+                          defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([config/libtool.m4])
+m4_include([config/ltoptions.m4])
+m4_include([config/ltsugar.m4])
+m4_include([config/ltversion.m4])
+m4_include([config/lt~obsolete.m4])
+m4_include([config/osmvsel.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..fee8800
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+# We change dir since the later utilities assume to work in the project dir
+cd ${0%*/*}
+
+# make sure autoconf is up-to-date
+ac_ver=`autoconf --version | head -n 1 | awk '{print $NF}'`
+ac_maj=`echo $ac_ver|sed 's/\..*//'`
+ac_min=`echo $ac_ver|sed 's/.*\.//'`
+if [[ $ac_maj -lt 2 ]]; then
+    echo Min autoconf version is 2.57
+    exit 1
+elif [[ $ac_maj -eq 2 && $ac_min -lt 57 ]]; then
+    echo Min autoconf version is 2.57
+    exit 1
+fi
+
+# make sure automake is up-to-date
+am_ver=`automake --version | head -n 1 | awk '{print $NF}'`
+am_maj=`echo $am_ver|sed 's/\..*//'`
+am_min=`echo $am_ver|sed 's/[^\.]*\.\([^\.]*\)\.*.*/\1/'`
+am_sub=`echo $am_ver|sed 's/[^\.]*\.[^\.]*\.*//'`
+if [[ $am_maj -lt 1 ]]; then
+    echo Min automake version is 1.6.3
+    exit 1
+elif [[ $am_maj -eq 1 && $am_min -lt 6 ]]; then
+    echo "automake version is too old:$am_maj.$am_min.$am_sub < required 1.6.3"
+    exit 1
+elif [[ $am_maj -eq 1 && $am_min -eq 6 && $am_sub -lt 3 ]]; then
+    echo "automake version is too old:$am_maj.$am_min.$am_sub < required 1.6.3"
+    exit 1
+fi
+
+# make sure libtool is up-to-date
+lt_ver=`libtool --version | head -n 1 | awk '{print $4}'`
+lt_maj=`echo $lt_ver|sed 's/\..*//'`
+lt_min=`echo $lt_ver|sed 's/[^\.]*\.\([^\.]*\)\.*.*/\1/'`
+lt_sub=`echo $lt_ver|sed 's/[^\.]*\.[^\.]*\.*//'`
+if [[ $lt_maj -lt 1 ]]; then
+    echo Min libtool version is 1.4.2
+    exit 1
+elif [[ $lt_maj -eq 1 && $lt_min -lt 4 ]]; then
+    echo "libtool version is too old:$lt_maj.$lt_min.$lt_sub < required 1.4.2"
+    exit 1
+elif [[ $lt_maj -eq 1 && $lt_min -eq 4 && $lt_sub -lt 2 ]]; then
+    echo "libtool version is too old:$lt_maj.$lt_min.$lt_sub < required 1.4.2"
+    exit 1
+fi
+
+# cleanup
+find . \( -name Makefile.in -o -name aclocal.m4 -o -name autom4te.cache -o -name configure -o -name aclocal.m4 \) -exec \rm -rf {} \; -prune
+
+aclocal -I config && \
+libtoolize --force --copy && \
+autoheader && \
+automake --foreign --add-missing --copy && \
+autoconf
diff --git a/complib/ChangeLog b/complib/ChangeLog
new file mode 100644
index 0000000..2b13147
--- /dev/null
+++ b/complib/ChangeLog
@@ -0,0 +1,96 @@
+2007-07=11  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: to version 2.2.1
+
+2007-06-25  Hal Rosenstock <halr at voltaire.com>
+
+	* cl_event_wheel.c: Fix some typos in printfs when
+	  __CL_EVENT_WHEEL_TEST__ defined
+
+2007-06-20  Hal Rosenstock <halr at voltaire.com>
+
+	* libosmcomp.map: Add get_next map functions as global
+
+2007-06-20  Todd Rimmer <todd.rimmer at qlogic.com>
+
+	* include/complib/cl_map.h, include/complib/cl_qmap.h,
+	  include/complib/cl_fleximap.h, cl_map.c:
+	  Add get_next functions to the various maps
+
+	* include/complib/cl_fleximap.h: In cl_fmap_remove_all, make
+	  sure the count field is properly maintained.
+
+2007-06-19  Todd Rimmer <todd.rimmer at qlogic.com>
+
+	* include/complib/cl_qmap.h: In cl_qmap_remove_all, make
+	  sure the count field is properly maintained.
+
+2007-06-19  Hal Rosenstock <halr at voltaire.com>
+
+	* include/complib/cl_threadpool.h: Eliminate compile warning
+	  with cl_threadpool.c introduced by previous change
+
+2007-06-13  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* include/complib/cl_threadpool.h, complib/cl_threadpool.c,
+	  complib/cl_dispatcher.c, complib/libosmcomp.map: Thread
+	  pool rework
+
+2007-06-13  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump to version 2.2.0
+
+	* libosmcomp.ver, libosmcomp.map: Update version info for
+	  previous API removals
+
+	* include/complib/cl_memory.h, include/complib/cl_memtrack.h,
+	  complib/cl_memory.c, complib/cl_memtrack.c, include/Makefile.am:
+	  Remove deprecated memory allocation related routines
+
+2007-06-13  Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
+
+	* include/complib/cl_perf.h, include/complib/cl_async_proc.h,
+	  complib/cl_perf.c, complib/cl_async_proc.c, Makefile.am,
+	  libosmcomp.map: Remove unused cl_perf and cl_async_proc
+
+2007-05-09  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump to version 2.1.2
+
+2007-03-29  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump to version 2.1.1
+
+2007-01-08  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* cl_log.c: SIGUSR1 fixes
+
+2007-01-08  Ira Weiny <weiny2 at llnl.gov>
+
+	* cl_log.c: Add SIGUSR1 handling to reopen osm.log
+
+2006-10-31  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bumped to version version 2.1.0
+
+2006-09-05  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* cl_event_wheel.c: Changes to support new osm_log
+	  initializer osm_log_init_v2()
+
+2006-08-29  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* cl_event_wheel.c: Support option to limit size of OpenSM
+	  log file
+
+2006-07-20  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* cl_pool.c: Fix memory corruption in cl_qcpool_init
+
+2006-07-19  Hal Rosenstock <halr at voltaire.com>
+
+	* Makefile.am: Eliminate deprecated warnings
+
+2006-06-11  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Released version 1.2.1 (OFED 1.1)
diff --git a/complib/Makefile.am b/complib/Makefile.am
new file mode 100644
index 0000000..6f2f203
--- /dev/null
+++ b/complib/Makefile.am
@@ -0,0 +1,81 @@
+
+INCLUDES = -I$(srcdir)/../include
+
+lib_LTLIBRARIES = libosmcomp.la
+
+if DEBUG
+DBGFLAGS = -ggdb -D_DEBUG_
+else
+DBGFLAGS = -g
+endif
+
+libosmcomp_la_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+
+if HAVE_LD_VERSION_SCRIPT
+    libosmcomp_version_script = -Wl,--version-script=$(srcdir)/libosmcomp.map
+else
+    libosmcomp_version_script =
+endif
+
+complib_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmcomp.ver | sed 's/LIBVERSION=//')
+
+libosmcomp_la_SOURCES = cl_complib.c cl_dispatcher.c \
+			cl_event.c cl_event_wheel.c \
+			cl_list.c cl_log.c cl_map.c \
+			cl_pool.c cl_ptr_vector.c \
+			cl_spinlock.c cl_statustext.c \
+			cl_thread.c cl_threadpool.c \
+			cl_timer.c cl_vector.c \
+			ib_statustext.c \
+			cl_nodenamemap.c
+
+libosmcomp_la_LDFLAGS = -version-info $(complib_api_version) \
+	 -export-dynamic $(libosmcomp_version_script)
+libosmcomp_la_DEPENDENCIES = $(srcdir)/libosmcomp.map
+
+libosmcompincludedir = $(includedir)/infiniband/complib
+
+libosmcompinclude_HEADERS = $(srcdir)/../include/complib/cl_atomic.h \
+	$(srcdir)/../include/complib/cl_atomic_osd.h \
+	$(srcdir)/../include/complib/cl_byteswap.h \
+	$(srcdir)/../include/complib/cl_byteswap_osd.h \
+	$(srcdir)/../include/complib/cl_comppool.h \
+	$(srcdir)/../include/complib/cl_debug.h \
+	$(srcdir)/../include/complib/cl_debug_osd.h \
+	$(srcdir)/../include/complib/cl_dispatcher.h \
+	$(srcdir)/../include/complib/cl_event.h \
+	$(srcdir)/../include/complib/cl_event_wheel.h \
+	$(srcdir)/../include/complib/cl_event_osd.h \
+	$(srcdir)/../include/complib/cl_fleximap.h \
+	$(srcdir)/../include/complib/cl_list.h \
+	$(srcdir)/../include/complib/cl_log.h \
+	$(srcdir)/../include/complib/cl_map.h \
+	$(srcdir)/../include/complib/cl_math.h \
+	$(srcdir)/../include/complib/cl_nodenamemap.h \
+	$(srcdir)/../include/complib/cl_packoff.h \
+	$(srcdir)/../include/complib/cl_packon.h \
+	$(srcdir)/../include/complib/cl_passivelock.h \
+	$(srcdir)/../include/complib/cl_pool.h \
+	$(srcdir)/../include/complib/cl_ptr_vector.h \
+	$(srcdir)/../include/complib/cl_qcomppool.h \
+	$(srcdir)/../include/complib/cl_qlist.h \
+	$(srcdir)/../include/complib/cl_qmap.h \
+	$(srcdir)/../include/complib/cl_qpool.h \
+	$(srcdir)/../include/complib/cl_spinlock.h \
+	$(srcdir)/../include/complib/cl_spinlock_osd.h \
+	$(srcdir)/../include/complib/cl_thread.h \
+	$(srcdir)/../include/complib/cl_thread_osd.h \
+	$(srcdir)/../include/complib/cl_threadpool.h \
+	$(srcdir)/../include/complib/cl_timer.h \
+	$(srcdir)/../include/complib/cl_timer_osd.h \
+	$(srcdir)/../include/complib/cl_types.h \
+	$(srcdir)/../include/complib/cl_types_osd.h \
+	$(srcdir)/../include/complib/cl_threadpool.h \
+	$(srcdir)/../include/complib/cl_timer.h \
+	$(srcdir)/../include/complib/cl_timer_osd.h \
+	$(srcdir)/../include/complib/cl_types.h \
+	$(srcdir)/../include/complib/cl_types_osd.h \
+	$(srcdir)/../include/complib/cl_vector.h
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmcomp.map $(srcdir)/libosmcomp.ver
diff --git a/complib/Makefile.in b/complib/Makefile.in
new file mode 100644
index 0000000..e2e4bf3
--- /dev/null
+++ b/complib/Makefile.in
@@ -0,0 +1,726 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = complib
+DIST_COMMON = $(libosmcompinclude_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in ChangeLog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+	"$(DESTDIR)$(libosmcompincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libosmcomp_la_LIBADD =
+am_libosmcomp_la_OBJECTS = libosmcomp_la-cl_complib.lo \
+	libosmcomp_la-cl_dispatcher.lo libosmcomp_la-cl_event.lo \
+	libosmcomp_la-cl_event_wheel.lo libosmcomp_la-cl_list.lo \
+	libosmcomp_la-cl_log.lo libosmcomp_la-cl_map.lo \
+	libosmcomp_la-cl_pool.lo libosmcomp_la-cl_ptr_vector.lo \
+	libosmcomp_la-cl_spinlock.lo libosmcomp_la-cl_statustext.lo \
+	libosmcomp_la-cl_thread.lo libosmcomp_la-cl_threadpool.lo \
+	libosmcomp_la-cl_timer.lo libosmcomp_la-cl_vector.lo \
+	libosmcomp_la-ib_statustext.lo libosmcomp_la-cl_nodenamemap.lo
+libosmcomp_la_OBJECTS = $(am_libosmcomp_la_OBJECTS)
+libosmcomp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libosmcomp_la_CFLAGS) \
+	$(CFLAGS) $(libosmcomp_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libosmcomp_la_SOURCES)
+DIST_SOURCES = $(libosmcomp_la_SOURCES)
+libosmcompincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libosmcompinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I$(srcdir)/../include
+lib_LTLIBRARIES = libosmcomp.la
+ at DEBUG_FALSE@DBGFLAGS = -g
+ at DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_
+libosmcomp_la_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+ at HAVE_LD_VERSION_SCRIPT_FALSE@libosmcomp_version_script = 
+ at HAVE_LD_VERSION_SCRIPT_TRUE@libosmcomp_version_script = -Wl,--version-script=$(srcdir)/libosmcomp.map
+complib_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmcomp.ver | sed 's/LIBVERSION=//')
+libosmcomp_la_SOURCES = cl_complib.c cl_dispatcher.c \
+			cl_event.c cl_event_wheel.c \
+			cl_list.c cl_log.c cl_map.c \
+			cl_pool.c cl_ptr_vector.c \
+			cl_spinlock.c cl_statustext.c \
+			cl_thread.c cl_threadpool.c \
+			cl_timer.c cl_vector.c \
+			ib_statustext.c \
+			cl_nodenamemap.c
+
+libosmcomp_la_LDFLAGS = -version-info $(complib_api_version) \
+	 -export-dynamic $(libosmcomp_version_script)
+
+libosmcomp_la_DEPENDENCIES = $(srcdir)/libosmcomp.map
+libosmcompincludedir = $(includedir)/infiniband/complib
+libosmcompinclude_HEADERS = $(srcdir)/../include/complib/cl_atomic.h \
+	$(srcdir)/../include/complib/cl_atomic_osd.h \
+	$(srcdir)/../include/complib/cl_byteswap.h \
+	$(srcdir)/../include/complib/cl_byteswap_osd.h \
+	$(srcdir)/../include/complib/cl_comppool.h \
+	$(srcdir)/../include/complib/cl_debug.h \
+	$(srcdir)/../include/complib/cl_debug_osd.h \
+	$(srcdir)/../include/complib/cl_dispatcher.h \
+	$(srcdir)/../include/complib/cl_event.h \
+	$(srcdir)/../include/complib/cl_event_wheel.h \
+	$(srcdir)/../include/complib/cl_event_osd.h \
+	$(srcdir)/../include/complib/cl_fleximap.h \
+	$(srcdir)/../include/complib/cl_list.h \
+	$(srcdir)/../include/complib/cl_log.h \
+	$(srcdir)/../include/complib/cl_map.h \
+	$(srcdir)/../include/complib/cl_math.h \
+	$(srcdir)/../include/complib/cl_nodenamemap.h \
+	$(srcdir)/../include/complib/cl_packoff.h \
+	$(srcdir)/../include/complib/cl_packon.h \
+	$(srcdir)/../include/complib/cl_passivelock.h \
+	$(srcdir)/../include/complib/cl_pool.h \
+	$(srcdir)/../include/complib/cl_ptr_vector.h \
+	$(srcdir)/../include/complib/cl_qcomppool.h \
+	$(srcdir)/../include/complib/cl_qlist.h \
+	$(srcdir)/../include/complib/cl_qmap.h \
+	$(srcdir)/../include/complib/cl_qpool.h \
+	$(srcdir)/../include/complib/cl_spinlock.h \
+	$(srcdir)/../include/complib/cl_spinlock_osd.h \
+	$(srcdir)/../include/complib/cl_thread.h \
+	$(srcdir)/../include/complib/cl_thread_osd.h \
+	$(srcdir)/../include/complib/cl_threadpool.h \
+	$(srcdir)/../include/complib/cl_timer.h \
+	$(srcdir)/../include/complib/cl_timer_osd.h \
+	$(srcdir)/../include/complib/cl_types.h \
+	$(srcdir)/../include/complib/cl_types_osd.h \
+	$(srcdir)/../include/complib/cl_threadpool.h \
+	$(srcdir)/../include/complib/cl_timer.h \
+	$(srcdir)/../include/complib/cl_timer_osd.h \
+	$(srcdir)/../include/complib/cl_types.h \
+	$(srcdir)/../include/complib/cl_types_osd.h \
+	$(srcdir)/../include/complib/cl_vector.h
+
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmcomp.map $(srcdir)/libosmcomp.ver
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  complib/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  complib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libosmcomp.la: $(libosmcomp_la_OBJECTS) $(libosmcomp_la_DEPENDENCIES) 
+	$(libosmcomp_la_LINK) -rpath $(libdir) $(libosmcomp_la_OBJECTS) $(libosmcomp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_complib.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_dispatcher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_event.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_event_wheel.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_list.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_log.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_map.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_nodenamemap.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_pool.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_ptr_vector.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_spinlock.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_statustext.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_thread.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_threadpool.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_timer.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-cl_vector.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmcomp_la-ib_statustext.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libosmcomp_la-cl_complib.lo: cl_complib.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_complib.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_complib.Tpo -c -o libosmcomp_la-cl_complib.lo `test -f 'cl_complib.c' || echo '$(srcdir)/'`cl_complib.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_complib.Tpo $(DEPDIR)/libosmcomp_la-cl_complib.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_complib.c' object='libosmcomp_la-cl_complib.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_complib.lo `test -f 'cl_complib.c' || echo '$(srcdir)/'`cl_complib.c
+
+libosmcomp_la-cl_dispatcher.lo: cl_dispatcher.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_dispatcher.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_dispatcher.Tpo -c -o libosmcomp_la-cl_dispatcher.lo `test -f 'cl_dispatcher.c' || echo '$(srcdir)/'`cl_dispatcher.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_dispatcher.Tpo $(DEPDIR)/libosmcomp_la-cl_dispatcher.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_dispatcher.c' object='libosmcomp_la-cl_dispatcher.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_dispatcher.lo `test -f 'cl_dispatcher.c' || echo '$(srcdir)/'`cl_dispatcher.c
+
+libosmcomp_la-cl_event.lo: cl_event.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_event.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_event.Tpo -c -o libosmcomp_la-cl_event.lo `test -f 'cl_event.c' || echo '$(srcdir)/'`cl_event.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_event.Tpo $(DEPDIR)/libosmcomp_la-cl_event.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_event.c' object='libosmcomp_la-cl_event.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_event.lo `test -f 'cl_event.c' || echo '$(srcdir)/'`cl_event.c
+
+libosmcomp_la-cl_event_wheel.lo: cl_event_wheel.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_event_wheel.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_event_wheel.Tpo -c -o libosmcomp_la-cl_event_wheel.lo `test -f 'cl_event_wheel.c' || echo '$(srcdir)/'`cl_event_wheel.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_event_wheel.Tpo $(DEPDIR)/libosmcomp_la-cl_event_wheel.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_event_wheel.c' object='libosmcomp_la-cl_event_wheel.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_event_wheel.lo `test -f 'cl_event_wheel.c' || echo '$(srcdir)/'`cl_event_wheel.c
+
+libosmcomp_la-cl_list.lo: cl_list.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_list.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_list.Tpo -c -o libosmcomp_la-cl_list.lo `test -f 'cl_list.c' || echo '$(srcdir)/'`cl_list.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_list.Tpo $(DEPDIR)/libosmcomp_la-cl_list.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_list.c' object='libosmcomp_la-cl_list.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_list.lo `test -f 'cl_list.c' || echo '$(srcdir)/'`cl_list.c
+
+libosmcomp_la-cl_log.lo: cl_log.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_log.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_log.Tpo -c -o libosmcomp_la-cl_log.lo `test -f 'cl_log.c' || echo '$(srcdir)/'`cl_log.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_log.Tpo $(DEPDIR)/libosmcomp_la-cl_log.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_log.c' object='libosmcomp_la-cl_log.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_log.lo `test -f 'cl_log.c' || echo '$(srcdir)/'`cl_log.c
+
+libosmcomp_la-cl_map.lo: cl_map.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_map.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_map.Tpo -c -o libosmcomp_la-cl_map.lo `test -f 'cl_map.c' || echo '$(srcdir)/'`cl_map.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_map.Tpo $(DEPDIR)/libosmcomp_la-cl_map.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_map.c' object='libosmcomp_la-cl_map.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_map.lo `test -f 'cl_map.c' || echo '$(srcdir)/'`cl_map.c
+
+libosmcomp_la-cl_pool.lo: cl_pool.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_pool.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_pool.Tpo -c -o libosmcomp_la-cl_pool.lo `test -f 'cl_pool.c' || echo '$(srcdir)/'`cl_pool.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_pool.Tpo $(DEPDIR)/libosmcomp_la-cl_pool.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_pool.c' object='libosmcomp_la-cl_pool.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_pool.lo `test -f 'cl_pool.c' || echo '$(srcdir)/'`cl_pool.c
+
+libosmcomp_la-cl_ptr_vector.lo: cl_ptr_vector.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_ptr_vector.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Tpo -c -o libosmcomp_la-cl_ptr_vector.lo `test -f 'cl_ptr_vector.c' || echo '$(srcdir)/'`cl_ptr_vector.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Tpo $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_ptr_vector.c' object='libosmcomp_la-cl_ptr_vector.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_ptr_vector.lo `test -f 'cl_ptr_vector.c' || echo '$(srcdir)/'`cl_ptr_vector.c
+
+libosmcomp_la-cl_spinlock.lo: cl_spinlock.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_spinlock.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_spinlock.Tpo -c -o libosmcomp_la-cl_spinlock.lo `test -f 'cl_spinlock.c' || echo '$(srcdir)/'`cl_spinlock.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_spinlock.Tpo $(DEPDIR)/libosmcomp_la-cl_spinlock.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_spinlock.c' object='libosmcomp_la-cl_spinlock.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_spinlock.lo `test -f 'cl_spinlock.c' || echo '$(srcdir)/'`cl_spinlock.c
+
+libosmcomp_la-cl_statustext.lo: cl_statustext.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_statustext.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_statustext.Tpo -c -o libosmcomp_la-cl_statustext.lo `test -f 'cl_statustext.c' || echo '$(srcdir)/'`cl_statustext.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_statustext.Tpo $(DEPDIR)/libosmcomp_la-cl_statustext.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_statustext.c' object='libosmcomp_la-cl_statustext.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_statustext.lo `test -f 'cl_statustext.c' || echo '$(srcdir)/'`cl_statustext.c
+
+libosmcomp_la-cl_thread.lo: cl_thread.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_thread.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_thread.Tpo -c -o libosmcomp_la-cl_thread.lo `test -f 'cl_thread.c' || echo '$(srcdir)/'`cl_thread.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_thread.Tpo $(DEPDIR)/libosmcomp_la-cl_thread.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_thread.c' object='libosmcomp_la-cl_thread.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_thread.lo `test -f 'cl_thread.c' || echo '$(srcdir)/'`cl_thread.c
+
+libosmcomp_la-cl_threadpool.lo: cl_threadpool.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_threadpool.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_threadpool.Tpo -c -o libosmcomp_la-cl_threadpool.lo `test -f 'cl_threadpool.c' || echo '$(srcdir)/'`cl_threadpool.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_threadpool.Tpo $(DEPDIR)/libosmcomp_la-cl_threadpool.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_threadpool.c' object='libosmcomp_la-cl_threadpool.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_threadpool.lo `test -f 'cl_threadpool.c' || echo '$(srcdir)/'`cl_threadpool.c
+
+libosmcomp_la-cl_timer.lo: cl_timer.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_timer.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_timer.Tpo -c -o libosmcomp_la-cl_timer.lo `test -f 'cl_timer.c' || echo '$(srcdir)/'`cl_timer.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_timer.Tpo $(DEPDIR)/libosmcomp_la-cl_timer.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_timer.c' object='libosmcomp_la-cl_timer.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_timer.lo `test -f 'cl_timer.c' || echo '$(srcdir)/'`cl_timer.c
+
+libosmcomp_la-cl_vector.lo: cl_vector.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_vector.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_vector.Tpo -c -o libosmcomp_la-cl_vector.lo `test -f 'cl_vector.c' || echo '$(srcdir)/'`cl_vector.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_vector.Tpo $(DEPDIR)/libosmcomp_la-cl_vector.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_vector.c' object='libosmcomp_la-cl_vector.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_vector.lo `test -f 'cl_vector.c' || echo '$(srcdir)/'`cl_vector.c
+
+libosmcomp_la-ib_statustext.lo: ib_statustext.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-ib_statustext.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-ib_statustext.Tpo -c -o libosmcomp_la-ib_statustext.lo `test -f 'ib_statustext.c' || echo '$(srcdir)/'`ib_statustext.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-ib_statustext.Tpo $(DEPDIR)/libosmcomp_la-ib_statustext.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='ib_statustext.c' object='libosmcomp_la-ib_statustext.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-ib_statustext.lo `test -f 'ib_statustext.c' || echo '$(srcdir)/'`ib_statustext.c
+
+libosmcomp_la-cl_nodenamemap.lo: cl_nodenamemap.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_nodenamemap.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Tpo -c -o libosmcomp_la-cl_nodenamemap.lo `test -f 'cl_nodenamemap.c' || echo '$(srcdir)/'`cl_nodenamemap.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Tpo $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cl_nodenamemap.c' object='libosmcomp_la-cl_nodenamemap.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_nodenamemap.lo `test -f 'cl_nodenamemap.c' || echo '$(srcdir)/'`cl_nodenamemap.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-libosmcompincludeHEADERS: $(libosmcompinclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libosmcompincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmcompincludedir)"
+	@list='$(libosmcompinclude_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libosmcompincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libosmcompincludedir)/$$f'"; \
+	  $(libosmcompincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libosmcompincludedir)/$$f"; \
+	done
+
+uninstall-libosmcompincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libosmcompinclude_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libosmcompincludedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libosmcompincludedir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmcompincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libosmcompincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES \
+	uninstall-libosmcompincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-libosmcompincludeHEADERS \
+	install-man install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-libLTLIBRARIES \
+	uninstall-libosmcompincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/complib/cl_complib.c b/complib/cl_complib.c
new file mode 100644
index 0000000..2449d9d
--- /dev/null
+++ b/complib/cl_complib.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_spinlock.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/*
+ *  Prototypes
+ */
+
+extern
+ cl_status_t __cl_timer_prov_create(void);
+
+extern
+void __cl_timer_prov_destroy(void);
+
+cl_spinlock_t cl_atomic_spinlock;
+
+void complib_init(void)
+{
+	cl_status_t status = CL_SUCCESS;
+
+	status = cl_spinlock_init(&cl_atomic_spinlock);
+	if (status != CL_SUCCESS)
+		goto _error;
+
+	status = __cl_timer_prov_create();
+	if (status != CL_SUCCESS)
+		goto _error;
+	return;
+
+_error:
+	cl_msg_out("__init: failed to create complib (%s)\n",
+		   CL_STATUS_MSG(status));
+	exit(1);
+}
+
+void complib_exit(void)
+{
+	__cl_timer_prov_destroy();
+	cl_spinlock_destroy(&cl_atomic_spinlock);
+}
+
+boolean_t cl_is_debug(void)
+{
+#if defined( _DEBUG_ )
+	return TRUE;
+#else
+	return FALSE;
+#endif				/* defined( _DEBUG_ ) */
+}
diff --git a/complib/cl_dispatcher.c b/complib/cl_dispatcher.c
new file mode 100644
index 0000000..b0a0a76
--- /dev/null
+++ b/complib/cl_dispatcher.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of Dispatcher abstraction.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_thread.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_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);
+}
diff --git a/complib/cl_event.c b/complib/cl_event.c
new file mode 100644
index 0000000..d14b2f4
--- /dev/null
+++ b/complib/cl_event.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_event.h>
+#include <complib/cl_debug.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+void cl_event_construct(IN cl_event_t * p_event)
+{
+	CL_ASSERT(p_event);
+
+	p_event->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_event_init(IN cl_event_t * const p_event, IN const boolean_t manual_reset)
+{
+	CL_ASSERT(p_event);
+
+	cl_event_construct(p_event);
+
+	pthread_cond_init(&p_event->condvar, NULL);
+	pthread_mutex_init(&p_event->mutex, NULL);
+	p_event->signaled = FALSE;
+	p_event->manual_reset = manual_reset;
+	p_event->state = CL_INITIALIZED;
+
+	return (CL_SUCCESS);
+}
+
+void cl_event_destroy(IN cl_event_t * const p_event)
+{
+	CL_ASSERT(cl_is_state_valid(p_event->state));
+
+	/* Destroy only if the event was constructed */
+	if (p_event->state == CL_INITIALIZED) {
+		pthread_cond_broadcast(&p_event->condvar);
+		pthread_cond_destroy(&p_event->condvar);
+		pthread_mutex_destroy(&p_event->mutex);
+	}
+
+	p_event->state = CL_UNINITIALIZED;
+}
+
+cl_status_t cl_event_signal(IN cl_event_t * const p_event)
+{
+	/* Make sure that the event was started */
+	CL_ASSERT(p_event->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&p_event->mutex);
+	p_event->signaled = TRUE;
+	/* Wake up one or all depending on whether the event is auto-resetting. */
+	if (p_event->manual_reset)
+		pthread_cond_broadcast(&p_event->condvar);
+	else
+		pthread_cond_signal(&p_event->condvar);
+
+	pthread_mutex_unlock(&p_event->mutex);
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t cl_event_reset(IN cl_event_t * const p_event)
+{
+	/* Make sure that the event was started */
+	CL_ASSERT(p_event->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&p_event->mutex);
+	p_event->signaled = FALSE;
+	pthread_mutex_unlock(&p_event->mutex);
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_event_wait_on(IN cl_event_t * const p_event,
+		 IN const uint32_t wait_us, IN const boolean_t interruptible)
+{
+	cl_status_t status;
+	int wait_ret;
+	struct timespec timeout;
+	struct timeval curtime;
+
+	/* Make sure that the event was Started */
+	CL_ASSERT(p_event->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&p_event->mutex);
+
+	/* Return immediately if the event is signalled. */
+	if (p_event->signaled) {
+		if (!p_event->manual_reset)
+			p_event->signaled = FALSE;
+
+		pthread_mutex_unlock(&p_event->mutex);
+		return (CL_SUCCESS);
+	}
+
+	/* If just testing the state, return CL_TIMEOUT. */
+	if (wait_us == 0) {
+		pthread_mutex_unlock(&p_event->mutex);
+		return (CL_TIMEOUT);
+	}
+
+	if (wait_us == EVENT_NO_TIMEOUT) {
+		/* Wait for condition variable to be signaled or broadcast. */
+		if (pthread_cond_wait
+		    (&p_event->condvar, &p_event->mutex))
+			status = CL_NOT_DONE;
+		else
+			status = CL_SUCCESS;
+	} else {
+		/* Get the current time */
+		if (gettimeofday(&curtime, NULL) == 0) {
+			timeout.tv_sec = curtime.tv_sec + (wait_us / 1000000);
+			timeout.tv_nsec =
+			    (curtime.tv_usec + (wait_us % 1000000)) * 1000;
+
+			wait_ret = pthread_cond_timedwait(&p_event->condvar,
+							  &p_event->mutex,
+							  &timeout);
+			if (wait_ret == 0)
+				status =
+				    (p_event->
+				     signaled ? CL_SUCCESS : CL_NOT_DONE);
+			else if (wait_ret == ETIMEDOUT)
+				status = CL_TIMEOUT;
+			else
+				status = CL_NOT_DONE;
+		} else {
+			status = CL_ERROR;
+		}
+	}
+	if (!p_event->manual_reset)
+		p_event->signaled = FALSE;
+
+	pthread_mutex_unlock(&p_event->mutex);
+	return (status);
+}
diff --git a/complib/cl_event_wheel.c b/complib/cl_event_wheel.c
new file mode 100644
index 0000000..ca06882
--- /dev/null
+++ b/complib/cl_event_wheel.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <math.h>
+#include <stdlib.h>
+#include <complib/cl_event_wheel.h>
+#include <complib/cl_debug.h>
+
+#define CL_DBG(fmt, arg...)
+
+static cl_status_t
+__event_will_age_before(IN const cl_list_item_t * const p_list_item,
+			IN void *context)
+{
+	uint64_t aging_time = *((uint64_t *) context);
+	cl_event_wheel_reg_info_t *p_event;
+
+	p_event =
+	    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+	if (p_event->aging_time < aging_time)
+		return CL_SUCCESS;
+	else
+		return CL_NOT_FOUND;
+}
+
+static void __cl_event_wheel_callback(IN void *context)
+{
+	cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *) context;
+	cl_list_item_t *p_list_item, *p_prev_event_list_item;
+	cl_list_item_t *p_list_next_item;
+	cl_event_wheel_reg_info_t *p_event;
+	uint64_t current_time;
+	uint64_t next_aging_time;
+	uint32_t new_timeout;
+	cl_status_t cl_status;
+
+	/* might be during closing ...  */
+	if (p_event_wheel->closing)
+		return;
+
+	current_time = cl_get_time_stamp();
+
+	if (NULL != p_event_wheel->p_external_lock)
+
+		/* Take care of the order of acquiring locks to avoid the deadlock!
+		 * The external lock goes first.
+		 */
+		cl_spinlock_acquire(p_event_wheel->p_external_lock);
+
+	cl_spinlock_acquire(&p_event_wheel->lock);
+
+	p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+	if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+		/* the list is empty - nothing to do */
+		goto Exit;
+
+	/* we found such an item.  get the p_event */
+	p_event =
+	    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+	while (p_event->aging_time <= current_time) {
+		/* this object has aged - invoke it's callback */
+		if (p_event->pfn_aged_callback)
+			next_aging_time =
+			    p_event->pfn_aged_callback(p_event->key,
+						       p_event->num_regs,
+						       p_event->context);
+		else
+			next_aging_time = 0;
+
+		/* point to the next object in the wheel */
+		p_list_next_item = cl_qlist_next(p_list_item);
+
+		/* We need to retire the event if the next aging time passed */
+		if (next_aging_time < current_time) {
+			/* remove it from the map */
+			cl_qmap_remove_item(&p_event_wheel->events_map,
+					    &(p_event->map_item));
+
+			/* pop p_event from the wheel */
+			cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+			/* delete the event info object - allocated by cl_event_wheel_reg */
+			free(p_event);
+		} else {
+			/* update the required aging time */
+			p_event->aging_time = next_aging_time;
+			p_event->num_regs++;
+
+			/* do not remove from the map  - but remove from the list head and
+			   place in the correct position */
+
+			/* pop p_event from the wheel */
+			cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+			/* find the event that ages just before */
+			p_prev_event_list_item =
+			    cl_qlist_find_from_tail(&p_event_wheel->
+						    events_wheel,
+						    __event_will_age_before,
+						    &p_event->aging_time);
+
+			/* insert just after */
+			cl_qlist_insert_next(&p_event_wheel->events_wheel,
+					     p_prev_event_list_item,
+					     &p_event->list_item);
+
+			/* as we have modified the list - restart from first item: */
+			p_list_next_item =
+			    cl_qlist_head(&p_event_wheel->events_wheel);
+		}
+
+		/* advance to next event */
+		p_list_item = p_list_next_item;
+		if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+			/* the list is empty - nothing to do */
+			break;
+
+		/* get the p_event */
+		p_event =
+		    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t,
+				  list_item);
+	}
+
+	/* We need to restart the timer only if the list is not empty now */
+	if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) {
+		/* get the p_event */
+		p_event =
+		    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t,
+				  list_item);
+
+		/* start the timer to the timeout [msec] */
+		new_timeout =
+		    (uint32_t) (((p_event->aging_time - current_time) / 1000) +
+				0.5);
+		CL_DBG("__cl_event_wheel_callback: Restart timer in: "
+		       "%u [msec]\n", new_timeout);
+		cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout);
+		if (cl_status != CL_SUCCESS) {
+			CL_DBG("__cl_event_wheel_callback : ERR 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);
+}
+
+/*
+ * Construct and Initialize
+ */
+void cl_event_wheel_construct(IN cl_event_wheel_t * const p_event_wheel)
+{
+	cl_spinlock_construct(&(p_event_wheel->lock));
+	cl_timer_construct(&(p_event_wheel->timer));
+}
+
+cl_status_t
+cl_event_wheel_init(IN cl_event_wheel_t * const p_event_wheel)
+{
+	cl_status_t cl_status = CL_SUCCESS;
+
+	/* initialize */
+	p_event_wheel->p_external_lock = NULL;
+	p_event_wheel->closing = FALSE;
+	cl_status = cl_spinlock_init(&(p_event_wheel->lock));
+	if (cl_status != CL_SUCCESS)
+		return cl_status;
+	cl_qlist_init(&p_event_wheel->events_wheel);
+	cl_qmap_init(&p_event_wheel->events_map);
+
+	/* init the timer with timeout */
+	cl_status = cl_timer_init(&p_event_wheel->timer, __cl_event_wheel_callback, p_event_wheel);	/* cb context */
+
+	return cl_status;
+}
+
+cl_status_t
+cl_event_wheel_init_ex(IN cl_event_wheel_t * const p_event_wheel,
+		       IN cl_spinlock_t * p_external_lock)
+{
+	cl_status_t cl_status;
+
+	cl_status = cl_event_wheel_init(p_event_wheel);
+	if (CL_SUCCESS != cl_status)
+		return cl_status;
+
+	p_event_wheel->p_external_lock = p_external_lock;
+	return cl_status;
+}
+
+void cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel)
+{
+	cl_list_item_t *p_list_item;
+	cl_event_wheel_reg_info_t *p_event;
+
+	p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+
+	while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) {
+		p_event =
+		    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t,
+				  list_item);
+		CL_DBG("cl_event_wheel_dump: Found event key:<0x%"
+		       PRIx64 ">, aging time:%" PRIu64 "\n",
+		       p_event->key, p_event->aging_time);
+		p_list_item = cl_qlist_next(p_list_item);
+	}
+}
+
+void cl_event_wheel_destroy(IN cl_event_wheel_t * const p_event_wheel)
+{
+	cl_list_item_t *p_list_item;
+	cl_map_item_t *p_map_item;
+	cl_event_wheel_reg_info_t *p_event;
+
+	/* we need to get a lock */
+	cl_spinlock_acquire(&p_event_wheel->lock);
+
+	cl_event_wheel_dump(p_event_wheel);
+
+	/* go over all the items in the list and remove them */
+	p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel);
+	while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) {
+		p_event =
+		    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t,
+				  list_item);
+
+		CL_DBG("cl_event_wheel_destroy: Found outstanding event"
+		       " key:<0x%" PRIx64 ">\n", p_event->key);
+
+		/* remove it from the map */
+		p_map_item = &(p_event->map_item);
+		cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item);
+		free(p_event);	/* allocated by cl_event_wheel_reg */
+		p_list_item =
+		    cl_qlist_remove_head(&p_event_wheel->events_wheel);
+	}
+
+	/* destroy the timer */
+	cl_timer_destroy(&p_event_wheel->timer);
+
+	/* destroy the lock (this should be done without releasing - we don't want
+	   any other run to grab the lock at this point. */
+	cl_spinlock_release(&p_event_wheel->lock);
+	cl_spinlock_destroy(&(p_event_wheel->lock));
+}
+
+cl_status_t
+cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel,
+		   IN const uint64_t key,
+		   IN const uint64_t aging_time_usec,
+		   IN cl_pfn_event_aged_cb_t pfn_callback,
+		   IN void *const context)
+{
+	cl_event_wheel_reg_info_t *p_event;
+	uint64_t timeout;
+	uint32_t to;
+	cl_status_t cl_status = CL_SUCCESS;
+	cl_list_item_t *prev_event_list_item;
+	cl_map_item_t *p_map_item;
+
+	/* Get the lock on the manager */
+	cl_spinlock_acquire(&(p_event_wheel->lock));
+
+	cl_event_wheel_dump(p_event_wheel);
+
+	/* Make sure such a key does not exists */
+	p_map_item = cl_qmap_get(&p_event_wheel->events_map, key);
+	if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) {
+		CL_DBG("cl_event_wheel_reg: Already exists key:0x%"
+		       PRIx64 "\n", key);
+
+		/* already there - remove it from the list as it is getting a new time */
+		p_event =
+		    PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t,
+				  map_item);
+
+		/* remove the item from the qlist */
+		cl_qlist_remove_item(&p_event_wheel->events_wheel,
+				     &p_event->list_item);
+		/* and the qmap */
+		cl_qmap_remove_item(&p_event_wheel->events_map,
+				    &p_event->map_item);
+	} else {
+		/* make a new one */
+		p_event = (cl_event_wheel_reg_info_t *)
+		    malloc(sizeof(cl_event_wheel_reg_info_t));
+		p_event->num_regs = 0;
+	}
+
+	p_event->key = key;
+	p_event->aging_time = aging_time_usec;
+	p_event->pfn_aged_callback = pfn_callback;
+	p_event->context = context;
+	p_event->num_regs++;
+
+	CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64
+	       " aging in %u [msec]\n", p_event->key,
+	       (uint32_t) ((p_event->aging_time -
+			    cl_get_time_stamp()) / 1000));
+
+	/* If the list is empty - need to start the timer */
+	if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) {
+		/* Edward Bortnikov 03/29/2003
+		 * ++TBD Consider moving the timer manipulation behind the list manipulation.
+		 */
+
+		/* calculate the new timeout */
+		timeout =
+		    (p_event->aging_time - cl_get_time_stamp() + 500) / 1000;
+
+		/* stop the timer if it is running */
+
+		/* Edward Bortnikov 03/29/2003
+		 * Don't call cl_timer_stop() because it spins forever.
+		 * cl_timer_start() will invoke cl_timer_stop() by itself.
+		 *
+		 * The problematic scenario is when __cl_event_wheel_callback()
+		 * is in race condition with this code. It sets timer.in_timer_cb
+		 * to TRUE and then blocks on p_event_wheel->lock. Following this,
+		 * the call to cl_timer_stop() hangs. Following this, the whole system
+		 * enters into a deadlock.
+		 *
+		 * cl_timer_stop(&p_event_wheel->timer);
+		 */
+
+		/* The timeout for the cl_timer_start should be given as uint32_t.
+		   if there is an overflow - warn about it. */
+		to = (uint32_t) timeout;
+		if (timeout > (uint32_t) timeout) {
+			to = 0xffffffff;	/* max 32 bit timer */
+			CL_DBG("cl_event_wheel_reg: timeout requested is "
+			       "too large. Using timeout: %u\n", to);
+		}
+
+		/* start the timer to the timeout [msec] */
+		cl_status = cl_timer_start(&p_event_wheel->timer, to);
+		if (cl_status != CL_SUCCESS) {
+			CL_DBG("cl_event_wheel_reg : ERR 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);
+
+	return cl_status;
+}
+
+void
+cl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key)
+{
+	cl_event_wheel_reg_info_t *p_event;
+	cl_map_item_t *p_map_item;
+
+	CL_DBG("cl_event_wheel_unreg: " "Removing key:0x%" PRIx64 "\n", key);
+
+	cl_spinlock_acquire(&p_event_wheel->lock);
+	p_map_item = cl_qmap_get(&p_event_wheel->events_map, key);
+	if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) {
+		/* we found such an item. */
+		p_event =
+		    PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t,
+				  map_item);
+
+		/* remove the item from the qlist */
+		cl_qlist_remove_item(&p_event_wheel->events_wheel,
+				     &(p_event->list_item));
+		/* remove the item from the qmap */
+		cl_qmap_remove_item(&p_event_wheel->events_map,
+				    &(p_event->map_item));
+
+		CL_DBG("cl_event_wheel_unreg: Removed key:0x%" PRIx64 "\n",
+		       key);
+
+		/* free the item */
+		free(p_event);
+	} else {
+		CL_DBG("cl_event_wheel_unreg: did not find key:0x%" PRIx64
+		       "\n", key);
+	}
+
+	cl_spinlock_release(&p_event_wheel->lock);
+}
+
+uint32_t
+cl_event_wheel_num_regs(IN cl_event_wheel_t * const p_event_wheel,
+			IN uint64_t key)
+{
+
+	cl_event_wheel_reg_info_t *p_event;
+	cl_map_item_t *p_map_item;
+	uint32_t num_regs = 0;
+
+	/* try to find the key in the map */
+	CL_DBG("cl_event_wheel_num_regs: Looking for key:0x%"
+	       PRIx64 "\n", key);
+
+	cl_spinlock_acquire(&p_event_wheel->lock);
+	p_map_item = cl_qmap_get(&p_event_wheel->events_map, key);
+	if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) {
+		/* ok so we can simply return it's num_regs */
+		p_event =
+		    PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t,
+				  map_item);
+		num_regs = p_event->num_regs;
+	}
+
+	cl_spinlock_release(&p_event_wheel->lock);
+	return (num_regs);
+}
+
+#ifdef __CL_EVENT_WHEEL_TEST__
+
+/* Dump out the complete state of the event wheel */
+void __cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel)
+{
+	cl_list_item_t *p_list_item;
+	cl_map_item_t *p_map_item;
+	cl_event_wheel_reg_info_t *p_event;
+
+	printf("************** Event Wheel Dump ***********************\n");
+	printf("Event Wheel List has %u items:\n",
+	       cl_qlist_count(&p_event_wheel->events_wheel));
+
+	p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+	while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) {
+		p_event =
+		    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t,
+				  list_item);
+		printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n",
+		       p_event->key, (char *)p_event->context,
+		       p_event->num_regs);
+
+		/* next */
+		p_list_item = cl_qlist_next(p_list_item);
+	}
+
+	printf("Event Map has %u items:\n",
+	       cl_qmap_count(&p_event_wheel->events_map));
+
+	p_map_item = cl_qmap_head(&p_event_wheel->events_map);
+	while (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) {
+		p_event =
+		    PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t,
+				  map_item);
+		printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n",
+		       p_event->key, (char *)p_event->context,
+		       p_event->num_regs);
+
+		/* next */
+		p_map_item = cl_qmap_next(p_map_item);
+	}
+
+}
+
+/* The callback for aging event */
+/* We assume we pass a text context */
+void __test_event_aging(uint64_t key, void *context)
+{
+	printf("*****************************************************\n");
+	printf("Aged key: 0x%" PRIx64 " Context:%s\n", key, (char *)context);
+}
+
+int main()
+{
+	cl_event_wheel_t event_wheel;
+	/*  uint64_t key; */
+
+	/* construct */
+	cl_event_wheel_construct(&event_wheel);
+
+	/* init */
+	cl_event_wheel_init(&event_wheel);
+
+	/* Start Playing */
+	cl_event_wheel_reg(&event_wheel, 1,	/*  key */
+			   cl_get_time_stamp() + 3000000,	/*  3 sec lifetime */
+			   __test_event_aging,	/*  cb */
+			   "The first Aging Event");
+
+	cl_event_wheel_reg(&event_wheel, 2,	/*  key */
+			   cl_get_time_stamp() + 3000000,	/*  3 sec lifetime */
+			   __test_event_aging,	/*  cb */
+			   "The Second Aging Event");
+
+	cl_event_wheel_reg(&event_wheel, 3,	/*  key */
+			   cl_get_time_stamp() + 3500000,	/*  3 sec lifetime */
+			   __test_event_aging,	/*  cb */
+			   "The Third Aging Event");
+
+	__cl_event_wheel_dump(&event_wheel);
+
+	sleep(2);
+	cl_event_wheel_reg(&event_wheel, 2,	/*  key */
+			   cl_get_time_stamp() + 8000000,	/*  3 sec lifetime */
+			   __test_event_aging,	/*  cb */
+			   "The Second Aging Event Moved");
+
+	__cl_event_wheel_dump(&event_wheel);
+
+	sleep(1);
+	/* remove the third event */
+	cl_event_wheel_unreg(&event_wheel, 3);	/*  key */
+
+	/* get the number of registrations for the keys */
+	printf("Event 1 Registered: %u\n",
+	       cl_event_wheel_num_regs(&event_wheel, 1));
+	printf("Event 2 Registered: %u\n",
+	       cl_event_wheel_num_regs(&event_wheel, 2));
+
+	sleep(5);
+	/* destroy */
+	cl_event_wheel_destroy(&event_wheel);
+
+	return (0);
+}
+
+#endif				/* __CL_EVENT_WHEEL_TEST__ */
diff --git a/complib/cl_list.c b/complib/cl_list.c
new file mode 100644
index 0000000..8129c61
--- /dev/null
+++ b/complib/cl_list.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation of quick list, and list.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_qlist.h>
+#include <complib/cl_list.h>
+
+#define FREE_ITEM_GROW_SIZE		10
+
+/******************************************************************************
+*******************************************************************************
+**************													   ************
+**************			 IMPLEMENTATION OF QUICK LIST			   ************
+**************													   ************
+*******************************************************************************
+******************************************************************************/
+void
+cl_qlist_insert_array_head(IN cl_qlist_t * const p_list,
+			   IN cl_list_item_t * const p_array,
+			   IN uint32_t item_count, IN const uint32_t item_size)
+{
+	cl_list_item_t *p_item;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_array);
+	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
+	CL_ASSERT(item_count);
+
+	/*
+	 * To add items from the array to the list in the same order as
+	 * the elements appear in the array, we add them starting with
+	 * the last one first.  Locate the last item.
+	 */
+	p_item = (cl_list_item_t *) ((uint8_t *) p_array +
+				     (item_size * (item_count - 1)));
+
+	/* Continue to add all items to the list. */
+	while (item_count--) {
+		cl_qlist_insert_head(p_list, p_item);
+
+		/* Get the next object to add to the list. */
+		p_item = (cl_list_item_t *) ((uint8_t *) p_item - item_size);
+	}
+}
+
+void
+cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list,
+			   IN cl_list_item_t * const p_array,
+			   IN uint32_t item_count, IN const uint32_t item_size)
+{
+	cl_list_item_t *p_item;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_array);
+	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
+	CL_ASSERT(item_count);
+
+	/* Set the first item to add to the list. */
+	p_item = p_array;
+
+	/* Continue to add all items to the list. */
+	while (item_count--) {
+		cl_qlist_insert_tail(p_list, p_item);
+
+		/* Get the next object to add to the list. */
+		p_item = (cl_list_item_t *) ((uint8_t *) p_item + item_size);
+	}
+}
+
+void
+cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list,
+			  IN cl_qlist_t * const p_src_list)
+{
+#if defined( _DEBUG_ )
+	cl_list_item_t *p_item;
+#endif
+
+	CL_ASSERT(p_dest_list);
+	CL_ASSERT(p_src_list);
+	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
+
+	/*
+	 * Is the src list empty?
+	 * We must have this check here for code below to work.
+	 */
+	if (cl_is_qlist_empty(p_src_list))
+		return;
+
+#if defined( _DEBUG_ )
+	/* Check that all items in the source list belong there. */
+	p_item = cl_qlist_head(p_src_list);
+	while (p_item != cl_qlist_end(p_src_list)) {
+		/* All list items in the source list must point to it. */
+		CL_ASSERT(p_item->p_list == p_src_list);
+		/* Point them all to the destination list. */
+		p_item->p_list = p_dest_list;
+		p_item = cl_qlist_next(p_item);
+	}
+#endif
+
+	/* Chain the destination list to the tail of the source list. */
+	cl_qlist_tail(p_src_list)->p_next = cl_qlist_head(p_dest_list);
+	cl_qlist_head(p_dest_list)->p_prev = cl_qlist_tail(p_src_list);
+
+	/*
+	 * Update the head of the destination list to the head of
+	 * the source list.
+	 */
+	p_dest_list->end.p_next = cl_qlist_head(p_src_list);
+	cl_qlist_head(p_src_list)->p_prev = &p_dest_list->end;
+
+	/*
+	 * Update the count of the destination to reflect the source items having
+	 * been added.
+	 */
+	p_dest_list->count += p_src_list->count;
+
+	/* Update source list to reflect being empty. */
+	__cl_qlist_reset(p_src_list);
+}
+
+void
+cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list,
+			  IN cl_qlist_t * const p_src_list)
+{
+#if defined( _DEBUG_ )
+	cl_list_item_t *p_item;
+#endif
+
+	CL_ASSERT(p_dest_list);
+	CL_ASSERT(p_src_list);
+	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
+
+	/*
+	 * Is the src list empty?
+	 * We must have this check here for code below to work.
+	 */
+	if (cl_is_qlist_empty(p_src_list))
+		return;
+
+#if defined( _DEBUG_ )
+	/* Check that all items in the source list belong there. */
+	p_item = cl_qlist_head(p_src_list);
+	while (p_item != cl_qlist_end(p_src_list)) {
+		/* All list items in the source list must point to it. */
+		CL_ASSERT(p_item->p_list == p_src_list);
+		/* Point them all to the destination list. */
+		p_item->p_list = p_dest_list;
+		p_item = cl_qlist_next(p_item);
+	}
+#endif
+
+	/* Chain the source list to the tail of the destination list. */
+	cl_qlist_tail(p_dest_list)->p_next = cl_qlist_head(p_src_list);
+	cl_qlist_head(p_src_list)->p_prev = cl_qlist_tail(p_dest_list);
+
+	/*
+	 * Update the tail of the destination list to the tail of
+	 * the source list.
+	 */
+	p_dest_list->end.p_prev = cl_qlist_tail(p_src_list);
+	cl_qlist_tail(p_src_list)->p_next = &p_dest_list->end;
+
+	/*
+	 * Update the count of the destination to reflect the source items having
+	 * been added.
+	 */
+	p_dest_list->count += p_src_list->count;
+
+	/* Update source list to reflect being empty. */
+	__cl_qlist_reset(p_src_list);
+}
+
+boolean_t
+cl_is_item_in_qlist(IN const cl_qlist_t * const p_list,
+		    IN const cl_list_item_t * const p_list_item)
+{
+	const cl_list_item_t *p_temp;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list_item);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	/* Traverse looking for a match */
+	p_temp = cl_qlist_head(p_list);
+	while (p_temp != cl_qlist_end(p_list)) {
+		if (p_temp == p_list_item) {
+			CL_ASSERT(p_list_item->p_list == p_list);
+			return (TRUE);
+		}
+
+		p_temp = cl_qlist_next(p_temp);
+	}
+
+	return (FALSE);
+}
+
+cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list,
+				   IN const cl_list_item_t * const p_list_item,
+				   IN cl_pfn_qlist_find_t pfn_func,
+				   IN const void *const context)
+{
+	cl_list_item_t *p_found_item;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_list_item);
+	CL_ASSERT(p_list_item->p_list == p_list);
+	CL_ASSERT(pfn_func);
+
+	p_found_item = cl_qlist_next(p_list_item);
+
+	/* The user provided a compare function */
+	while (p_found_item != cl_qlist_end(p_list)) {
+		CL_ASSERT(p_found_item->p_list == p_list);
+
+		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
+			break;
+
+		p_found_item = cl_qlist_next(p_found_item);
+	}
+
+	/* No match */
+	return (p_found_item);
+}
+
+cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list,
+				   IN const cl_list_item_t * const p_list_item,
+				   IN cl_pfn_qlist_find_t pfn_func,
+				   IN const void *const context)
+{
+	cl_list_item_t *p_found_item;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_list_item);
+	CL_ASSERT(p_list_item->p_list == p_list);
+	CL_ASSERT(pfn_func);
+
+	p_found_item = cl_qlist_prev(p_list_item);
+
+	/* The user provided a compare function */
+	while (p_found_item != cl_qlist_end(p_list)) {
+		CL_ASSERT(p_found_item->p_list == p_list);
+
+		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
+			break;
+
+		p_found_item = cl_qlist_prev(p_found_item);
+	}
+
+	/* No match */
+	return (p_found_item);
+}
+
+void
+cl_qlist_apply_func(IN const cl_qlist_t * const p_list,
+		    IN cl_pfn_qlist_apply_t pfn_func,
+		    IN const void *const context)
+{
+	cl_list_item_t *p_list_item;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_func);
+
+	p_list_item = cl_qlist_head(p_list);
+	while (p_list_item != cl_qlist_end(p_list)) {
+		pfn_func(p_list_item, (void *)context);
+		p_list_item = cl_qlist_next(p_list_item);
+	}
+}
+
+void
+cl_qlist_move_items(IN cl_qlist_t * const p_src_list,
+		    IN cl_qlist_t * const p_dest_list,
+		    IN cl_pfn_qlist_find_t pfn_func,
+		    IN const void *const context)
+{
+	cl_list_item_t *p_current_item, *p_next;
+
+	CL_ASSERT(p_src_list);
+	CL_ASSERT(p_dest_list);
+	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_func);
+
+	p_current_item = cl_qlist_head(p_src_list);
+
+	while (p_current_item != cl_qlist_end(p_src_list)) {
+		/* Before we do anything, get a pointer to the next item. */
+		p_next = cl_qlist_next(p_current_item);
+
+		if (pfn_func(p_current_item, (void *)context) == CL_SUCCESS) {
+			/* Move the item from one list to the other. */
+			cl_qlist_remove_item(p_src_list, p_current_item);
+			cl_qlist_insert_tail(p_dest_list, p_current_item);
+		}
+		p_current_item = p_next;
+	}
+}
+
+/******************************************************************************
+*******************************************************************************
+**************													   ************
+**************			 IMPLEMENTATION OF LIST					   ************
+**************													   ************
+*******************************************************************************
+******************************************************************************/
+void cl_list_construct(IN cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+
+	cl_qpool_construct(&p_list->list_item_pool);
+}
+
+cl_status_t cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items)
+{
+	uint32_t grow_size;
+
+	CL_ASSERT(p_list);
+	cl_qlist_init(&p_list->list);
+
+	/*
+	 * We will grow by min_items/8 items at a time, with a minimum of
+	 * FREE_ITEM_GROW_SIZE.
+	 */
+	grow_size = (uint32_t) min_items >> 3;
+	if (grow_size < FREE_ITEM_GROW_SIZE)
+		grow_size = FREE_ITEM_GROW_SIZE;
+
+	/* Initialize the pool of list items. */
+	return (cl_qpool_init(&p_list->list_item_pool, min_items, 0, grow_size,
+			      sizeof(cl_pool_obj_t), NULL, NULL, NULL));
+}
+
+void cl_list_destroy(IN cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+
+	cl_qpool_destroy(&p_list->list_item_pool);
+}
+
+static cl_status_t
+cl_list_find_cb(IN const cl_list_item_t * const p_list_item,
+		IN void *const context)
+{
+	CL_ASSERT(p_list_item);
+
+	if (cl_list_obj(p_list_item) == context)
+		return (CL_SUCCESS);
+
+	return (CL_NOT_FOUND);
+}
+
+cl_status_t
+cl_list_remove_object(IN cl_list_t * const p_list,
+		      IN const void *const p_object)
+{
+	cl_list_item_t *p_list_item;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* find the item in question */
+	p_list_item =
+	    cl_qlist_find_from_head(&p_list->list, cl_list_find_cb, p_object);
+	if (p_list_item != cl_qlist_end(&p_list->list)) {
+		/* remove this item */
+		cl_qlist_remove_item(&p_list->list, p_list_item);
+		cl_qpool_put(&p_list->list_item_pool,
+			     (cl_pool_item_t *) p_list_item);
+		return (CL_SUCCESS);
+	}
+	return (CL_NOT_FOUND);
+}
+
+boolean_t
+cl_is_object_in_list(IN const cl_list_t * const p_list,
+		     IN const void *const p_object)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	return (cl_qlist_find_from_head
+		(&p_list->list, cl_list_find_cb, p_object)
+		!= cl_qlist_end(&p_list->list));
+}
+
+cl_status_t
+cl_list_insert_array_head(IN cl_list_t * const p_list,
+			  IN const void *const p_array,
+			  IN uint32_t item_count, IN const uint32_t item_size)
+{
+	cl_status_t status;
+	void *p_object;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	CL_ASSERT(p_array);
+	CL_ASSERT(item_size);
+	CL_ASSERT(item_count);
+
+	/*
+	 * To add items from the array to the list in the same order as
+	 * the elements appear in the array, we add them starting with
+	 * the last one first.  Locate the last item.
+	 */
+	p_object = ((uint8_t *) p_array + (item_size * (item_count - 1)));
+
+	/* Continue to add all items to the list. */
+	while (item_count--) {
+		status = cl_list_insert_head(p_list, p_object);
+		if (status != CL_SUCCESS) {
+			/* Remove all items that have been inserted. */
+			while (item_count++ < item_count)
+				cl_list_remove_head(p_list);
+			return (status);
+		}
+
+		/* Get the next object to add to the list. */
+		p_object = ((uint8_t *) p_object - item_size);
+	}
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_list_insert_array_tail(IN cl_list_t * const p_list,
+			  IN const void *const p_array,
+			  IN uint32_t item_count, IN const uint32_t item_size)
+{
+	cl_status_t status;
+	void *p_object;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	CL_ASSERT(p_array);
+	CL_ASSERT(item_size);
+	CL_ASSERT(item_count);
+
+	/* Set the first item to add to the list. */
+	p_object = (void *)p_array;
+
+	/* Continue to add all items to the list. */
+	while (item_count--) {
+		status = cl_list_insert_tail(p_list, p_object);
+		if (status != CL_SUCCESS) {
+			/* Remove all items that have been inserted. */
+			while (item_count++ < item_count)
+				cl_list_remove_tail(p_list);
+			return (status);
+		}
+
+		/* Get the next object to add to the list. */
+		p_object = ((uint8_t *) p_object + item_size);
+	}
+
+	return (CL_SUCCESS);
+}
+
+cl_list_iterator_t
+cl_list_find_from_head(IN const cl_list_t * const p_list,
+		       IN cl_pfn_list_find_t pfn_func,
+		       IN const void *const context)
+{
+	cl_status_t status;
+	cl_list_iterator_t itor;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	CL_ASSERT(pfn_func);
+
+	itor = cl_list_head(p_list);
+
+	while (itor != cl_list_end(p_list)) {
+		status = pfn_func(cl_list_obj(itor), (void *)context);
+		if (status == CL_SUCCESS)
+			break;
+
+		itor = cl_list_next(itor);
+	}
+
+	/* no match */
+	return (itor);
+}
+
+cl_list_iterator_t
+cl_list_find_from_tail(IN const cl_list_t * const p_list,
+		       IN cl_pfn_list_find_t pfn_func,
+		       IN const void *const context)
+{
+	cl_status_t status;
+	cl_list_iterator_t itor;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	CL_ASSERT(pfn_func);
+
+	itor = cl_list_tail(p_list);
+
+	while (itor != cl_list_end(p_list)) {
+		status = pfn_func(cl_list_obj(itor), (void *)context);
+		if (status == CL_SUCCESS)
+			break;
+
+		itor = cl_list_prev(itor);
+	}
+
+	/* no match */
+	return (itor);
+}
+
+void
+cl_list_apply_func(IN const cl_list_t * const p_list,
+		   IN cl_pfn_list_apply_t pfn_func,
+		   IN const void *const context)
+{
+	cl_list_iterator_t itor;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	CL_ASSERT(pfn_func);
+
+	itor = cl_list_head(p_list);
+
+	while (itor != cl_list_end(p_list)) {
+		pfn_func(cl_list_obj(itor), (void *)context);
+
+		itor = cl_list_next(itor);
+	}
+}
diff --git a/complib/cl_log.c b/complib/cl_log.c
new file mode 100644
index 0000000..a2a1372
--- /dev/null
+++ b/complib/cl_log.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef __WIN__
+#pragma warning(disable : 4996)
+#endif
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_log.h>
+#include <complib/cl_debug.h>
+#include <syslog.h>
+
+/* Maximum number of bytes that can be logged. */
+#define CL_MAX_LOG_DATA		(256)
+
+/*
+ * Size of the character buffer to allow logging the above
+ * number of bytes.  A space is added after every DWORD, and
+ * a new line is added after 8 DWORDS (for a line length less than 80).
+ */
+#define CL_LOG_DATA_SIZE	(CL_MAX_LOG_DATA + (CL_MAX_LOG_DATA/4))
+
+void
+cl_log_event(IN const char *const name,
+	     IN const cl_log_type_t type,
+	     IN const char *const message,
+	     IN const void *const p_data OPTIONAL, IN const uint32_t data_len)
+{
+	int priority, i;
+	char data[CL_LOG_DATA_SIZE];
+	char *p_buf;
+	uint8_t *p_int_data = (uint8_t *) p_data;
+
+	CL_ASSERT(name);
+	CL_ASSERT(message);
+
+	openlog(name, LOG_NDELAY | LOG_PID, LOG_USER);
+	switch (type) {
+	case CL_LOG_ERROR:
+		priority = LOG_ERR;
+		break;
+
+	case CL_LOG_WARN:
+		priority = LOG_WARNING;
+		break;
+
+	case CL_LOG_INFO:
+	default:
+		priority = LOG_INFO;
+		break;
+	}
+
+	if (p_data) {
+		CL_ASSERT(data_len);
+		if (data_len < CL_MAX_LOG_DATA) {
+			p_buf = data;
+			/* Format the data into ASCII. */
+			for (i = 0; i < data_len; i++) {
+				sprintf(p_buf, "%02x", *p_int_data++);
+				p_buf += 2;
+
+				/* Add line break after 8 DWORDS. */
+				if (i % 32) {
+					sprintf(p_buf++, "\n");
+					continue;
+				}
+
+				/* Add a space between DWORDS. */
+				if (i % 4)
+					sprintf(p_buf++, " ");
+			}
+			syslog(priority, "%s data:\n%s\n", message, p_buf);
+		} else {
+			/* The data portion is too large to log. */
+			cl_msg_out
+			    ("cl_log() - WARNING: data too large to log.\n");
+			syslog(priority, "%s\n", message);
+		}
+	} else {
+		syslog(priority, "%s\n", message);
+	}
+	closelog();
+}
diff --git a/complib/cl_map.c b/complib/cl_map.c
new file mode 100644
index 0000000..c0e44be
--- /dev/null
+++ b/complib/cl_map.c
@@ -0,0 +1,1636 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation of quick map, a binary tree where the caller always
+ *	provides all necessary storage.
+ *
+ */
+
+/*****************************************************************************
+*
+* Map
+*
+* Map is an associative array.  By providing a key, the caller can retrieve
+* an object from the map.  All objects in the map have an associated key,
+* as specified by the caller when the object was inserted into the map.
+* In addition to random access, the caller can traverse the map much like
+* a linked list, either forwards from the first object or backwards from
+* the last object.  The objects in the map are always traversed in
+* order since the nodes are stored sorted.
+*
+* This implementation of Map uses a red black tree verified against
+* Cormen-Leiserson-Rivest text, McGraw-Hill Edition, fourteenth
+* printing, 1994.
+*
+*****************************************************************************/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <complib/cl_fleximap.h>
+
+/******************************************************************************
+*******************************************************************************
+**************													   ************
+**************			 IMPLEMENTATION OF QUICK MAP			   ************
+**************													   ************
+*******************************************************************************
+******************************************************************************/
+
+/*
+ * Get the root.
+ */
+static inline cl_map_item_t *__cl_map_root(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (p_map->root.p_left);
+}
+
+/*
+ * Returns whether a given item is on the left of its parent.
+ */
+static boolean_t __cl_map_is_left_child(IN const cl_map_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_up);
+	CL_ASSERT(p_item->p_up != p_item);
+
+	return (p_item->p_up->p_left == p_item);
+}
+
+/*
+ * Retrieve the pointer to the parent's pointer to an item.
+ */
+static cl_map_item_t **__cl_map_get_parent_ptr_to_item(IN cl_map_item_t *
+						       const p_item)
+{
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_up);
+	CL_ASSERT(p_item->p_up != p_item);
+
+	if (__cl_map_is_left_child(p_item))
+		return (&p_item->p_up->p_left);
+
+	CL_ASSERT(p_item->p_up->p_right == p_item);
+	return (&p_item->p_up->p_right);
+}
+
+/*
+ * Rotate a node to the left.  This rotation affects the least number of links
+ * between nodes and brings the level of C up by one while increasing the depth
+ * of A one.  Note that the links to/from W, X, Y, and Z are not affected.
+ *
+ *	    R				      R
+ *	    |				      |
+ *	    A				      C
+ *	  /   \			        /   \
+ *	W       C			  A       Z
+ *	       / \			 / \
+ *	      B   Z			W   B
+ *	     / \			   / \
+ *	    X   Y			  X   Y
+ */
+static void
+__cl_map_rot_left(IN cl_qmap_t * const p_map, IN cl_map_item_t * const p_item)
+{
+	cl_map_item_t **pp_root;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_right != &p_map->nil);
+
+	pp_root = __cl_map_get_parent_ptr_to_item(p_item);
+
+	/* Point R to C instead of A. */
+	*pp_root = p_item->p_right;
+	/* Set C's parent to R. */
+	(*pp_root)->p_up = p_item->p_up;
+
+	/* Set A's right to B */
+	p_item->p_right = (*pp_root)->p_left;
+	/*
+	 * Set B's parent to A.  We trap for B being NIL since the
+	 * caller may depend on NIL not changing.
+	 */
+	if ((*pp_root)->p_left != &p_map->nil)
+		(*pp_root)->p_left->p_up = p_item;
+
+	/* Set C's left to A. */
+	(*pp_root)->p_left = p_item;
+	/* Set A's parent to C. */
+	p_item->p_up = *pp_root;
+}
+
+/*
+ * Rotate a node to the right.  This rotation affects the least number of links
+ * between nodes and brings the level of A up by one while increasing the depth
+ * of C one.  Note that the links to/from W, X, Y, and Z are not affected.
+ *
+ *	        R				     R
+ *	        |				     |
+ *	        C				     A
+ *	      /   \				   /   \
+ *	    A       Z			 W       C
+ *	   / \    				        / \
+ *	  W   B   				       B   Z
+ *	     / \				      / \
+ *	    X   Y				     X   Y
+ */
+static void
+__cl_map_rot_right(IN cl_qmap_t * const p_map, IN cl_map_item_t * const p_item)
+{
+	cl_map_item_t **pp_root;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_left != &p_map->nil);
+
+	/* Point R to A instead of C. */
+	pp_root = __cl_map_get_parent_ptr_to_item(p_item);
+	(*pp_root) = p_item->p_left;
+	/* Set A's parent to R. */
+	(*pp_root)->p_up = p_item->p_up;
+
+	/* Set C's left to B */
+	p_item->p_left = (*pp_root)->p_right;
+	/*
+	 * Set B's parent to C.  We trap for B being NIL since the
+	 * caller may depend on NIL not changing.
+	 */
+	if ((*pp_root)->p_right != &p_map->nil)
+		(*pp_root)->p_right->p_up = p_item;
+
+	/* Set A's right to C. */
+	(*pp_root)->p_right = p_item;
+	/* Set C's parent to A. */
+	p_item->p_up = *pp_root;
+}
+
+void cl_qmap_init(IN cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+
+	memset(p_map, 0, sizeof(cl_qmap_t));
+
+	/* special setup for the root node */
+	p_map->root.p_up = &p_map->root;
+	p_map->root.p_left = &p_map->nil;
+	p_map->root.p_right = &p_map->nil;
+	p_map->root.color = CL_MAP_BLACK;
+
+	/* Setup the node used as terminator for all leaves. */
+	p_map->nil.p_up = &p_map->nil;
+	p_map->nil.p_left = &p_map->nil;
+	p_map->nil.p_right = &p_map->nil;
+	p_map->nil.color = CL_MAP_BLACK;
+
+	p_map->state = CL_INITIALIZED;
+
+	cl_qmap_remove_all(p_map);
+}
+
+cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map,
+			   IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_item = __cl_map_root(p_map);
+
+	while (p_item != &p_map->nil) {
+		if (key == p_item->key)
+			break;	/* just right */
+
+		if (key < p_item->key)
+			p_item = p_item->p_left;	/* too small */
+		else
+			p_item = p_item->p_right;	/* too big */
+	}
+
+	return (p_item);
+}
+
+cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map,
+				IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+	cl_map_item_t *p_item_found;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_item = __cl_map_root(p_map);
+	p_item_found = (cl_map_item_t *) & p_map->nil;
+
+	while (p_item != &p_map->nil) {
+		if (key < p_item->key) {
+			p_item_found = p_item;
+			p_item = p_item->p_left;
+		} else {
+			p_item = p_item->p_right;
+		}
+	}
+
+	return (p_item_found);
+}
+
+void
+cl_qmap_apply_func(IN const cl_qmap_t * const p_map,
+		   IN cl_pfn_qmap_apply_t pfn_func,
+		   IN const void *const context)
+{
+	cl_map_item_t *p_map_item;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_func);
+
+	p_map_item = cl_qmap_head(p_map);
+	while (p_map_item != cl_qmap_end(p_map)) {
+		pfn_func(p_map_item, (void *)context);
+		p_map_item = cl_qmap_next(p_map_item);
+	}
+}
+
+/*
+ * Balance a tree starting at a given item back to the root.
+ */
+static void
+__cl_map_ins_bal(IN cl_qmap_t * const p_map, IN cl_map_item_t * p_item)
+{
+	cl_map_item_t *p_grand_uncle;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item != &p_map->root);
+
+	while (p_item->p_up->color == CL_MAP_RED) {
+		if (__cl_map_is_left_child(p_item->p_up)) {
+			p_grand_uncle = p_item->p_up->p_up->p_right;
+			CL_ASSERT(p_grand_uncle);
+			if (p_grand_uncle->color == CL_MAP_RED) {
+				p_grand_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_BLACK;
+				p_item->p_up->p_up->color = CL_MAP_RED;
+				p_item = p_item->p_up->p_up;
+				continue;
+			}
+
+			if (!__cl_map_is_left_child(p_item)) {
+				p_item = p_item->p_up;
+				__cl_map_rot_left(p_map, p_item);
+			}
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_item->p_up->p_up->color = CL_MAP_RED;
+			__cl_map_rot_right(p_map, p_item->p_up->p_up);
+		} else {
+			p_grand_uncle = p_item->p_up->p_up->p_left;
+			CL_ASSERT(p_grand_uncle);
+			if (p_grand_uncle->color == CL_MAP_RED) {
+				p_grand_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_BLACK;
+				p_item->p_up->p_up->color = CL_MAP_RED;
+				p_item = p_item->p_up->p_up;
+				continue;
+			}
+
+			if (__cl_map_is_left_child(p_item)) {
+				p_item = p_item->p_up;
+				__cl_map_rot_right(p_map, p_item);
+			}
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_item->p_up->p_up->color = CL_MAP_RED;
+			__cl_map_rot_left(p_map, p_item->p_up->p_up);
+		}
+	}
+}
+
+cl_map_item_t *cl_qmap_insert(IN cl_qmap_t * const p_map,
+			      IN const uint64_t key,
+			      IN cl_map_item_t * const p_item)
+{
+	cl_map_item_t *p_insert_at, *p_comp_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_map->root.p_up == &p_map->root);
+	CL_ASSERT(p_map->root.color != CL_MAP_RED);
+	CL_ASSERT(p_map->nil.color != CL_MAP_RED);
+
+	p_item->p_left = &p_map->nil;
+	p_item->p_right = &p_map->nil;
+	p_item->key = key;
+	p_item->color = CL_MAP_RED;
+
+	/* Find the insertion location. */
+	p_insert_at = &p_map->root;
+	p_comp_item = __cl_map_root(p_map);
+
+	while (p_comp_item != &p_map->nil) {
+		p_insert_at = p_comp_item;
+
+		if (key == p_insert_at->key)
+			return (p_insert_at);
+
+		/* Traverse the tree until the correct insertion point is found. */
+		if (key < p_insert_at->key)
+			p_comp_item = p_insert_at->p_left;
+		else
+			p_comp_item = p_insert_at->p_right;
+	}
+
+	CL_ASSERT(p_insert_at != &p_map->nil);
+	CL_ASSERT(p_comp_item == &p_map->nil);
+	/* Insert the item. */
+	if (p_insert_at == &p_map->root) {
+		p_insert_at->p_left = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(&p_map->nil.pool_item.list_item,
+				      &p_item->pool_item.list_item);
+	} else if (key < p_insert_at->key) {
+		p_insert_at->p_left = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(&p_insert_at->pool_item.list_item,
+				      &p_item->pool_item.list_item);
+	} else {
+		p_insert_at->p_right = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(p_insert_at->pool_item.list_item.p_next,
+				      &p_item->pool_item.list_item);
+	}
+	/* Increase the count. */
+	p_map->count++;
+
+	p_item->p_up = p_insert_at;
+
+	/*
+	 * We have added depth to this section of the tree.
+	 * Rebalance as necessary as we retrace our path through the tree
+	 * and update colors.
+	 */
+	__cl_map_ins_bal(p_map, p_item);
+
+	__cl_map_root(p_map)->color = CL_MAP_BLACK;
+
+	/*
+	 * Note that it is not necessary to re-color the nil node black because all
+	 * red color assignments are made via the p_up pointer, and nil is never
+	 * set as the value of a p_up pointer.
+	 */
+
+#ifdef _DEBUG_
+	/* Set the pointer to the map in the map item for consistency checking. */
+	p_item->p_map = p_map;
+#endif
+
+	return (p_item);
+}
+
+static void
+__cl_map_del_bal(IN cl_qmap_t * const p_map, IN cl_map_item_t * p_item)
+{
+	cl_map_item_t *p_uncle;
+
+	while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) {
+		if (__cl_map_is_left_child(p_item)) {
+			p_uncle = p_item->p_up->p_right;
+
+			if (p_uncle->color == CL_MAP_RED) {
+				p_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_RED;
+				__cl_map_rot_left(p_map, p_item->p_up);
+				p_uncle = p_item->p_up->p_right;
+			}
+
+			if (p_uncle->p_right->color != CL_MAP_RED) {
+				if (p_uncle->p_left->color != CL_MAP_RED) {
+					p_uncle->color = CL_MAP_RED;
+					p_item = p_item->p_up;
+					continue;
+				}
+
+				p_uncle->p_left->color = CL_MAP_BLACK;
+				p_uncle->color = CL_MAP_RED;
+				__cl_map_rot_right(p_map, p_uncle);
+				p_uncle = p_item->p_up->p_right;
+			}
+			p_uncle->color = p_item->p_up->color;
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_uncle->p_right->color = CL_MAP_BLACK;
+			__cl_map_rot_left(p_map, p_item->p_up);
+			break;
+		} else {
+			p_uncle = p_item->p_up->p_left;
+
+			if (p_uncle->color == CL_MAP_RED) {
+				p_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_RED;
+				__cl_map_rot_right(p_map, p_item->p_up);
+				p_uncle = p_item->p_up->p_left;
+			}
+
+			if (p_uncle->p_left->color != CL_MAP_RED) {
+				if (p_uncle->p_right->color != CL_MAP_RED) {
+					p_uncle->color = CL_MAP_RED;
+					p_item = p_item->p_up;
+					continue;
+				}
+
+				p_uncle->p_right->color = CL_MAP_BLACK;
+				p_uncle->color = CL_MAP_RED;
+				__cl_map_rot_left(p_map, p_uncle);
+				p_uncle = p_item->p_up->p_left;
+			}
+			p_uncle->color = p_item->p_up->color;
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_uncle->p_left->color = CL_MAP_BLACK;
+			__cl_map_rot_right(p_map, p_item->p_up);
+			break;
+		}
+	}
+	p_item->color = CL_MAP_BLACK;
+}
+
+void
+cl_qmap_remove_item(IN cl_qmap_t * const p_map, IN cl_map_item_t * const p_item)
+{
+	cl_map_item_t *p_child, *p_del_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(p_item);
+
+	if (p_item == cl_qmap_end(p_map))
+		return;
+
+	/* must be checked after comparing to cl_qmap_end, since
+	   the end is not a valid item. */
+	CL_ASSERT(p_item->p_map == p_map);
+
+	if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) {
+		/* The item being removed has children on at most on side. */
+		p_del_item = p_item;
+	} else {
+		/*
+		 * The item being removed has children on both side.
+		 * We select the item that will replace it.  After removing
+		 * the substitute item and rebalancing, the tree will have the
+		 * correct topology.  Exchanging the substitute for the item
+		 * will finalize the removal.
+		 */
+		p_del_item = cl_qmap_next(p_item);
+		CL_ASSERT(p_del_item != &p_map->nil);
+	}
+
+	/* Remove the item from the list. */
+	__cl_primitive_remove(&p_item->pool_item.list_item);
+	/* Decrement the item count. */
+	p_map->count--;
+
+	/* Get the pointer to the new root's child, if any. */
+	if (p_del_item->p_left != &p_map->nil)
+		p_child = p_del_item->p_left;
+	else
+		p_child = p_del_item->p_right;
+
+	/*
+	 * This assignment may modify the parent pointer of the nil node.
+	 * This is inconsequential.
+	 */
+	p_child->p_up = p_del_item->p_up;
+	(*__cl_map_get_parent_ptr_to_item(p_del_item)) = p_child;
+
+	if (p_del_item->color != CL_MAP_RED)
+		__cl_map_del_bal(p_map, p_child);
+
+	/*
+	 * Note that the splicing done below does not need to occur before
+	 * the tree is balanced, since the actual topology changes are made by the
+	 * preceding code.  The topology is preserved by the color assignment made
+	 * below (reader should be reminded that p_del_item == p_item in some cases).
+	 */
+	if (p_del_item != p_item) {
+		/*
+		 * Finalize the removal of the specified item by exchanging it with
+		 * the substitute which we removed above.
+		 */
+		p_del_item->p_up = p_item->p_up;
+		p_del_item->p_left = p_item->p_left;
+		p_del_item->p_right = p_item->p_right;
+		(*__cl_map_get_parent_ptr_to_item(p_item)) = p_del_item;
+		p_item->p_right->p_up = p_del_item;
+		p_item->p_left->p_up = p_del_item;
+		p_del_item->color = p_item->color;
+	}
+
+	CL_ASSERT(p_map->nil.color != CL_MAP_RED);
+
+#ifdef _DEBUG_
+	/* Clear the pointer to the map since the item has been removed. */
+	p_item->p_map = NULL;
+#endif
+}
+
+cl_map_item_t *cl_qmap_remove(IN cl_qmap_t * const p_map, IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	/* Seek the node with the specified key */
+	p_item = cl_qmap_get(p_map, key);
+
+	cl_qmap_remove_item(p_map, p_item);
+
+	return (p_item);
+}
+
+void
+cl_qmap_merge(OUT cl_qmap_t * const p_dest_map,
+	      IN OUT cl_qmap_t * const p_src_map)
+{
+	cl_map_item_t *p_item, *p_item2, *p_next;
+
+	CL_ASSERT(p_dest_map);
+	CL_ASSERT(p_src_map);
+
+	p_item = cl_qmap_head(p_src_map);
+
+	while (p_item != cl_qmap_end(p_src_map)) {
+		p_next = cl_qmap_next(p_item);
+
+		/* Remove the item from its current map. */
+		cl_qmap_remove_item(p_src_map, p_item);
+		/* Insert the item into the destination map. */
+		p_item2 =
+		    cl_qmap_insert(p_dest_map, cl_qmap_key(p_item), p_item);
+		/* Check that the item was successfully inserted. */
+		if (p_item2 != p_item) {
+			/* Put the item in back in the source map. */
+			p_item2 =
+			    cl_qmap_insert(p_src_map, cl_qmap_key(p_item),
+					   p_item);
+			CL_ASSERT(p_item2 == p_item);
+		}
+		p_item = p_next;
+	}
+}
+
+static void
+__cl_qmap_delta_move(IN OUT cl_qmap_t * const p_dest,
+		     IN OUT cl_qmap_t * const p_src,
+		     IN OUT cl_map_item_t ** const pp_item)
+{
+	cl_map_item_t *p_temp, *p_next;
+
+	/*
+	 * Get the next item so that we can ensure that pp_item points to
+	 * a valid item upon return from the function.
+	 */
+	p_next = cl_qmap_next(*pp_item);
+	/* Move the old item from its current map the the old map. */
+	cl_qmap_remove_item(p_src, *pp_item);
+	p_temp = cl_qmap_insert(p_dest, cl_qmap_key(*pp_item), *pp_item);
+	/* We should never have duplicates. */
+	CL_ASSERT(p_temp == *pp_item);
+	/* Point pp_item to a valid item in the source map. */
+	(*pp_item) = p_next;
+}
+
+void
+cl_qmap_delta(IN OUT cl_qmap_t * const p_map1,
+	      IN OUT cl_qmap_t * const p_map2,
+	      OUT cl_qmap_t * const p_new, OUT cl_qmap_t * const p_old)
+{
+	cl_map_item_t *p_item1, *p_item2;
+	uint64_t key1, key2;
+
+	CL_ASSERT(p_map1);
+	CL_ASSERT(p_map2);
+	CL_ASSERT(p_new);
+	CL_ASSERT(p_old);
+	CL_ASSERT(cl_is_qmap_empty(p_new));
+	CL_ASSERT(cl_is_qmap_empty(p_old));
+
+	p_item1 = cl_qmap_head(p_map1);
+	p_item2 = cl_qmap_head(p_map2);
+
+	while (p_item1 != cl_qmap_end(p_map1) && p_item2 != cl_qmap_end(p_map2)) {
+		key1 = cl_qmap_key(p_item1);
+		key2 = cl_qmap_key(p_item2);
+		if (key1 < key2) {
+			/* We found an old item. */
+			__cl_qmap_delta_move(p_old, p_map1, &p_item1);
+		} else if (key1 > key2) {
+			/* We found a new item. */
+			__cl_qmap_delta_move(p_new, p_map2, &p_item2);
+		} else {
+			/* Move both forward since they have the same key. */
+			p_item1 = cl_qmap_next(p_item1);
+			p_item2 = cl_qmap_next(p_item2);
+		}
+	}
+
+	/* Process the remainder if the end of either source map was reached. */
+	while (p_item2 != cl_qmap_end(p_map2))
+		__cl_qmap_delta_move(p_new, p_map2, &p_item2);
+
+	while (p_item1 != cl_qmap_end(p_map1))
+		__cl_qmap_delta_move(p_old, p_map1, &p_item1);
+}
+
+/******************************************************************************
+*******************************************************************************
+**************													   ************
+**************				IMPLEMENTATION OF MAP				   ************
+**************													   ************
+*******************************************************************************
+******************************************************************************/
+
+#define MAP_GROW_SIZE 32
+
+void cl_map_construct(IN cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+
+	cl_qpool_construct(&p_map->pool);
+}
+
+cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items)
+{
+	uint32_t grow_size;
+
+	CL_ASSERT(p_map);
+
+	cl_qmap_init(&p_map->qmap);
+
+	/*
+	 * We will grow by min_items/8 items at a time, with a minimum of
+	 * MAP_GROW_SIZE.
+	 */
+	grow_size = min_items >> 3;
+	if (grow_size < MAP_GROW_SIZE)
+		grow_size = MAP_GROW_SIZE;
+
+	return (cl_qpool_init(&p_map->pool, min_items, 0, grow_size,
+			      sizeof(cl_map_obj_t), NULL, NULL, NULL));
+}
+
+void cl_map_destroy(IN cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+
+	cl_qpool_destroy(&p_map->pool);
+}
+
+void *cl_map_insert(IN cl_map_t * const p_map,
+		    IN const uint64_t key, IN const void *const p_object)
+{
+	cl_map_obj_t *p_map_obj, *p_obj_at_key;
+
+	CL_ASSERT(p_map);
+
+	p_map_obj = (cl_map_obj_t *) cl_qpool_get(&p_map->pool);
+
+	if (!p_map_obj)
+		return (NULL);
+
+	cl_qmap_set_obj(p_map_obj, p_object);
+
+	p_obj_at_key =
+	    (cl_map_obj_t *) cl_qmap_insert(&p_map->qmap, key,
+					    &p_map_obj->item);
+
+	/* Return the item to the pool if insertion failed. */
+	if (p_obj_at_key != p_map_obj)
+		cl_qpool_put(&p_map->pool, &p_map_obj->item.pool_item);
+
+	return (cl_qmap_obj(p_obj_at_key));
+}
+
+void *cl_map_get(IN const cl_map_t * const p_map, IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+
+	CL_ASSERT(p_map);
+
+	p_item = cl_qmap_get(&p_map->qmap, key);
+
+	if (p_item == cl_qmap_end(&p_map->qmap))
+		return (NULL);
+
+	return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item)));
+}
+
+void *cl_map_get_next(IN const cl_map_t * const p_map, IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+
+	CL_ASSERT(p_map);
+
+	p_item = cl_qmap_get_next(&p_map->qmap, key);
+
+	if (p_item == cl_qmap_end(&p_map->qmap))
+		return (NULL);
+
+	return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item)));
+}
+
+void
+cl_map_remove_item(IN cl_map_t * const p_map, IN const cl_map_iterator_t itor)
+{
+	CL_ASSERT(itor->p_map == &p_map->qmap);
+
+	if (itor == cl_map_end(p_map))
+		return;
+
+	cl_qmap_remove_item(&p_map->qmap, (cl_map_item_t *) itor);
+	cl_qpool_put(&p_map->pool, &((cl_map_item_t *) itor)->pool_item);
+}
+
+void *cl_map_remove(IN cl_map_t * const p_map, IN const uint64_t key)
+{
+	cl_map_item_t *p_item;
+	void *p_obj;
+
+	CL_ASSERT(p_map);
+
+	p_item = cl_qmap_remove(&p_map->qmap, key);
+
+	if (p_item == cl_qmap_end(&p_map->qmap))
+		return (NULL);
+
+	p_obj = cl_qmap_obj((cl_map_obj_t *) p_item);
+	cl_qpool_put(&p_map->pool, &p_item->pool_item);
+
+	return (p_obj);
+}
+
+void cl_map_remove_all(IN cl_map_t * const p_map)
+{
+	cl_map_item_t *p_item;
+
+	CL_ASSERT(p_map);
+
+	/* Return all map items to the pool. */
+	while (!cl_is_qmap_empty(&p_map->qmap)) {
+		p_item = cl_qmap_head(&p_map->qmap);
+		cl_qmap_remove_item(&p_map->qmap, p_item);
+		cl_qpool_put(&p_map->pool, &p_item->pool_item);
+
+		if (!cl_is_qmap_empty(&p_map->qmap)) {
+			p_item = cl_qmap_tail(&p_map->qmap);
+			cl_qmap_remove_item(&p_map->qmap, p_item);
+			cl_qpool_put(&p_map->pool, &p_item->pool_item);
+		}
+	}
+}
+
+cl_status_t
+cl_map_merge(OUT cl_map_t * const p_dest_map, IN OUT cl_map_t * const p_src_map)
+{
+	cl_status_t status = CL_SUCCESS;
+	cl_map_iterator_t itor, next;
+	uint64_t key;
+	void *p_obj, *p_obj2;
+
+	CL_ASSERT(p_dest_map);
+	CL_ASSERT(p_src_map);
+
+	itor = cl_map_head(p_src_map);
+	while (itor != cl_map_end(p_src_map)) {
+		next = cl_map_next(itor);
+
+		p_obj = cl_map_obj(itor);
+		key = cl_map_key(itor);
+
+		cl_map_remove_item(p_src_map, itor);
+
+		/* Insert the object into the destination map. */
+		p_obj2 = cl_map_insert(p_dest_map, key, p_obj);
+		/* Trap for failure. */
+		if (p_obj != p_obj2) {
+			if (!p_obj2)
+				status = CL_INSUFFICIENT_MEMORY;
+			/* Put the object back in the source map.  This must succeed. */
+			p_obj2 = cl_map_insert(p_src_map, key, p_obj);
+			CL_ASSERT(p_obj == p_obj2);
+			/* If the failure was due to insufficient memory, return. */
+			if (status != CL_SUCCESS)
+				return (status);
+		}
+		itor = next;
+	}
+
+	return (CL_SUCCESS);
+}
+
+static void
+__cl_map_revert(IN OUT cl_map_t * const p_map1,
+		IN OUT cl_map_t * const p_map2,
+		IN OUT cl_map_t * const p_new, IN OUT cl_map_t * const p_old)
+{
+	cl_status_t status;
+
+	/* Restore the initial state. */
+	status = cl_map_merge(p_map1, p_old);
+	CL_ASSERT(status == CL_SUCCESS);
+	status = cl_map_merge(p_map2, p_new);
+	CL_ASSERT(status == CL_SUCCESS);
+}
+
+static cl_status_t
+__cl_map_delta_move(OUT cl_map_t * const p_dest,
+		    IN OUT cl_map_t * const p_src,
+		    IN OUT cl_map_iterator_t * const p_itor)
+{
+	cl_map_iterator_t next;
+	void *p_obj, *p_obj2;
+	uint64_t key;
+
+	/* Get a valid iterator so we can continue the loop. */
+	next = cl_map_next(*p_itor);
+	/* Get the pointer to the object for insertion. */
+	p_obj = cl_map_obj(*p_itor);
+	/* Get the key for the object. */
+	key = cl_map_key(*p_itor);
+	/* Move the object. */
+	cl_map_remove_item(p_src, *p_itor);
+	p_obj2 = cl_map_insert(p_dest, key, p_obj);
+	/* Check for failure. We should never get a duplicate. */
+	if (!p_obj2) {
+		p_obj2 = cl_map_insert(p_src, key, p_obj);
+		CL_ASSERT(p_obj2 == p_obj);
+		return (CL_INSUFFICIENT_MEMORY);
+	}
+
+	/* We should never get a duplicate */
+	CL_ASSERT(p_obj == p_obj2);
+	/* Update the iterator so that it is valid. */
+	(*p_itor) = next;
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_map_delta(IN OUT cl_map_t * const p_map1,
+	     IN OUT cl_map_t * const p_map2,
+	     OUT cl_map_t * const p_new, OUT cl_map_t * const p_old)
+{
+	cl_map_iterator_t itor1, itor2;
+	uint64_t key1, key2;
+	cl_status_t status;
+
+	CL_ASSERT(p_map1);
+	CL_ASSERT(p_map2);
+	CL_ASSERT(p_new);
+	CL_ASSERT(p_old);
+	CL_ASSERT(cl_is_map_empty(p_new));
+	CL_ASSERT(cl_is_map_empty(p_old));
+
+	itor1 = cl_map_head(p_map1);
+	itor2 = cl_map_head(p_map2);
+
+	/*
+	 * Note that the check is for the end, since duplicate items will remain
+	 * in their respective maps.
+	 */
+	while (itor1 != cl_map_end(p_map1) && itor2 != cl_map_end(p_map2)) {
+		key1 = cl_map_key(itor1);
+		key2 = cl_map_key(itor2);
+		if (key1 < key2) {
+			status = __cl_map_delta_move(p_old, p_map1, &itor1);
+			/* Check for failure. */
+			if (status != CL_SUCCESS) {
+				/* Restore the initial state. */
+				__cl_map_revert(p_map1, p_map2, p_new, p_old);
+				/* Return the failure status. */
+				return (status);
+			}
+		} else if (key1 > key2) {
+			status = __cl_map_delta_move(p_new, p_map2, &itor2);
+			if (status != CL_SUCCESS) {
+				/* Restore the initial state. */
+				__cl_map_revert(p_map1, p_map2, p_new, p_old);
+				/* Return the failure status. */
+				return (status);
+			}
+		} else {
+			/* Move both forward since they have the same key. */
+			itor1 = cl_map_next(itor1);
+			itor2 = cl_map_next(itor2);
+		}
+	}
+
+	/* Process the remainder if either source map is empty. */
+	while (itor2 != cl_map_end(p_map2)) {
+		status = __cl_map_delta_move(p_new, p_map2, &itor2);
+		if (status != CL_SUCCESS) {
+			/* Restore the initial state. */
+			__cl_map_revert(p_map1, p_map2, p_new, p_old);
+			/* Return the failure status. */
+			return (status);
+		}
+	}
+
+	while (itor1 != cl_map_end(p_map1)) {
+		status = __cl_map_delta_move(p_old, p_map1, &itor1);
+		if (status != CL_SUCCESS) {
+			/* Restore the initial state. */
+			__cl_map_revert(p_map1, p_map2, p_new, p_old);
+			/* Return the failure status. */
+			return (status);
+		}
+	}
+
+	return (CL_SUCCESS);
+}
+
+/******************************************************************************
+*******************************************************************************
+**************													   ************
+**************			 IMPLEMENTATION OF FLEXI MAP			   ************
+**************													   ************
+*******************************************************************************
+******************************************************************************/
+
+/*
+ * Get the root.
+ */
+static inline cl_fmap_item_t *__cl_fmap_root(IN const cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (p_map->root.p_left);
+}
+
+/*
+ * Returns whether a given item is on the left of its parent.
+ */
+static boolean_t __cl_fmap_is_left_child(IN const cl_fmap_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_up);
+	CL_ASSERT(p_item->p_up != p_item);
+
+	return (p_item->p_up->p_left == p_item);
+}
+
+/*
+ * Retrieve the pointer to the parent's pointer to an item.
+ */
+static cl_fmap_item_t **__cl_fmap_get_parent_ptr_to_item(IN cl_fmap_item_t *
+							 const p_item)
+{
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_up);
+	CL_ASSERT(p_item->p_up != p_item);
+
+	if (__cl_fmap_is_left_child(p_item))
+		return (&p_item->p_up->p_left);
+
+	CL_ASSERT(p_item->p_up->p_right == p_item);
+	return (&p_item->p_up->p_right);
+}
+
+/*
+ * Rotate a node to the left.  This rotation affects the least number of links
+ * between nodes and brings the level of C up by one while increasing the depth
+ * of A one.  Note that the links to/from W, X, Y, and Z are not affected.
+ *
+ *	    R				      R
+ *	    |				      |
+ *	    A				      C
+ *	  /   \			        /   \
+ *	W       C			  A       Z
+ *	       / \			 / \
+ *	      B   Z			W   B
+ *	     / \			   / \
+ *	    X   Y			  X   Y
+ */
+static void
+__cl_fmap_rot_left(IN cl_fmap_t * const p_map, IN cl_fmap_item_t * const p_item)
+{
+	cl_fmap_item_t **pp_root;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_right != &p_map->nil);
+
+	pp_root = __cl_fmap_get_parent_ptr_to_item(p_item);
+
+	/* Point R to C instead of A. */
+	*pp_root = p_item->p_right;
+	/* Set C's parent to R. */
+	(*pp_root)->p_up = p_item->p_up;
+
+	/* Set A's right to B */
+	p_item->p_right = (*pp_root)->p_left;
+	/*
+	 * Set B's parent to A.  We trap for B being NIL since the
+	 * caller may depend on NIL not changing.
+	 */
+	if ((*pp_root)->p_left != &p_map->nil)
+		(*pp_root)->p_left->p_up = p_item;
+
+	/* Set C's left to A. */
+	(*pp_root)->p_left = p_item;
+	/* Set A's parent to C. */
+	p_item->p_up = *pp_root;
+}
+
+/*
+ * Rotate a node to the right.  This rotation affects the least number of links
+ * between nodes and brings the level of A up by one while increasing the depth
+ * of C one.  Note that the links to/from W, X, Y, and Z are not affected.
+ *
+ *	        R				     R
+ *	        |				     |
+ *	        C				     A
+ *	      /   \				   /   \
+ *	    A       Z			 W       C
+ *	   / \    				        / \
+ *	  W   B   				       B   Z
+ *	     / \				      / \
+ *	    X   Y				     X   Y
+ */
+static void
+__cl_fmap_rot_right(IN cl_fmap_t * const p_map,
+		    IN cl_fmap_item_t * const p_item)
+{
+	cl_fmap_item_t **pp_root;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_left != &p_map->nil);
+
+	/* Point R to A instead of C. */
+	pp_root = __cl_fmap_get_parent_ptr_to_item(p_item);
+	(*pp_root) = p_item->p_left;
+	/* Set A's parent to R. */
+	(*pp_root)->p_up = p_item->p_up;
+
+	/* Set C's left to B */
+	p_item->p_left = (*pp_root)->p_right;
+	/*
+	 * Set B's parent to C.  We trap for B being NIL since the
+	 * caller may depend on NIL not changing.
+	 */
+	if ((*pp_root)->p_right != &p_map->nil)
+		(*pp_root)->p_right->p_up = p_item;
+
+	/* Set A's right to C. */
+	(*pp_root)->p_right = p_item;
+	/* Set C's parent to A. */
+	p_item->p_up = *pp_root;
+}
+
+void cl_fmap_init(IN cl_fmap_t * const p_map, IN cl_pfn_fmap_cmp_t pfn_compare)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(pfn_compare);
+
+	memset(p_map, 0, sizeof(cl_fmap_t));
+
+	/* special setup for the root node */
+	p_map->root.p_up = &p_map->root;
+	p_map->root.p_left = &p_map->nil;
+	p_map->root.p_right = &p_map->nil;
+	p_map->root.color = CL_MAP_BLACK;
+
+	/* Setup the node used as terminator for all leaves. */
+	p_map->nil.p_up = &p_map->nil;
+	p_map->nil.p_left = &p_map->nil;
+	p_map->nil.p_right = &p_map->nil;
+	p_map->nil.color = CL_MAP_BLACK;
+
+	/* Store the compare function pointer. */
+	p_map->pfn_compare = pfn_compare;
+
+	p_map->state = CL_INITIALIZED;
+
+	cl_fmap_remove_all(p_map);
+}
+
+cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map,
+			    IN const void *const p_key)
+{
+	cl_fmap_item_t *p_item;
+	intn_t cmp;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_item = __cl_fmap_root(p_map);
+
+	while (p_item != &p_map->nil) {
+		cmp = p_map->pfn_compare(p_key, p_item->p_key);
+
+		if (!cmp)
+			break;	/* just right */
+
+		if (cmp < 0)
+			p_item = p_item->p_left;	/* too small */
+		else
+			p_item = p_item->p_right;	/* too big */
+	}
+
+	return (p_item);
+}
+
+cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map,
+				 IN const void *const p_key)
+{
+	cl_fmap_item_t *p_item;
+	cl_fmap_item_t *p_item_found;
+	intn_t cmp;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_item = __cl_fmap_root(p_map);
+	p_item_found = (cl_fmap_item_t *) & p_map->nil;
+
+	while (p_item != &p_map->nil) {
+		cmp = p_map->pfn_compare(p_key, p_item->p_key);
+
+		if (cmp < 0) {
+			p_item_found = p_item;
+			p_item = p_item->p_left;	/* too small */
+		} else {
+			p_item = p_item->p_right;	/* too big or match */
+		}
+	}
+
+	return (p_item_found);
+}
+
+void
+cl_fmap_apply_func(IN const cl_fmap_t * const p_map,
+		   IN cl_pfn_fmap_apply_t pfn_func,
+		   IN const void *const context)
+{
+	cl_fmap_item_t *p_fmap_item;
+
+	/* Note that context can have any arbitrary value. */
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_func);
+
+	p_fmap_item = cl_fmap_head(p_map);
+	while (p_fmap_item != cl_fmap_end(p_map)) {
+		pfn_func(p_fmap_item, (void *)context);
+		p_fmap_item = cl_fmap_next(p_fmap_item);
+	}
+}
+
+/*
+ * Balance a tree starting at a given item back to the root.
+ */
+static void
+__cl_fmap_ins_bal(IN cl_fmap_t * const p_map, IN cl_fmap_item_t * p_item)
+{
+	cl_fmap_item_t *p_grand_uncle;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item != &p_map->root);
+
+	while (p_item->p_up->color == CL_MAP_RED) {
+		if (__cl_fmap_is_left_child(p_item->p_up)) {
+			p_grand_uncle = p_item->p_up->p_up->p_right;
+			CL_ASSERT(p_grand_uncle);
+			if (p_grand_uncle->color == CL_MAP_RED) {
+				p_grand_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_BLACK;
+				p_item->p_up->p_up->color = CL_MAP_RED;
+				p_item = p_item->p_up->p_up;
+				continue;
+			}
+
+			if (!__cl_fmap_is_left_child(p_item)) {
+				p_item = p_item->p_up;
+				__cl_fmap_rot_left(p_map, p_item);
+			}
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_item->p_up->p_up->color = CL_MAP_RED;
+			__cl_fmap_rot_right(p_map, p_item->p_up->p_up);
+		} else {
+			p_grand_uncle = p_item->p_up->p_up->p_left;
+			CL_ASSERT(p_grand_uncle);
+			if (p_grand_uncle->color == CL_MAP_RED) {
+				p_grand_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_BLACK;
+				p_item->p_up->p_up->color = CL_MAP_RED;
+				p_item = p_item->p_up->p_up;
+				continue;
+			}
+
+			if (__cl_fmap_is_left_child(p_item)) {
+				p_item = p_item->p_up;
+				__cl_fmap_rot_right(p_map, p_item);
+			}
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_item->p_up->p_up->color = CL_MAP_RED;
+			__cl_fmap_rot_left(p_map, p_item->p_up->p_up);
+		}
+	}
+}
+
+cl_fmap_item_t *cl_fmap_insert(IN cl_fmap_t * const p_map,
+			       IN const void *const p_key,
+			       IN cl_fmap_item_t * const p_item)
+{
+	cl_fmap_item_t *p_insert_at, *p_comp_item;
+	intn_t cmp = 0;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_map->root.p_up == &p_map->root);
+	CL_ASSERT(p_map->root.color != CL_MAP_RED);
+	CL_ASSERT(p_map->nil.color != CL_MAP_RED);
+
+	p_item->p_left = &p_map->nil;
+	p_item->p_right = &p_map->nil;
+	p_item->p_key = p_key;
+	p_item->color = CL_MAP_RED;
+
+	/* Find the insertion location. */
+	p_insert_at = &p_map->root;
+	p_comp_item = __cl_fmap_root(p_map);
+
+	while (p_comp_item != &p_map->nil) {
+		p_insert_at = p_comp_item;
+
+		cmp = p_map->pfn_compare(p_key, p_insert_at->p_key);
+
+		if (!cmp)
+			return (p_insert_at);
+
+		/* Traverse the tree until the correct insertion point is found. */
+		if (cmp < 0)
+			p_comp_item = p_insert_at->p_left;
+		else
+			p_comp_item = p_insert_at->p_right;
+	}
+
+	CL_ASSERT(p_insert_at != &p_map->nil);
+	CL_ASSERT(p_comp_item == &p_map->nil);
+	/* Insert the item. */
+	if (p_insert_at == &p_map->root) {
+		p_insert_at->p_left = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(&p_map->nil.pool_item.list_item,
+				      &p_item->pool_item.list_item);
+	} else if (cmp < 0) {
+		p_insert_at->p_left = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(&p_insert_at->pool_item.list_item,
+				      &p_item->pool_item.list_item);
+	} else {
+		p_insert_at->p_right = p_item;
+		/*
+		 * Primitive insert places the new item in front of
+		 * the existing item.
+		 */
+		__cl_primitive_insert(p_insert_at->pool_item.list_item.p_next,
+				      &p_item->pool_item.list_item);
+	}
+	/* Increase the count. */
+	p_map->count++;
+
+	p_item->p_up = p_insert_at;
+
+	/*
+	 * We have added depth to this section of the tree.
+	 * Rebalance as necessary as we retrace our path through the tree
+	 * and update colors.
+	 */
+	__cl_fmap_ins_bal(p_map, p_item);
+
+	__cl_fmap_root(p_map)->color = CL_MAP_BLACK;
+
+	/*
+	 * Note that it is not necessary to re-color the nil node black because all
+	 * red color assignments are made via the p_up pointer, and nil is never
+	 * set as the value of a p_up pointer.
+	 */
+
+#ifdef _DEBUG_
+	/* Set the pointer to the map in the map item for consistency checking. */
+	p_item->p_map = p_map;
+#endif
+
+	return (p_item);
+}
+
+static void
+__cl_fmap_del_bal(IN cl_fmap_t * const p_map, IN cl_fmap_item_t * p_item)
+{
+	cl_fmap_item_t *p_uncle;
+
+	while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) {
+		if (__cl_fmap_is_left_child(p_item)) {
+			p_uncle = p_item->p_up->p_right;
+
+			if (p_uncle->color == CL_MAP_RED) {
+				p_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_RED;
+				__cl_fmap_rot_left(p_map, p_item->p_up);
+				p_uncle = p_item->p_up->p_right;
+			}
+
+			if (p_uncle->p_right->color != CL_MAP_RED) {
+				if (p_uncle->p_left->color != CL_MAP_RED) {
+					p_uncle->color = CL_MAP_RED;
+					p_item = p_item->p_up;
+					continue;
+				}
+
+				p_uncle->p_left->color = CL_MAP_BLACK;
+				p_uncle->color = CL_MAP_RED;
+				__cl_fmap_rot_right(p_map, p_uncle);
+				p_uncle = p_item->p_up->p_right;
+			}
+			p_uncle->color = p_item->p_up->color;
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_uncle->p_right->color = CL_MAP_BLACK;
+			__cl_fmap_rot_left(p_map, p_item->p_up);
+			break;
+		} else {
+			p_uncle = p_item->p_up->p_left;
+
+			if (p_uncle->color == CL_MAP_RED) {
+				p_uncle->color = CL_MAP_BLACK;
+				p_item->p_up->color = CL_MAP_RED;
+				__cl_fmap_rot_right(p_map, p_item->p_up);
+				p_uncle = p_item->p_up->p_left;
+			}
+
+			if (p_uncle->p_left->color != CL_MAP_RED) {
+				if (p_uncle->p_right->color != CL_MAP_RED) {
+					p_uncle->color = CL_MAP_RED;
+					p_item = p_item->p_up;
+					continue;
+				}
+
+				p_uncle->p_right->color = CL_MAP_BLACK;
+				p_uncle->color = CL_MAP_RED;
+				__cl_fmap_rot_left(p_map, p_uncle);
+				p_uncle = p_item->p_up->p_left;
+			}
+			p_uncle->color = p_item->p_up->color;
+			p_item->p_up->color = CL_MAP_BLACK;
+			p_uncle->p_left->color = CL_MAP_BLACK;
+			__cl_fmap_rot_right(p_map, p_item->p_up);
+			break;
+		}
+	}
+	p_item->color = CL_MAP_BLACK;
+}
+
+void
+cl_fmap_remove_item(IN cl_fmap_t * const p_map,
+		    IN cl_fmap_item_t * const p_item)
+{
+	cl_fmap_item_t *p_child, *p_del_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	CL_ASSERT(p_item);
+	CL_ASSERT(p_item->p_map == p_map);
+
+	if (p_item == cl_fmap_end(p_map))
+		return;
+
+	if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) {
+		/* The item being removed has children on at most on side. */
+		p_del_item = p_item;
+	} else {
+		/*
+		 * The item being removed has children on both side.
+		 * We select the item that will replace it.  After removing
+		 * the substitute item and rebalancing, the tree will have the
+		 * correct topology.  Exchanging the substitute for the item
+		 * will finalize the removal.
+		 */
+		p_del_item = cl_fmap_next(p_item);
+		CL_ASSERT(p_del_item != &p_map->nil);
+	}
+
+	/* Remove the item from the list. */
+	__cl_primitive_remove(&p_item->pool_item.list_item);
+	/* Decrement the item count. */
+	p_map->count--;
+
+	/* Get the pointer to the new root's child, if any. */
+	if (p_del_item->p_left != &p_map->nil)
+		p_child = p_del_item->p_left;
+	else
+		p_child = p_del_item->p_right;
+
+	/*
+	 * This assignment may modify the parent pointer of the nil node.
+	 * This is inconsequential.
+	 */
+	p_child->p_up = p_del_item->p_up;
+	(*__cl_fmap_get_parent_ptr_to_item(p_del_item)) = p_child;
+
+	if (p_del_item->color != CL_MAP_RED)
+		__cl_fmap_del_bal(p_map, p_child);
+
+	/*
+	 * Note that the splicing done below does not need to occur before
+	 * the tree is balanced, since the actual topology changes are made by the
+	 * preceding code.  The topology is preserved by the color assignment made
+	 * below (reader should be reminded that p_del_item == p_item in some cases).
+	 */
+	if (p_del_item != p_item) {
+		/*
+		 * Finalize the removal of the specified item by exchanging it with
+		 * the substitute which we removed above.
+		 */
+		p_del_item->p_up = p_item->p_up;
+		p_del_item->p_left = p_item->p_left;
+		p_del_item->p_right = p_item->p_right;
+		(*__cl_fmap_get_parent_ptr_to_item(p_item)) = p_del_item;
+		p_item->p_right->p_up = p_del_item;
+		p_item->p_left->p_up = p_del_item;
+		p_del_item->color = p_item->color;
+	}
+
+	CL_ASSERT(p_map->nil.color != CL_MAP_RED);
+
+#ifdef _DEBUG_
+	/* Clear the pointer to the map since the item has been removed. */
+	p_item->p_map = NULL;
+#endif
+}
+
+cl_fmap_item_t *cl_fmap_remove(IN cl_fmap_t * const p_map,
+			       IN const void *const p_key)
+{
+	cl_fmap_item_t *p_item;
+
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	/* Seek the node with the specified key */
+	p_item = cl_fmap_get(p_map, p_key);
+
+	cl_fmap_remove_item(p_map, p_item);
+
+	return (p_item);
+}
+
+void
+cl_fmap_merge(OUT cl_fmap_t * const p_dest_map,
+	      IN OUT cl_fmap_t * const p_src_map)
+{
+	cl_fmap_item_t *p_item, *p_item2, *p_next;
+
+	CL_ASSERT(p_dest_map);
+	CL_ASSERT(p_src_map);
+
+	p_item = cl_fmap_head(p_src_map);
+
+	while (p_item != cl_fmap_end(p_src_map)) {
+		p_next = cl_fmap_next(p_item);
+
+		/* Remove the item from its current map. */
+		cl_fmap_remove_item(p_src_map, p_item);
+		/* Insert the item into the destination map. */
+		p_item2 =
+		    cl_fmap_insert(p_dest_map, cl_fmap_key(p_item), p_item);
+		/* Check that the item was successfully inserted. */
+		if (p_item2 != p_item) {
+			/* Put the item in back in the source map. */
+			p_item2 =
+			    cl_fmap_insert(p_src_map, cl_fmap_key(p_item),
+					   p_item);
+			CL_ASSERT(p_item2 == p_item);
+		}
+		p_item = p_next;
+	}
+}
+
+static void
+__cl_fmap_delta_move(IN OUT cl_fmap_t * const p_dest,
+		     IN OUT cl_fmap_t * const p_src,
+		     IN OUT cl_fmap_item_t ** const pp_item)
+{
+	cl_fmap_item_t *p_temp, *p_next;
+
+	/*
+	 * Get the next item so that we can ensure that pp_item points to
+	 * a valid item upon return from the function.
+	 */
+	p_next = cl_fmap_next(*pp_item);
+	/* Move the old item from its current map the the old map. */
+	cl_fmap_remove_item(p_src, *pp_item);
+	p_temp = cl_fmap_insert(p_dest, cl_fmap_key(*pp_item), *pp_item);
+	/* We should never have duplicates. */
+	CL_ASSERT(p_temp == *pp_item);
+	/* Point pp_item to a valid item in the source map. */
+	(*pp_item) = p_next;
+}
+
+void
+cl_fmap_delta(IN OUT cl_fmap_t * const p_map1,
+	      IN OUT cl_fmap_t * const p_map2,
+	      OUT cl_fmap_t * const p_new, OUT cl_fmap_t * const p_old)
+{
+	cl_fmap_item_t *p_item1, *p_item2;
+	intn_t cmp;
+
+	CL_ASSERT(p_map1);
+	CL_ASSERT(p_map2);
+	CL_ASSERT(p_new);
+	CL_ASSERT(p_old);
+	CL_ASSERT(cl_is_fmap_empty(p_new));
+	CL_ASSERT(cl_is_fmap_empty(p_old));
+
+	p_item1 = cl_fmap_head(p_map1);
+	p_item2 = cl_fmap_head(p_map2);
+
+	while (p_item1 != cl_fmap_end(p_map1) && p_item2 != cl_fmap_end(p_map2)) {
+		cmp = p_map1->pfn_compare(cl_fmap_key(p_item1),
+					  cl_fmap_key(p_item2));
+		if (cmp < 0) {
+			/* We found an old item. */
+			__cl_fmap_delta_move(p_old, p_map1, &p_item1);
+		} else if (cmp > 0) {
+			/* We found a new item. */
+			__cl_fmap_delta_move(p_new, p_map2, &p_item2);
+		} else {
+			/* Move both forward since they have the same key. */
+			p_item1 = cl_fmap_next(p_item1);
+			p_item2 = cl_fmap_next(p_item2);
+		}
+	}
+
+	/* Process the remainder if the end of either source map was reached. */
+	while (p_item2 != cl_fmap_end(p_map2))
+		__cl_fmap_delta_move(p_new, p_map2, &p_item2);
+
+	while (p_item1 != cl_fmap_end(p_map1))
+		__cl_fmap_delta_move(p_old, p_map1, &p_item1);
+}
diff --git a/complib/cl_nodenamemap.c b/complib/cl_nodenamemap.c
new file mode 100644
index 0000000..04f6bbf
--- /dev/null
+++ b/complib/cl_nodenamemap.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 Lawrence Livermore National Lab
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <config.h>
+
+#include <complib/cl_nodenamemap.h>
+
+static int map_name(void *cxt, uint64_t guid, char *p)
+{
+	cl_qmap_t *map = cxt;
+	name_map_item_t *item;
+
+	p = strtok(p, "\"#");
+	if (!p)
+		return 0;
+
+	item = malloc(sizeof(*item));
+	if (!item)
+		return -1;
+	item->guid = guid;
+	item->name = strdup(p);
+	cl_qmap_insert(map, item->guid, (cl_map_item_t *)item);
+	return 0;
+}
+
+nn_map_t *
+open_node_name_map(char *node_name_map)
+{
+	nn_map_t *map;
+
+	if (!node_name_map) {
+#ifdef HAVE_DEFAULT_NODENAME_MAP
+		struct stat buf;
+		node_name_map = HAVE_DEFAULT_NODENAME_MAP;
+		if (stat(node_name_map, &buf))
+			return NULL;
+#else
+		return NULL;
+#endif /* HAVE_DEFAULT_NODENAME_MAP */
+	}
+
+	map = malloc(sizeof(*map));
+	if (!map)
+		return NULL;
+	cl_qmap_init(map);
+
+	if (parse_node_map(node_name_map, map_name, map)) {
+		fprintf(stderr,
+			"WARNING failed to open node name map \"%s\" (%s)\n",
+			node_name_map, strerror(errno));
+			close_node_name_map(map);
+			return NULL;
+	}
+
+	return map;
+}
+
+void
+close_node_name_map(nn_map_t *map)
+{
+	name_map_item_t *item = NULL;
+
+	if (!map)
+		return;
+
+	item = (name_map_item_t *)cl_qmap_head(map);
+	while (item != (name_map_item_t *)cl_qmap_end(map)) {
+		item = (name_map_item_t *)cl_qmap_remove(map, item->guid);
+		free(item->name);
+		free(item);
+		item = (name_map_item_t *)cl_qmap_head(map);
+	}
+	free(map);
+}
+
+char *
+remap_node_name(nn_map_t *map, uint64_t target_guid, char *nodedesc)
+{
+	char *rc = NULL;
+	name_map_item_t *item = NULL;
+
+	if (!map)
+		goto done;
+
+	item = (name_map_item_t *)cl_qmap_get(map, target_guid);
+	if (item != (name_map_item_t *)cl_qmap_end(map))
+		rc = strdup(item->name);
+
+done:
+	if (rc == NULL)
+		rc = strdup(clean_nodedesc(nodedesc));
+	return (rc);
+}
+
+char *
+clean_nodedesc(char *nodedesc)
+{
+	int i = 0;
+
+	nodedesc[63] = '\0';
+	while (nodedesc[i]) {
+		if (!isprint(nodedesc[i]))
+			nodedesc[i] = ' ';
+		i++;
+	}
+
+	return (nodedesc);
+}
+
+int parse_node_map(const char *file_name,
+		   int (*create)(void *, uint64_t, char *), void *cxt)
+{
+	char line[256];
+	FILE *f;
+
+	if (!(f = fopen(file_name, "r")))
+		return -1;
+
+	while (fgets(line, sizeof(line), f)) {
+		uint64_t guid;
+		char *p, *e;
+
+		p = line;
+		while (isspace(*p))
+			p++;
+		if (*p == '\0' || *p == '\n' || *p == '#')
+			continue;
+
+		guid = strtoull(p, &e, 0);
+		if (e == p || (!isspace(*e) && *e != '#' && *e != '\0')) {
+			fclose(f);
+			return -1;
+		}
+
+		p = e;
+		while (isspace(*p))
+			p++;
+
+		e = strpbrk(p, "\n");
+		if (e)
+			*e = '\0';
+
+		if (create(cxt, guid, p)) {
+			fclose(f);
+			return -1;
+		}
+	}
+
+	fclose(f);
+	return 0;
+}
diff --git a/complib/cl_pool.c b/complib/cl_pool.c
new file mode 100644
index 0000000..0790304
--- /dev/null
+++ b/complib/cl_pool.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation of the grow pools.  The grow pools manage a pool of objects.
+ *	The pools can grow to meet demand, limited only by system memory.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_qcomppool.h>
+#include <complib/cl_comppool.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_pool.h>
+#include <complib/cl_math.h>
+
+/*
+ * IMPLEMENTATION OF QUICK COMPOSITE POOL
+ */
+void cl_qcpool_construct(IN cl_qcpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+
+	memset(p_pool, 0, sizeof(cl_qcpool_t));
+
+	p_pool->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_qcpool_init(IN cl_qcpool_t * const p_pool,
+	       IN const size_t min_size,
+	       IN const size_t max_size,
+	       IN const size_t grow_size,
+	       IN const size_t * const component_sizes,
+	       IN const uint32_t num_components,
+	       IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL,
+	       IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL,
+	       IN const void *const context)
+{
+	cl_status_t status;
+	uint32_t i;
+
+	CL_ASSERT(p_pool);
+	/* Must have a minimum of 1 component. */
+	CL_ASSERT(num_components);
+	/* A component size array is required. */
+	CL_ASSERT(component_sizes);
+	/*
+	 * If no initializer is provided, the first component must be large
+	 * enough to hold a pool item.
+	 */
+	CL_ASSERT(pfn_initializer ||
+		  (component_sizes[0] >= sizeof(cl_pool_item_t)));
+
+	cl_qcpool_construct(p_pool);
+
+	if (num_components > 1 && !pfn_initializer)
+		return (CL_INVALID_SETTING);
+
+	if (max_size && max_size < min_size)
+		return (CL_INVALID_SETTING);
+
+	/*
+	 * Allocate the array of component sizes and component pointers all
+	 * in one allocation.
+	 */
+	p_pool->component_sizes = (size_t *) malloc((sizeof(size_t) +
+						     sizeof(void *)) *
+						    num_components);
+
+	if (!p_pool->component_sizes)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(p_pool->component_sizes, 0,
+		       (sizeof(size_t) + sizeof(void *)) * num_components);
+
+	/* Calculate the pointer to the array of pointers, used for callbacks. */
+	p_pool->p_components =
+	    (void **)(p_pool->component_sizes + num_components);
+
+	/* Copy the user's sizes into our array for future use. */
+	memcpy(p_pool->component_sizes, component_sizes,
+	       sizeof(component_sizes[0]) * num_components);
+
+	/* Store the number of components per object. */
+	p_pool->num_components = num_components;
+
+	/* Round up and store the size of the components. */
+	for (i = 0; i < num_components; i++) {
+		/*
+		 * We roundup each component size so that all components
+		 * are aligned on a natural boundary.
+		 */
+		p_pool->component_sizes[i] =
+		    ROUNDUP(p_pool->component_sizes[i], sizeof(uintn_t));
+	}
+
+	p_pool->max_objects = max_size ? max_size : ~(size_t) 0;
+	p_pool->grow_size = grow_size;
+
+	/* Store callback function pointers. */
+	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
+	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
+	p_pool->context = context;
+
+	cl_qlist_init(&p_pool->alloc_list);
+
+	cl_qlist_init(&p_pool->free_list);
+
+	/*
+	 * We are now initialized.  We change the initialized flag before
+	 * growing since the grow function asserts that we are initialized.
+	 */
+	p_pool->state = CL_INITIALIZED;
+
+	/* Allocate the minimum number of objects as requested. */
+	if (!min_size)
+		return (CL_SUCCESS);
+
+	status = cl_qcpool_grow(p_pool, min_size);
+	/* Trap for error and cleanup if necessary. */
+	if (status != CL_SUCCESS)
+		cl_qcpool_destroy(p_pool);
+
+	return (status);
+}
+
+void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool)
+{
+	/* CL_ASSERT that a non-NULL pointer was provided. */
+	CL_ASSERT(p_pool);
+	/* CL_ASSERT that we are in a valid state (not uninitialized memory). */
+	CL_ASSERT(cl_is_state_valid(p_pool->state));
+
+	if (p_pool->state == CL_INITIALIZED) {
+		/*
+		 * Assert if the user hasn't put everything back in the pool
+		 * before destroying it
+		 * if they haven't, then most likely they are still using memory
+		 * that will be freed, and the destructor will not be called!
+		 */
+#ifdef _DEBUG_
+		/* but we do not want "free" version to assert on this one */
+		CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects);
+#endif
+		/* call the user's destructor for each object in the pool */
+		if (p_pool->pfn_dtor) {
+			while (!cl_is_qlist_empty(&p_pool->free_list)) {
+				p_pool->pfn_dtor((cl_pool_item_t *)
+						 cl_qlist_remove_head(&p_pool->
+								      free_list),
+						 (void *)p_pool->context);
+			}
+		} else {
+			cl_qlist_remove_all(&p_pool->free_list);
+		}
+
+		/* Free all allocated memory blocks. */
+		while (!cl_is_qlist_empty(&p_pool->alloc_list))
+			free(cl_qlist_remove_head(&p_pool->alloc_list));
+
+		if (p_pool->component_sizes) {
+			free(p_pool->component_sizes);
+			p_pool->component_sizes = NULL;
+		}
+	}
+
+	p_pool->state = CL_UNINITIALIZED;
+}
+
+cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count)
+{
+	cl_status_t status = CL_SUCCESS;
+	uint8_t *p_objects;
+	cl_pool_item_t *p_pool_item;
+	uint32_t i;
+	size_t obj_size;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+	CL_ASSERT(obj_count);
+
+	/* Validate that growth is possible. */
+	if (p_pool->num_objects == p_pool->max_objects)
+		return (CL_INSUFFICIENT_MEMORY);
+
+	/* Cap the growth to the desired maximum. */
+	if (obj_count > (p_pool->max_objects - p_pool->num_objects))
+		obj_count = p_pool->max_objects - p_pool->num_objects;
+
+	/* Calculate the size of an object. */
+	obj_size = 0;
+	for (i = 0; i < p_pool->num_components; i++)
+		obj_size += p_pool->component_sizes[i];
+
+	/* Allocate the buffer for the new objects. */
+	p_objects = (uint8_t *)
+	    malloc(sizeof(cl_list_item_t) + (obj_size * obj_count));
+
+	/* Make sure the allocation succeeded. */
+	if (!p_objects)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(p_objects, 0,
+		       sizeof(cl_list_item_t) + (obj_size * obj_count));
+
+	/* Insert the allocation in our list. */
+	cl_qlist_insert_tail(&p_pool->alloc_list, (cl_list_item_t *) p_objects);
+	p_objects += sizeof(cl_list_item_t);
+
+	/* initialize the new elements and add them to the free list */
+	while (obj_count--) {
+		/* Setup the array of components for the current object. */
+		p_pool->p_components[0] = p_objects;
+		for (i = 1; i < p_pool->num_components; i++) {
+			/* Calculate the pointer to the next component. */
+			p_pool->p_components[i] =
+			    (uint8_t *) p_pool->p_components[i - 1] +
+			    p_pool->component_sizes[i - 1];
+		}
+
+		/*
+		 * call the user's initializer
+		 * this can fail!
+		 */
+		if (p_pool->pfn_init) {
+			p_pool_item = NULL;
+			status = p_pool->pfn_init(p_pool->p_components,
+						  p_pool->num_components,
+						  (void *)p_pool->context,
+						  &p_pool_item);
+			if (status != CL_SUCCESS) {
+				/*
+				 * User initialization failed
+				 * we may have only grown the pool by some partial amount
+				 * Invoke the destructor for the object that failed
+				 * initialization.
+				 */
+				if (p_pool->pfn_dtor)
+					p_pool->pfn_dtor(p_pool_item,
+							 (void *)p_pool->
+							 context);
+
+				/* Return the user's status. */
+				return (status);
+			}
+			CL_ASSERT(p_pool_item);
+		} else {
+			/*
+			 * If no initializer is provided, assume that the pool item
+			 * is stored at the beginning of the first component.
+			 */
+			p_pool_item =
+			    (cl_pool_item_t *) p_pool->p_components[0];
+		}
+
+#ifdef _DEBUG_
+		/*
+		 * Set the pool item's pool pointer to this pool so that we can
+		 * check that items get returned to the correct pool.
+		 */
+		p_pool_item->p_pool = p_pool;
+#endif
+
+		/* Insert the new item in the free list, traping for failure. */
+		cl_qlist_insert_head(&p_pool->free_list,
+				     &p_pool_item->list_item);
+
+		p_pool->num_objects++;
+
+		/* move the pointer to the next item */
+		p_objects += obj_size;
+	}
+
+	return (status);
+}
+
+cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool)
+{
+	cl_list_item_t *p_list_item;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+
+	if (cl_is_qlist_empty(&p_pool->free_list)) {
+		/*
+		 * No object is available.
+		 * Return NULL if the user does not want automatic growth.
+		 */
+		if (!p_pool->grow_size)
+			return (NULL);
+
+		/* We ran out of elements.  Get more */
+		cl_qcpool_grow(p_pool, p_pool->grow_size);
+		/*
+		 * We may not have gotten everything we wanted but we might have
+		 * gotten something.
+		 */
+		if (cl_is_qlist_empty(&p_pool->free_list))
+			return (NULL);
+	}
+
+	p_list_item = cl_qlist_remove_head(&p_pool->free_list);
+	/* OK, at this point we have an object */
+	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
+	return ((cl_pool_item_t *) p_list_item);
+}
+
+cl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool)
+{
+	cl_list_item_t *p_list_item;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+
+	if (cl_is_qlist_empty(&p_pool->free_list)) {
+		/*
+		 * No object is available.
+		 * Return NULL if the user does not want automatic growth.
+		 */
+		if (!p_pool->grow_size)
+			return (NULL);
+
+		/* We ran out of elements.  Get more */
+		cl_qcpool_grow(p_pool, p_pool->grow_size);
+		/*
+		 * We may not have gotten everything we wanted but we might have
+		 * gotten something.
+		 */
+		if (cl_is_qlist_empty(&p_pool->free_list))
+			return (NULL);
+	}
+
+	p_list_item = cl_qlist_remove_tail(&p_pool->free_list);
+	/* OK, at this point we have an object */
+	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
+	return ((cl_pool_item_t *) p_list_item);
+}
+
+/*
+ * IMPLEMENTATION OF QUICK GROW POOL
+ */
+
+/*
+ * Callback to translate quick composite to quick grow pool
+ * initializer callback.
+ */
+static cl_status_t
+__cl_qpool_init_cb(IN void **const p_comp_array,
+		   IN const uint32_t num_components,
+		   IN void *const context,
+		   OUT cl_pool_item_t ** const pp_pool_item)
+{
+	cl_qpool_t *p_pool = (cl_qpool_t *) context;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->pfn_init);
+	CL_ASSERT(num_components == 1);
+
+	UNUSED_PARAM(num_components);
+
+	return (p_pool->pfn_init(p_comp_array[0], (void *)p_pool->context,
+				 pp_pool_item));
+}
+
+/*
+ * Callback to translate quick composite to quick grow pool
+ * destructor callback.
+ */
+static void
+__cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
+		   IN void *const context)
+{
+	cl_qpool_t *p_pool = (cl_qpool_t *) context;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->pfn_dtor);
+
+	p_pool->pfn_dtor(p_pool_item, (void *)p_pool->context);
+}
+
+void cl_qpool_construct(IN cl_qpool_t * const p_pool)
+{
+	memset(p_pool, 0, sizeof(cl_qpool_t));
+
+	cl_qcpool_construct(&p_pool->qcpool);
+}
+
+cl_status_t
+cl_qpool_init(IN cl_qpool_t * const p_pool,
+	      IN const size_t min_size,
+	      IN const size_t max_size,
+	      IN const size_t grow_size,
+	      IN const size_t object_size,
+	      IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL,
+	      IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL,
+	      IN const void *const context)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_pool);
+
+	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
+	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
+	p_pool->context = context;
+
+	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
+				&object_size, 1,
+				pfn_initializer ? __cl_qpool_init_cb : NULL,
+				pfn_destructor ? __cl_qpool_dtor_cb : NULL,
+				p_pool);
+
+	return (status);
+}
+
+/*
+ * IMPLEMENTATION OF COMPOSITE POOL
+ */
+
+/*
+ * Callback to translate quick composite to compsite pool
+ * initializer callback.
+ */
+static cl_status_t
+__cl_cpool_init_cb(IN void **const p_comp_array,
+		   IN const uint32_t num_components,
+		   IN void *const context,
+		   OUT cl_pool_item_t ** const pp_pool_item)
+{
+	cl_cpool_t *p_pool = (cl_cpool_t *) context;
+	cl_pool_obj_t *p_pool_obj;
+	cl_status_t status = CL_SUCCESS;
+
+	CL_ASSERT(p_pool);
+
+	/*
+	 * Set our pointer to the list item, which is stored at the beginning of
+	 * the first component.
+	 */
+	p_pool_obj = (cl_pool_obj_t *) p_comp_array[0];
+	/* Set the pool item pointer for the caller. */
+	*pp_pool_item = &p_pool_obj->pool_item;
+
+	/* Calculate the pointer to the user's first component. */
+	p_comp_array[0] = ((uint8_t *) p_comp_array[0]) + sizeof(cl_pool_obj_t);
+
+	/*
+	 * Set the object pointer in the pool object to point to the first of the
+	 * user's components.
+	 */
+	p_pool_obj->p_object = p_comp_array[0];
+
+	/* Invoke the user's constructor callback. */
+	if (p_pool->pfn_init) {
+		status = p_pool->pfn_init(p_comp_array, num_components,
+					  (void *)p_pool->context);
+	}
+
+	return (status);
+}
+
+/*
+ * Callback to translate quick composite to composite pool
+ * destructor callback.
+ */
+static void
+__cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
+		   IN void *const context)
+{
+	cl_cpool_t *p_pool = (cl_cpool_t *) context;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->pfn_dtor);
+	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
+
+	/* Invoke the user's destructor callback. */
+	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
+			 (void *)p_pool->context);
+}
+
+void cl_cpool_construct(IN cl_cpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+
+	memset(p_pool, 0, sizeof(cl_cpool_t));
+
+	cl_qcpool_construct(&p_pool->qcpool);
+}
+
+cl_status_t
+cl_cpool_init(IN cl_cpool_t * const p_pool,
+	      IN const size_t min_size,
+	      IN const size_t max_size,
+	      IN const size_t grow_size,
+	      IN size_t * const component_sizes,
+	      IN const uint32_t num_components,
+	      IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL,
+	      IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL,
+	      IN const void *const context)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(num_components);
+	CL_ASSERT(component_sizes);
+
+	/* Add the size of the pool object to the first component. */
+	component_sizes[0] += sizeof(cl_pool_obj_t);
+
+	/* Store callback function pointers. */
+	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
+	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
+	p_pool->context = context;
+
+	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
+				component_sizes, num_components,
+				__cl_cpool_init_cb,
+				pfn_destructor ? __cl_cpool_dtor_cb : NULL,
+				p_pool);
+
+	/* Restore the original value of the first component. */
+	component_sizes[0] -= sizeof(cl_pool_obj_t);
+
+	return (status);
+}
+
+/*
+ * IMPLEMENTATION OF GROW POOL
+ */
+
+/*
+ * Callback to translate quick composite to grow pool constructor callback.
+ */
+static cl_status_t
+__cl_pool_init_cb(IN void **const pp_obj,
+		  IN const uint32_t count,
+		  IN void *const context,
+		  OUT cl_pool_item_t ** const pp_pool_item)
+{
+	cl_pool_t *p_pool = (cl_pool_t *) context;
+	cl_pool_obj_t *p_pool_obj;
+	cl_status_t status = CL_SUCCESS;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(pp_obj);
+	CL_ASSERT(count == 1);
+
+	UNUSED_PARAM(count);
+
+	/*
+	 * Set our pointer to the list item, which is stored at the beginning of
+	 * the first component.
+	 */
+	p_pool_obj = (cl_pool_obj_t *) * pp_obj;
+	*pp_pool_item = &p_pool_obj->pool_item;
+
+	/* Calculate the pointer to the user's first component. */
+	*pp_obj = ((uint8_t *) * pp_obj) + sizeof(cl_pool_obj_t);
+
+	/*
+	 * Set the object pointer in the pool item to point to the first of the
+	 * user's components.
+	 */
+	p_pool_obj->p_object = *pp_obj;
+
+	/* Invoke the user's constructor callback. */
+	if (p_pool->pfn_init)
+		status = p_pool->pfn_init(*pp_obj, (void *)p_pool->context);
+
+	return (status);
+}
+
+/*
+ * Callback to translate quick composite to grow pool destructor callback.
+ */
+static void
+__cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
+		  IN void *const context)
+{
+	cl_pool_t *p_pool = (cl_pool_t *) context;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->pfn_dtor);
+	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
+
+	/* Invoke the user's destructor callback. */
+	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
+			 (void *)p_pool->context);
+}
+
+void cl_pool_construct(IN cl_pool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+
+	memset(p_pool, 0, sizeof(cl_pool_t));
+
+	cl_qcpool_construct(&p_pool->qcpool);
+}
+
+cl_status_t
+cl_pool_init(IN cl_pool_t * const p_pool,
+	     IN const size_t min_size,
+	     IN const size_t max_size,
+	     IN const size_t grow_size,
+	     IN const size_t object_size,
+	     IN cl_pfn_pool_init_t pfn_initializer OPTIONAL,
+	     IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL,
+	     IN const void *const context)
+{
+	cl_status_t status;
+	size_t total_size;
+
+	CL_ASSERT(p_pool);
+
+	/* Add the size of the list item to the first component. */
+	total_size = object_size + sizeof(cl_pool_obj_t);
+
+	/* Store callback function pointers. */
+	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
+	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
+	p_pool->context = context;
+
+	/*
+	 * We need an initializer in all cases for quick composite pool, since
+	 * the user pointer must be manipulated to hide the prefixed cl_pool_obj_t.
+	 */
+	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
+				&total_size, 1, __cl_pool_init_cb,
+				pfn_destructor ? __cl_pool_dtor_cb : NULL,
+				p_pool);
+
+	return (status);
+}
diff --git a/complib/cl_ptr_vector.c b/complib/cl_ptr_vector.c
new file mode 100644
index 0000000..c34316e
--- /dev/null
+++ b/complib/cl_ptr_vector.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	This file contains ivector and isvector implementations.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_ptr_vector.h>
+
+void cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+
+	memset(p_vector, 0, sizeof(cl_ptr_vector_t));
+
+	p_vector->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector,
+		   IN const size_t min_size, IN const size_t grow_size)
+{
+	cl_status_t status = CL_SUCCESS;
+
+	CL_ASSERT(p_vector);
+
+	cl_ptr_vector_construct(p_vector);
+
+	p_vector->grow_size = grow_size;
+
+	/*
+	 * Set the state to initialized so that the call to set_size
+	 * doesn't assert.
+	 */
+	p_vector->state = CL_INITIALIZED;
+
+	/* get the storage needed by the user */
+	if (min_size) {
+		status = cl_ptr_vector_set_size(p_vector, min_size);
+		if (status != CL_SUCCESS)
+			cl_ptr_vector_destroy(p_vector);
+	}
+
+	return (status);
+}
+
+void cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(cl_is_state_valid(p_vector->state));
+
+	/* Call the user's destructor for each element in the array. */
+	if (p_vector->state == CL_INITIALIZED) {
+		/* Destroy the page vector. */
+		if (p_vector->p_ptr_array) {
+			free((void *)p_vector->p_ptr_array);
+			p_vector->p_ptr_array = NULL;
+		}
+	}
+
+	p_vector->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector,
+		 IN const size_t index, OUT void **const p_element)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Range check */
+	if (index >= p_vector->size)
+		return (CL_INVALID_PARAMETER);
+
+	*p_element = cl_ptr_vector_get(p_vector, index);
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector,
+		  IN const size_t index, IN const void *const element)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Determine if the vector has room for this element. */
+	if (index >= p_vector->size) {
+		/* Resize to accomodate the given index. */
+		status = cl_ptr_vector_set_size(p_vector, index + 1);
+
+		/* Check for failure on or before the given index. */
+		if ((status != CL_SUCCESS) && (p_vector->size < index))
+			return (status);
+	}
+
+	/* At this point, the array is guaranteed to be big enough */
+	p_vector->p_ptr_array[index] = element;
+
+	return (CL_SUCCESS);
+}
+
+void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t index)
+{
+	size_t src;
+	const void *element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(p_vector->size > index);
+
+	/* Store a copy of the element to return. */
+	element = p_vector->p_ptr_array[index];
+	/* Shift all items above the removed item down. */
+	if (index < --p_vector->size) {
+		for (src = index; src < p_vector->size; src++)
+			p_vector->p_ptr_array[src] =
+			    p_vector->p_ptr_array[src + 1];
+	}
+	/* Clear the entry for the element just outside of the new upper bound. */
+	p_vector->p_ptr_array[p_vector->size] = NULL;
+
+	return ((void *)element);
+}
+
+cl_status_t
+cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t new_capacity)
+{
+	void *p_new_ptr_array;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Do we have to do anything here? */
+	if (new_capacity <= p_vector->capacity) {
+		/* Nope */
+		return (CL_SUCCESS);
+	}
+
+	/* Allocate our pointer array. */
+	p_new_ptr_array = malloc(new_capacity * sizeof(void *));
+	if (!p_new_ptr_array)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(p_new_ptr_array, 0, new_capacity * sizeof(void *));
+
+	if (p_vector->p_ptr_array) {
+		/* Copy the old pointer array into the new. */
+		memcpy(p_new_ptr_array, p_vector->p_ptr_array,
+		       p_vector->capacity * sizeof(void *));
+
+		/* Free the old pointer array. */
+		free((void *)p_vector->p_ptr_array);
+	}
+
+	/* Set the new array. */
+	p_vector->p_ptr_array = p_new_ptr_array;
+
+	/* Update the vector with the new capactity. */
+	p_vector->capacity = new_capacity;
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector,
+		       IN const size_t size)
+{
+	cl_status_t status;
+	size_t new_capacity;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Check to see if the requested size is the same as the existing size. */
+	if (size == p_vector->size)
+		return (CL_SUCCESS);
+
+	/* Determine if the vector has room for this element. */
+	if (size >= p_vector->capacity) {
+		if (!p_vector->grow_size)
+			return (CL_INSUFFICIENT_MEMORY);
+
+		/* Calculate the new capacity, taking into account the grow size. */
+		new_capacity = size;
+		if (size % p_vector->grow_size) {
+			/* Round up to nearest grow_size boundary. */
+			new_capacity += p_vector->grow_size -
+			    (size % p_vector->grow_size);
+		}
+
+		status = cl_ptr_vector_set_capacity(p_vector, new_capacity);
+		if (status != CL_SUCCESS)
+			return (status);
+	}
+
+	p_vector->size = size;
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t min_size)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	if (min_size > p_vector->size) {
+		/* We have to resize the array */
+		return (cl_ptr_vector_set_size(p_vector, min_size));
+	}
+
+	/* We didn't have to do anything */
+	return (CL_SUCCESS);
+}
+
+void
+cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector,
+			 IN cl_pfn_ptr_vec_apply_t pfn_callback,
+			 IN const void *const context)
+{
+	size_t i;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	for (i = 0; i < p_vector->size; i++)
+		pfn_callback(i, (void *)p_vector->p_ptr_array[i],
+			     (void *)context);
+}
+
+size_t
+cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector,
+			      IN cl_pfn_ptr_vec_find_t pfn_callback,
+			      IN const void *const context)
+{
+	size_t i;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	for (i = 0; i < p_vector->size; i++) {
+		/* Invoke the callback */
+		if (pfn_callback(i, (void *)p_vector->p_ptr_array[i],
+				 (void *)context) == CL_SUCCESS) {
+			break;
+		}
+	}
+	return (i);
+}
+
+size_t
+cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector,
+			    IN cl_pfn_ptr_vec_find_t pfn_callback,
+			    IN const void *const context)
+{
+	size_t i;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	i = p_vector->size;
+
+	while (i) {
+		/* Invoke the callback for the current element. */
+		if (pfn_callback(i, (void *)p_vector->p_ptr_array[--i],
+				 (void *)context) == CL_SUCCESS) {
+			return (i);
+		}
+	}
+
+	return (p_vector->size);
+}
diff --git a/complib/cl_spinlock.c b/complib/cl_spinlock.c
new file mode 100644
index 0000000..2d81696
--- /dev/null
+++ b/complib/cl_spinlock.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_spinlock.h>
+
+void cl_spinlock_construct(IN cl_spinlock_t * const p_spinlock)
+{
+	CL_ASSERT(p_spinlock);
+
+	p_spinlock->state = CL_UNINITIALIZED;
+}
+
+cl_status_t cl_spinlock_init(IN cl_spinlock_t * const p_spinlock)
+{
+	CL_ASSERT(p_spinlock);
+
+	cl_spinlock_construct(p_spinlock);
+
+	/* Initialize with pthread_mutexattr_t = NULL */
+	if (pthread_mutex_init(&p_spinlock->mutex, NULL))
+		return (CL_ERROR);
+
+	p_spinlock->state = CL_INITIALIZED;
+	return (CL_SUCCESS);
+}
+
+void cl_spinlock_destroy(IN cl_spinlock_t * const p_spinlock)
+{
+	CL_ASSERT(p_spinlock);
+	CL_ASSERT(cl_is_state_valid(p_spinlock->state));
+
+	if (p_spinlock->state == CL_INITIALIZED) {
+		p_spinlock->state = CL_UNINITIALIZED;
+		pthread_mutex_lock(&p_spinlock->mutex);
+		pthread_mutex_unlock(&p_spinlock->mutex);
+		pthread_mutex_destroy(&p_spinlock->mutex);
+	}
+	p_spinlock->state = CL_UNINITIALIZED;
+}
+
+void cl_spinlock_acquire(IN cl_spinlock_t * const p_spinlock)
+{
+	CL_ASSERT(p_spinlock);
+	CL_ASSERT(p_spinlock->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&p_spinlock->mutex);
+}
+
+void cl_spinlock_release(IN cl_spinlock_t * const p_spinlock)
+{
+	CL_ASSERT(p_spinlock);
+	CL_ASSERT(p_spinlock->state == CL_INITIALIZED);
+
+	pthread_mutex_unlock(&p_spinlock->mutex);
+}
diff --git a/complib/cl_statustext.c b/complib/cl_statustext.c
new file mode 100644
index 0000000..b02b8b8
--- /dev/null
+++ b/complib/cl_statustext.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Defines string to decode cl_status_t return values.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_types.h>
+
+/* Status values above converted to text for easier printing. */
+const char *cl_status_text[] = {
+	"CL_SUCCESS",
+	"CL_ERROR",
+	"CL_INVALID_STATE",
+	"CL_INVALID_OPERATION",
+	"CL_INVALID_SETTING",
+	"CL_INVALID_PARAMETER",
+	"CL_INSUFFICIENT_RESOURCES",
+	"CL_INSUFFICIENT_MEMORY",
+	"CL_INVALID_PERMISSION",
+	"CL_COMPLETED",
+	"CL_NOT_DONE",
+	"CL_PENDING",
+	"CL_TIMEOUT",
+	"CL_CANCELED",
+	"CL_REJECT",
+	"CL_OVERRUN",
+	"CL_NOT_FOUND",
+	"CL_UNAVAILABLE",
+	"CL_BUSY",
+	"CL_DISCONNECT",
+	"CL_DUPLICATE"
+};
diff --git a/complib/cl_thread.c b/complib/cl_thread.c
new file mode 100644
index 0000000..ab1a329
--- /dev/null
+++ b/complib/cl_thread.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/sysinfo.h>
+#include <complib/cl_thread.h>
+
+/*
+ * Internal function to run a new user mode thread.
+ * This function is always run as a result of creation a new user mode thread.
+ * Its main job is to synchronize the creation and running of the new thread.
+ */
+static void *__cl_thread_wrapper(void *arg)
+{
+	cl_thread_t *p_thread = (cl_thread_t *) arg;
+
+	CL_ASSERT(p_thread);
+	CL_ASSERT(p_thread->pfn_callback);
+
+	p_thread->pfn_callback((void *)p_thread->context);
+
+	return (NULL);
+}
+
+void cl_thread_construct(IN cl_thread_t * const p_thread)
+{
+	CL_ASSERT(p_thread);
+
+	p_thread->osd.state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_thread_init(IN cl_thread_t * const p_thread,
+	       IN cl_pfn_thread_callback_t pfn_callback,
+	       IN const void *const context, IN const char *const name)
+{
+	int ret;
+
+	CL_ASSERT(p_thread);
+
+	cl_thread_construct(p_thread);
+
+	/* Initialize the thread structure */
+	p_thread->pfn_callback = pfn_callback;
+	p_thread->context = context;
+
+	ret = pthread_create(&p_thread->osd.id, NULL,
+			     __cl_thread_wrapper, (void *)p_thread);
+
+	if (ret != 0)		/* pthread_create returns a "0" for success */
+		return (CL_ERROR);
+
+	p_thread->osd.state = CL_INITIALIZED;
+
+	return (CL_SUCCESS);
+}
+
+void cl_thread_destroy(IN cl_thread_t * const p_thread)
+{
+	CL_ASSERT(p_thread);
+	CL_ASSERT(cl_is_state_valid(p_thread->osd.state));
+
+	if (p_thread->osd.state == CL_INITIALIZED)
+		pthread_join(p_thread->osd.id, NULL);
+
+	p_thread->osd.state = CL_UNINITIALIZED;
+}
+
+void cl_thread_suspend(IN const uint32_t pause_ms)
+{
+	/* Convert to micro seconds */
+	usleep(pause_ms * 1000);
+}
+
+void cl_thread_stall(IN const uint32_t pause_us)
+{
+	/*
+	 * Not quite a busy wait, but Linux is lacking in terms of high
+	 * resolution time stamp information in user mode.
+	 */
+	usleep(pause_us);
+}
+
+int cl_proc_count(void)
+{
+	uint32_t ret;
+
+	ret = get_nprocs();
+	if (!ret)
+		return 1;	/* Workaround for PPC where get_nprocs() returns 0 */
+
+	return ret;
+}
+
+boolean_t cl_is_current_thread(IN const cl_thread_t * const p_thread)
+{
+	pthread_t current;
+
+	CL_ASSERT(p_thread);
+	CL_ASSERT(p_thread->osd.state == CL_INITIALIZED);
+
+	current = pthread_self();
+	return (pthread_equal(current, p_thread->osd.id));
+}
diff --git a/complib/cl_threadpool.c b/complib/cl_threadpool.c
new file mode 100644
index 0000000..3f6c0a4
--- /dev/null
+++ b/complib/cl_threadpool.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation of thread pool.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <complib/cl_threadpool.h>
+
+static void cleanup_mutex(void *arg)
+{
+	pthread_mutex_unlock(&((cl_thread_pool_t *) arg)->mutex);
+}
+
+static void *thread_pool_routine(void *context)
+{
+	cl_thread_pool_t *p_thread_pool = (cl_thread_pool_t *) context;
+
+	do {
+		pthread_mutex_lock(&p_thread_pool->mutex);
+		pthread_cleanup_push(cleanup_mutex, p_thread_pool);
+		while (!p_thread_pool->events)
+			pthread_cond_wait(&p_thread_pool->cond,
+					  &p_thread_pool->mutex);
+		p_thread_pool->events--;
+		pthread_cleanup_pop(1);
+		/* The event has been signalled.  Invoke the callback. */
+		(*p_thread_pool->pfn_callback) (p_thread_pool->context);
+	} while (1);
+
+	return NULL;
+}
+
+cl_status_t
+cl_thread_pool_init(IN cl_thread_pool_t * const p_thread_pool,
+		    IN unsigned count,
+		    IN void (*pfn_callback) (void *),
+		    IN void *context, IN const char *const name)
+{
+	int i;
+
+	CL_ASSERT(p_thread_pool);
+	CL_ASSERT(pfn_callback);
+
+	memset(p_thread_pool, 0, sizeof(*p_thread_pool));
+
+	if (!count)
+		count = cl_proc_count();
+
+	pthread_mutex_init(&p_thread_pool->mutex, NULL);
+	pthread_cond_init(&p_thread_pool->cond, NULL);
+
+	p_thread_pool->events = 0;
+
+	p_thread_pool->pfn_callback = pfn_callback;
+	p_thread_pool->context = context;
+
+	p_thread_pool->tid = calloc(count, sizeof(*p_thread_pool->tid));
+	if (!p_thread_pool->tid) {
+		cl_thread_pool_destroy(p_thread_pool);
+		return CL_INSUFFICIENT_MEMORY;
+	}
+
+	p_thread_pool->running_count = count;
+
+	for (i = 0; i < count; i++) {
+		if (pthread_create(&p_thread_pool->tid[i], NULL,
+				   thread_pool_routine, p_thread_pool) < 0) {
+			cl_thread_pool_destroy(p_thread_pool);
+			return CL_INSUFFICIENT_RESOURCES;
+		}
+	}
+
+	return (CL_SUCCESS);
+}
+
+void cl_thread_pool_destroy(IN cl_thread_pool_t * const p_thread_pool)
+{
+	int i;
+
+	CL_ASSERT(p_thread_pool);
+
+	for (i = 0; i < p_thread_pool->running_count; i++)
+		if (p_thread_pool->tid[i])
+			pthread_cancel(p_thread_pool->tid[i]);
+
+	for (i = 0; i < p_thread_pool->running_count; i++)
+		if (p_thread_pool->tid[i])
+			pthread_join(p_thread_pool->tid[i], NULL);
+
+	p_thread_pool->running_count = 0;
+	pthread_cond_destroy(&p_thread_pool->cond);
+	pthread_mutex_destroy(&p_thread_pool->mutex);
+
+	p_thread_pool->events = 0;
+}
+
+cl_status_t cl_thread_pool_signal(IN cl_thread_pool_t * const p_thread_pool)
+{
+	int ret;
+	CL_ASSERT(p_thread_pool);
+	pthread_mutex_lock(&p_thread_pool->mutex);
+	p_thread_pool->events++;
+	ret = pthread_cond_signal(&p_thread_pool->cond);
+	pthread_mutex_unlock(&p_thread_pool->mutex);
+	return ret;
+}
diff --git a/complib/cl_timer.c b/complib/cl_timer.c
new file mode 100644
index 0000000..41b669f
--- /dev/null
+++ b/complib/cl_timer.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * Abstraction of Timer create, destroy functions.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_timer.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <stdio.h>
+
+/* Timer provider (emulates timers in user mode). */
+typedef struct _cl_timer_prov {
+	pthread_t thread;
+	pthread_mutex_t mutex;
+	pthread_cond_t cond;
+	cl_qlist_t queue;
+
+	boolean_t exit;
+
+} cl_timer_prov_t;
+
+/* Global timer provider. */
+static cl_timer_prov_t *gp_timer_prov = NULL;
+
+static void *__cl_timer_prov_cb(IN void *const context);
+
+/*
+ * Creates the process global timer provider.  Must be called by the shared
+ * object framework to solve all serialization issues.
+ */
+cl_status_t __cl_timer_prov_create(void)
+{
+	CL_ASSERT(gp_timer_prov == NULL);
+
+	gp_timer_prov = malloc(sizeof(cl_timer_prov_t));
+	if (!gp_timer_prov)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(gp_timer_prov, 0, sizeof(cl_timer_prov_t));
+
+	cl_qlist_init(&gp_timer_prov->queue);
+
+	pthread_mutex_init(&gp_timer_prov->mutex, NULL);
+	pthread_cond_init(&gp_timer_prov->cond, NULL);
+
+	if (pthread_create(&gp_timer_prov->thread, NULL,
+			   __cl_timer_prov_cb, NULL)) {
+		__cl_timer_prov_destroy();
+		return (CL_ERROR);
+	}
+
+	return (CL_SUCCESS);
+}
+
+void __cl_timer_prov_destroy(void)
+{
+	pthread_t tid;
+
+	if (!gp_timer_prov)
+		return;
+
+	tid = gp_timer_prov->thread;
+	pthread_mutex_lock(&gp_timer_prov->mutex);
+	gp_timer_prov->exit = TRUE;
+	pthread_cond_broadcast(&gp_timer_prov->cond);
+	pthread_mutex_unlock(&gp_timer_prov->mutex);
+	pthread_join(tid, NULL);
+
+	/* Destroy the mutex and condition variable. */
+	pthread_mutex_destroy(&gp_timer_prov->mutex);
+	pthread_cond_destroy(&gp_timer_prov->cond);
+
+	/* Free the memory and reset the global pointer. */
+	free(gp_timer_prov);
+	gp_timer_prov = NULL;
+}
+
+/*
+ * This is the internal work function executed by the timer's thread.
+ */
+static void *__cl_timer_prov_cb(IN void *const context)
+{
+	int ret;
+	cl_timer_t *p_timer;
+
+	pthread_mutex_lock(&gp_timer_prov->mutex);
+	while (!gp_timer_prov->exit) {
+		if (cl_is_qlist_empty(&gp_timer_prov->queue)) {
+			/* Wait until we exit or a timer is queued. */
+			/* cond wait does:
+			 * pthread_cond_wait atomically unlocks the mutex (as per
+			 * pthread_unlock_mutex) and waits for the condition variable
+			 * cond to be signaled. The thread execution is suspended and
+			 * does not consume any CPU time until the condition variable is
+			 * signaled. The mutex must be locked by the calling thread on
+			 * entrance to pthread_cond_wait. Before RETURNING TO THE
+			 * CALLING THREAD, PTHREAD_COND_WAIT RE-ACQUIRES MUTEX (as per
+			 * pthread_lock_mutex).
+			 */
+			ret = pthread_cond_wait(&gp_timer_prov->cond,
+						&gp_timer_prov->mutex);
+		} else {
+			/*
+			 * The timer elements are on the queue in expiration order.
+			 * Get the first in the list to determine how long to wait.
+			 */
+
+			p_timer =
+			    (cl_timer_t *) cl_qlist_head(&gp_timer_prov->queue);
+			ret =
+			    pthread_cond_timedwait(&gp_timer_prov->cond,
+						   &gp_timer_prov->mutex,
+						   &p_timer->timeout);
+
+			/*
+			   Sleep again on every event other than timeout and invalid
+			   Note: EINVAL means that we got behind. This can occur when
+			   we are very busy...
+			 */
+			if (ret != ETIMEDOUT && ret != EINVAL)
+				continue;
+
+			/*
+			 * The timer expired.  Check the state in case it was cancelled
+			 * after it expired but before we got a chance to invoke the
+			 * callback.
+			 */
+			if (p_timer->timer_state != CL_TIMER_QUEUED)
+				continue;
+
+			/*
+			 * Mark the timer as running to synchronize with its
+			 * cancelation since we can't hold the mutex during the
+			 * callback.
+			 */
+			p_timer->timer_state = CL_TIMER_RUNNING;
+
+			/* Remove the item from the timer queue. */
+			cl_qlist_remove_item(&gp_timer_prov->queue,
+					     &p_timer->list_item);
+			pthread_mutex_unlock(&gp_timer_prov->mutex);
+			/* Invoke the callback. */
+			p_timer->pfn_callback((void *)p_timer->context);
+
+			/* Acquire the mutex again. */
+			pthread_mutex_lock(&gp_timer_prov->mutex);
+			/*
+			 * Only set the state to idle if the timer has not been accessed
+			 * from the callback
+			 */
+			if (p_timer->timer_state == CL_TIMER_RUNNING)
+				p_timer->timer_state = CL_TIMER_IDLE;
+
+			/*
+			 * Signal any thread trying to manipulate the timer
+			 * that expired.
+			 */
+			pthread_cond_signal(&p_timer->cond);
+		}
+	}
+	gp_timer_prov->thread = 0;
+	pthread_mutex_unlock(&gp_timer_prov->mutex);
+	pthread_exit(NULL);
+}
+
+/* Timer implementation. */
+void cl_timer_construct(IN cl_timer_t * const p_timer)
+{
+	memset(p_timer, 0, sizeof(cl_timer_t));
+	p_timer->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_timer_init(IN cl_timer_t * const p_timer,
+	      IN cl_pfn_timer_callback_t pfn_callback,
+	      IN const void *const context)
+{
+	CL_ASSERT(p_timer);
+	CL_ASSERT(pfn_callback);
+
+	cl_timer_construct(p_timer);
+
+	if (!gp_timer_prov)
+		return (CL_ERROR);
+
+	/* Store timer parameters. */
+	p_timer->pfn_callback = pfn_callback;
+	p_timer->context = context;
+
+	/* Mark the timer as idle. */
+	p_timer->timer_state = CL_TIMER_IDLE;
+
+	/* Create the condition variable that is used when cancelling a timer. */
+	pthread_cond_init(&p_timer->cond, NULL);
+
+	p_timer->state = CL_INITIALIZED;
+
+	return (CL_SUCCESS);
+}
+
+void cl_timer_destroy(IN cl_timer_t * const p_timer)
+{
+	CL_ASSERT(p_timer);
+	CL_ASSERT(cl_is_state_valid(p_timer->state));
+
+	if (p_timer->state == CL_INITIALIZED)
+		cl_timer_stop(p_timer);
+
+	p_timer->state = CL_UNINITIALIZED;
+
+	/* is it possible we have some threads waiting on the cond now? */
+	pthread_cond_broadcast(&p_timer->cond);
+	pthread_cond_destroy(&p_timer->cond);
+
+}
+
+/*
+ * Return TRUE if timeout value 1 is earlier than timeout value 2.
+ */
+static __inline boolean_t
+__cl_timer_is_earlier(IN struct timespec *p_timeout1,
+		      IN struct timespec *p_timeout2)
+{
+	return ((p_timeout1->tv_sec < p_timeout2->tv_sec) ||
+		((p_timeout1->tv_sec == p_timeout2->tv_sec) &&
+		 (p_timeout1->tv_nsec < p_timeout2->tv_nsec)));
+}
+
+/*
+ * Search for a timer with an earlier timeout than the one provided by
+ * the context.  Both the list item and the context are pointers to
+ * a cl_timer_t structure with valid timeouts.
+ */
+static cl_status_t
+__cl_timer_find(IN const cl_list_item_t * const p_list_item,
+		IN void *const context)
+{
+	cl_timer_t *p_in_list;
+	cl_timer_t *p_new;
+
+	CL_ASSERT(p_list_item);
+	CL_ASSERT(context);
+
+	p_in_list = (cl_timer_t *) p_list_item;
+	p_new = (cl_timer_t *) context;
+
+	CL_ASSERT(p_in_list->state == CL_INITIALIZED);
+	CL_ASSERT(p_new->state == CL_INITIALIZED);
+
+	CL_ASSERT(p_in_list->timer_state == CL_TIMER_QUEUED);
+
+	if (__cl_timer_is_earlier(&p_in_list->timeout, &p_new->timeout))
+		return (CL_SUCCESS);
+
+	return (CL_NOT_FOUND);
+}
+
+cl_status_t
+cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms)
+{
+	struct timeval curtime;
+	cl_list_item_t *p_list_item;
+	uint32_t delta_time = time_ms;
+
+	CL_ASSERT(p_timer);
+	CL_ASSERT(p_timer->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&gp_timer_prov->mutex);
+	/* Signal the timer provider thread to wake up. */
+	pthread_cond_signal(&gp_timer_prov->cond);
+
+	/* Remove the timer from the queue if currently queued. */
+	if (p_timer->timer_state == CL_TIMER_QUEUED)
+		cl_qlist_remove_item(&gp_timer_prov->queue,
+				     &p_timer->list_item);
+
+	/* Get the current time */
+#ifndef timerclear
+#define	timerclear(tvp)		(tvp)->tv_sec = (time_t)0, (tvp)->tv_usec = 0L
+#endif
+	timerclear(&curtime);
+	gettimeofday(&curtime, NULL);
+
+	/* do not do 0 wait ! */
+	/* if (delta_time < 1000.0) {delta_time = 1000;} */
+
+	/* Calculate the timeout. */
+	p_timer->timeout.tv_sec = curtime.tv_sec + (delta_time / 1000);
+	p_timer->timeout.tv_nsec =
+	    (curtime.tv_usec + ((delta_time % 1000) * 1000)) * 1000;
+
+	/* Add the timer to the queue. */
+	if (cl_is_qlist_empty(&gp_timer_prov->queue)) {
+		/* The timer list is empty.  Add to the head. */
+		cl_qlist_insert_head(&gp_timer_prov->queue,
+				     &p_timer->list_item);
+	} else {
+		/* Find the correct insertion place in the list for the timer. */
+		p_list_item = cl_qlist_find_from_tail(&gp_timer_prov->queue,
+						      __cl_timer_find, p_timer);
+
+		/* Insert the timer. */
+		cl_qlist_insert_next(&gp_timer_prov->queue, p_list_item,
+				     &p_timer->list_item);
+	}
+	/* Set the state. */
+	p_timer->timer_state = CL_TIMER_QUEUED;
+	pthread_mutex_unlock(&gp_timer_prov->mutex);
+
+	return (CL_SUCCESS);
+}
+
+void cl_timer_stop(IN cl_timer_t * const p_timer)
+{
+	CL_ASSERT(p_timer);
+	CL_ASSERT(p_timer->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&gp_timer_prov->mutex);
+	switch (p_timer->timer_state) {
+	case CL_TIMER_RUNNING:
+		/* Wait for the callback to complete. */
+		pthread_cond_wait(&p_timer->cond, &gp_timer_prov->mutex);
+		/* Timer could have been queued while we were waiting. */
+		if (p_timer->timer_state != CL_TIMER_QUEUED)
+			break;
+
+	case CL_TIMER_QUEUED:
+		/* Change the state of the timer. */
+		p_timer->timer_state = CL_TIMER_IDLE;
+		/* Remove the timer from the queue. */
+		cl_qlist_remove_item(&gp_timer_prov->queue,
+				     &p_timer->list_item);
+		/*
+		 * Signal the timer provider thread to move onto the
+		 * next timer in the queue.
+		 */
+		pthread_cond_signal(&gp_timer_prov->cond);
+		break;
+
+	case CL_TIMER_IDLE:
+		break;
+	}
+	pthread_mutex_unlock(&gp_timer_prov->mutex);
+}
+
+cl_status_t
+cl_timer_trim(IN cl_timer_t * const p_timer, IN const uint32_t time_ms)
+{
+	struct timeval curtime;
+	struct timespec newtime;
+	cl_status_t status;
+
+	CL_ASSERT(p_timer);
+	CL_ASSERT(p_timer->state == CL_INITIALIZED);
+
+	pthread_mutex_lock(&gp_timer_prov->mutex);
+
+	/* Get the current time */
+	timerclear(&curtime);
+	gettimeofday(&curtime, NULL);
+
+	/* Calculate the timeout. */
+	newtime.tv_sec = curtime.tv_sec + (time_ms / 1000);
+	newtime.tv_nsec = (curtime.tv_usec + ((time_ms % 1000) * 1000)) * 1000;
+
+	if (p_timer->timer_state == CL_TIMER_QUEUED) {
+		/* If the old time is earlier, do not trim it.  Just return. */
+		if (__cl_timer_is_earlier(&p_timer->timeout, &newtime)) {
+			pthread_mutex_unlock(&gp_timer_prov->mutex);
+			return (CL_SUCCESS);
+		}
+	}
+
+	/* Reset the timer to the new timeout value. */
+
+	pthread_mutex_unlock(&gp_timer_prov->mutex);
+	status = cl_timer_start(p_timer, time_ms);
+
+	return (status);
+}
+
+uint64_t cl_get_time_stamp(void)
+{
+	uint64_t tstamp;
+	struct timeval tv;
+
+	timerclear(&tv);
+	gettimeofday(&tv, NULL);
+
+	/* Convert the time of day into a microsecond timestamp. */
+	tstamp = ((uint64_t) tv.tv_sec * 1000000) + (uint64_t) tv.tv_usec;
+
+	return (tstamp);
+}
+
+uint32_t cl_get_time_stamp_sec(void)
+{
+	struct timeval tv;
+
+	timerclear(&tv);
+	gettimeofday(&tv, NULL);
+
+	return (tv.tv_sec);
+}
diff --git a/complib/cl_vector.c b/complib/cl_vector.c
new file mode 100644
index 0000000..d9bcf34
--- /dev/null
+++ b/complib/cl_vector.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	This file contains ivector and isvector implementations.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_vector.h>
+
+/*
+ * Define the maximum size for array pages in an cl_vector_t.
+ * This size is in objects, not bytes.
+ */
+#define SVEC_MAX_PAGE_SIZE 0x1000
+
+/*
+ * cl_vector_copy_general
+ *
+ * Description:
+ *	copy operator used when size of the user object doesn't fit one of the
+ *	other optimized copy functions.
+ *
+ * Inputs:
+ *	p_src - source for copy
+ *
+ * Outputs:
+ *	p_dest - destination for copy
+ *
+ * Returns:
+ *	None
+ *
+ */
+static void
+cl_vector_copy_general(OUT void *const p_dest,
+		       IN const void *const p_src, IN const size_t size)
+{
+	memcpy(p_dest, p_src, size);
+}
+
+/*
+ * cl_vector_copy8
+ *
+ * Description:
+ *	copy operator used when the user structure is only 8 bits long.
+ *
+ * Inputs:
+ *	p_src - source for copy
+ *
+ * Outputs:
+ *	p_dest - destination for copy
+ *
+ * Returns:
+ *	None
+ *
+ */
+static void
+cl_vector_copy8(OUT void *const p_dest,
+		IN const void *const p_src, IN const size_t size)
+{
+	CL_ASSERT(size == sizeof(uint8_t));
+	UNUSED_PARAM(size);
+
+	*(uint8_t *) p_dest = *(uint8_t *) p_src;
+}
+
+/*
+ * cl_vector_copy16
+ *
+ * Description:
+ *	copy operator used when the user structure is only 16 bits long.
+ *
+ * Inputs:
+ *	p_src - source for copy
+ *
+ * Outputs:
+ *	p_dest - destination for copy
+ *
+ * Returns:
+ *	None
+ *
+ */
+void
+cl_vector_copy16(OUT void *const p_dest,
+		 IN const void *const p_src, IN const size_t size)
+{
+	CL_ASSERT(size == sizeof(uint16_t));
+	UNUSED_PARAM(size);
+
+	*(uint16_t *) p_dest = *(uint16_t *) p_src;
+}
+
+/*
+ * cl_vector_copy32
+ *
+ * Description:
+ *	copy operator used when the user structure is only 32 bits long.
+ *
+ * Inputs:
+ *	p_src - source for copy
+ *
+ * Outputs:
+ *	p_dest - destination for copy
+ *
+ * Returns:
+ *	None
+ *
+ */
+void
+cl_vector_copy32(OUT void *const p_dest,
+		 IN const void *const p_src, IN const size_t size)
+{
+	CL_ASSERT(size == sizeof(uint32_t));
+	UNUSED_PARAM(size);
+
+	*(uint32_t *) p_dest = *(uint32_t *) p_src;
+}
+
+/*
+ * cl_vector_copy64
+ *
+ * Description:
+ *	copy operator used when the user structure is only 64 bits long.
+ *
+ * Inputs:
+ *	p_src - source for copy
+ *
+ * Outputs:
+ *	p_dest - destination for copy
+ *
+ * Returns:
+ *	None
+ *
+ */
+void
+cl_vector_copy64(OUT void *const p_dest,
+		 IN const void *const p_src, IN const size_t size)
+{
+	CL_ASSERT(size == sizeof(uint64_t));
+	UNUSED_PARAM(size);
+
+	*(uint64_t *) p_dest = *(uint64_t *) p_src;
+}
+
+void cl_vector_construct(IN cl_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+
+	memset(p_vector, 0, sizeof(cl_vector_t));
+
+	p_vector->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_vector_init(IN cl_vector_t * const p_vector,
+	       IN const size_t min_size,
+	       IN const size_t grow_size,
+	       IN const size_t element_size,
+	       IN cl_pfn_vec_init_t pfn_init OPTIONAL,
+	       IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,
+	       IN const void *const context)
+{
+	cl_status_t status = CL_SUCCESS;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(element_size);
+
+	cl_vector_construct(p_vector);
+
+	p_vector->grow_size = grow_size;
+	p_vector->element_size = element_size;
+	p_vector->pfn_init = pfn_init;
+	p_vector->pfn_dtor = pfn_dtor;
+	p_vector->context = context;
+
+	/*
+	 * Try to choose a smart copy operator
+	 * someday, we could simply let the users pass one in
+	 */
+	switch (element_size) {
+	case sizeof(uint8_t):
+		p_vector->pfn_copy = cl_vector_copy8;
+		break;
+
+	case sizeof(uint16_t):
+		p_vector->pfn_copy = cl_vector_copy16;
+		break;
+
+	case sizeof(uint32_t):
+		p_vector->pfn_copy = cl_vector_copy32;
+		break;
+
+	case sizeof(uint64_t):
+		p_vector->pfn_copy = cl_vector_copy64;
+		break;
+
+	default:
+		p_vector->pfn_copy = cl_vector_copy_general;
+		break;
+	}
+
+	/*
+	 * Set the state to initialized so that the call to set_size
+	 * doesn't assert.
+	 */
+	p_vector->state = CL_INITIALIZED;
+
+	/* Initialize the allocation list */
+	cl_qlist_init(&p_vector->alloc_list);
+
+	/* get the storage needed by the user */
+	if (min_size) {
+		status = cl_vector_set_size(p_vector, min_size);
+		if (status != CL_SUCCESS)
+			cl_vector_destroy(p_vector);
+	}
+
+	return (status);
+}
+
+void cl_vector_destroy(IN cl_vector_t * const p_vector)
+{
+	size_t i;
+	void *p_element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(cl_is_state_valid(p_vector->state));
+
+	/* Call the user's destructor for each element in the array. */
+	if (p_vector->state == CL_INITIALIZED) {
+		if (p_vector->pfn_dtor) {
+			for (i = 0; i < p_vector->size; i++) {
+				p_element = p_vector->p_ptr_array[i];
+				/* Sanity check! */
+				CL_ASSERT(p_element);
+				p_vector->pfn_dtor(p_element,
+						   (void *)p_vector->context);
+			}
+		}
+
+		/* Deallocate the pages */
+		while (!cl_is_qlist_empty(&p_vector->alloc_list))
+			free(cl_qlist_remove_head(&p_vector->alloc_list));
+
+		/* Destroy the page vector. */
+		if (p_vector->p_ptr_array) {
+			free(p_vector->p_ptr_array);
+			p_vector->p_ptr_array = NULL;
+		}
+	}
+
+	p_vector->state = CL_UNINITIALIZED;
+}
+
+cl_status_t
+cl_vector_at(IN const cl_vector_t * const p_vector,
+	     IN const size_t index, OUT void *const p_element)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Range check */
+	if (index >= p_vector->size)
+		return (CL_INVALID_PARAMETER);
+
+	cl_vector_get(p_vector, index, p_element);
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_vector_set(IN cl_vector_t * const p_vector,
+	      IN const size_t index, IN void *const p_element)
+{
+	cl_status_t status;
+	void *p_dest;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(p_element);
+
+	/* Determine if the vector has room for this element. */
+	if (index >= p_vector->size) {
+		/* Resize to accomodate the given index. */
+		status = cl_vector_set_size(p_vector, index + 1);
+
+		/* Check for failure on or before the given index. */
+		if ((status != CL_SUCCESS) && (p_vector->size < index))
+			return (status);
+	}
+
+	/* At this point, the array is guaranteed to be big enough */
+	p_dest = cl_vector_get_ptr(p_vector, index);
+	/* Sanity check! */
+	CL_ASSERT(p_dest);
+
+	/* Copy the data into the array */
+	p_vector->pfn_copy(p_dest, p_element, p_vector->element_size);
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_vector_set_capacity(IN cl_vector_t * const p_vector,
+		       IN const size_t new_capacity)
+{
+	size_t new_elements;
+	size_t alloc_size;
+	size_t i;
+	cl_list_item_t *p_buf;
+	void *p_new_ptr_array;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Do we have to do anything here? */
+	if (new_capacity <= p_vector->capacity) {
+		/* Nope */
+		return (CL_SUCCESS);
+	}
+
+	/* Allocate our pointer array. */
+	p_new_ptr_array = malloc(new_capacity * sizeof(void *));
+	if (!p_new_ptr_array)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(p_new_ptr_array, 0, new_capacity * sizeof(void *));
+
+	if (p_vector->p_ptr_array) {
+		/* Copy the old pointer array into the new. */
+		memcpy(p_new_ptr_array, p_vector->p_ptr_array,
+		       p_vector->capacity * sizeof(void *));
+
+		/* Free the old pointer array. */
+		free(p_vector->p_ptr_array);
+	}
+
+	/* Set the new array. */
+	p_vector->p_ptr_array = p_new_ptr_array;
+
+	/*
+	 * We have to add capacity to the array.  Determine how many
+	 * elements to add.
+	 */
+	new_elements = new_capacity - p_vector->capacity;
+	/* Determine the allocation size for the new array elements. */
+	alloc_size = new_elements * p_vector->element_size;
+
+	p_buf = (cl_list_item_t *) malloc(alloc_size + sizeof(cl_list_item_t));
+	if (!p_buf)
+		return (CL_INSUFFICIENT_MEMORY);
+	else
+		memset(p_buf, 0, alloc_size + sizeof(cl_list_item_t));
+
+	cl_qlist_insert_tail(&p_vector->alloc_list, p_buf);
+	/* Advance the buffer pointer past the list item. */
+	p_buf++;
+
+	for (i = p_vector->capacity; i < new_capacity; i++) {
+		p_vector->p_ptr_array[i] = p_buf;
+		/* Move the buffer pointer to the next element. */
+		p_buf = (void *)(((uint8_t *) p_buf) + p_vector->element_size);
+	}
+
+	/* Update the vector with the new capactity. */
+	p_vector->capacity = new_capacity;
+
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_vector_set_size(IN cl_vector_t * const p_vector, IN const size_t size)
+{
+	cl_status_t status;
+	size_t new_capacity;
+	size_t index;
+	void *p_element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	/* Check to see if the requested size is the same as the existing size. */
+	if (size == p_vector->size)
+		return (CL_SUCCESS);
+
+	/* Determine if the vector has room for this element. */
+	if (size >= p_vector->capacity) {
+		if (!p_vector->grow_size)
+			return (CL_INSUFFICIENT_MEMORY);
+
+		/* Calculate the new capacity, taking into account the grow size. */
+		new_capacity = size;
+		if (size % p_vector->grow_size) {
+			/* Round up to nearest grow_size boundary. */
+			new_capacity += p_vector->grow_size -
+			    (size % p_vector->grow_size);
+		}
+
+		status = cl_vector_set_capacity(p_vector, new_capacity);
+		if (status != CL_SUCCESS)
+			return (status);
+	}
+
+	/* Are we growing the array and need to invoke an initializer callback? */
+	if (size > p_vector->size && p_vector->pfn_init) {
+		for (index = p_vector->size; index < size; index++) {
+			/* Get a pointer to this element */
+			p_element = cl_vector_get_ptr(p_vector, index);
+
+			/* Call the user's initializer and trap failures. */
+			status =
+			    p_vector->pfn_init(p_element,
+					       (void *)p_vector->context);
+			if (status != CL_SUCCESS) {
+				/* Call the destructor for this object */
+				if (p_vector->pfn_dtor)
+					p_vector->pfn_dtor(p_element,
+							   (void *)p_vector->
+							   context);
+
+				/* Return the failure status to the caller. */
+				return (status);
+			}
+
+			/* The array just grew by one element */
+			p_vector->size++;
+		}
+	} else if (p_vector->pfn_dtor) {
+		/* The array is shrinking and there is a destructor to invoke. */
+		for (index = size; index < p_vector->size; index++) {
+			/* compute the address of the new elements */
+			p_element = cl_vector_get_ptr(p_vector, index);
+			/* call the user's destructor */
+			p_vector->pfn_dtor(p_element,
+					   (void *)p_vector->context);
+		}
+	}
+
+	p_vector->size = size;
+	return (CL_SUCCESS);
+}
+
+cl_status_t
+cl_vector_set_min_size(IN cl_vector_t * const p_vector,
+		       IN const size_t min_size)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	if (min_size > p_vector->size) {
+		/* We have to resize the array */
+		return (cl_vector_set_size(p_vector, min_size));
+	}
+
+	/* We didn't have to do anything */
+	return (CL_SUCCESS);
+}
+
+void
+cl_vector_apply_func(IN const cl_vector_t * const p_vector,
+		     IN cl_pfn_vec_apply_t pfn_callback,
+		     IN const void *const context)
+{
+	size_t i;
+	void *p_element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	for (i = 0; i < p_vector->size; i++) {
+		p_element = cl_vector_get_ptr(p_vector, i);
+		pfn_callback(i, p_element, (void *)context);
+	}
+}
+
+size_t
+cl_vector_find_from_start(IN const cl_vector_t * const p_vector,
+			  IN cl_pfn_vec_find_t pfn_callback,
+			  IN const void *const context)
+{
+	size_t i;
+	void *p_element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	for (i = 0; i < p_vector->size; i++) {
+		p_element = cl_vector_get_ptr(p_vector, i);
+		/* Invoke the callback */
+		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
+			break;
+	}
+	return (i);
+}
+
+size_t
+cl_vector_find_from_end(IN const cl_vector_t * const p_vector,
+			IN cl_pfn_vec_find_t pfn_callback,
+			IN const void *const context)
+{
+	size_t i;
+	void *p_element;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(pfn_callback);
+
+	i = p_vector->size;
+
+	while (i) {
+		/* Get a pointer to the element in the array. */
+		p_element = cl_vector_get_ptr(p_vector, --i);
+		CL_ASSERT(p_element);
+
+		/* Invoke the callback for the current element. */
+		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
+			return (i);
+	}
+
+	return (p_vector->size);
+}
diff --git a/complib/ib_statustext.c b/complib/ib_statustext.c
new file mode 100644
index 0000000..52b2adc
--- /dev/null
+++ b/complib/ib_statustext.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Defines string to decode ib_api_status_t return values.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <complib/cl_types.h>
+
+/* ib_api_status_t values above converted to text for easier printing. */
+const char *ib_error_str[] = {
+	"IB_SUCCESS",
+	"IB_INSUFFICIENT_RESOURCES",
+	"IB_INSUFFICIENT_MEMORY",
+	"IB_INVALID_PARAMETER",
+	"IB_INVALID_SETTING",
+	"IB_NOT_FOUND",
+	"IB_TIMEOUT",
+	"IB_CANCELED",
+	"IB_INTERRUPTED",
+	"IB_INVALID_PERMISSION",
+	"IB_UNSUPPORTED",
+	"IB_OVERFLOW",
+	"IB_MAX_MCAST_QPS_REACHED",
+	"IB_INVALID_QP_STATE",
+	"IB_INVALID_EEC_STATE",
+	"IB_INVALID_APM_STATE",
+	"IB_INVALID_PORT_STATE",
+	"IB_INVALID_STATE",
+	"IB_RESOURCE_BUSY",
+	"IB_INVALID_PKEY",
+	"IB_INVALID_LKEY",
+	"IB_INVALID_RKEY",
+	"IB_INVALID_MAX_WRS",
+	"IB_INVALID_MAX_SGE",
+	"IB_INVALID_CQ_SIZE",
+	"IB_INVALID_SERVICE_TYPE",
+	"IB_INVALID_GID",
+	"IB_INVALID_LID",
+	"IB_INVALID_GUID",
+	"IB_INVALID_CA_HANDLE",
+	"IB_INVALID_AV_HANDLE",
+	"IB_INVALID_CQ_HANDLE",
+	"IB_INVALID_EEC_HANDLE",
+	"IB_INVALID_QP_HANDLE",
+	"IB_INVALID_PD_HANDLE",
+	"IB_INVALID_MR_HANDLE",
+	"IB_INVALID_MW_HANDLE",
+	"IB_INVALID_RDD_HANDLE",
+	"IB_INVALID_MCAST_HANDLE",
+	"IB_INVALID_CALLBACK",
+	"IB_INVALID_AL_HANDLE",
+	"IB_INVALID_HANDLE",
+	"IB_ERROR",
+	"IB_REMOTE_ERROR",	/* Infiniband Access Layer */
+	"IB_VERBS_PROCESSING_DONE",
+	"IB_INVALID_WR_TYPE",
+	"IB_QP_IN_TIMEWAIT",
+	"IB_EE_IN_TIMEWAIT",
+	"IB_INVALID_PORT",
+	"IB_NOT_DONE",
+	"IB_UNKNOWN_ERROR"
+};
+
+/* ib_async_event_t values above converted to text for easier printing. */
+const char *ib_async_event_str[] = {
+	"IB_AE_SQ_ERROR",
+	"IB_AE_SQ_DRAINED",
+	"IB_AE_RQ_ERROR",
+	"IB_AE_CQ_ERROR",
+	"IB_AE_QP_FATAL",
+	"IB_AE_QP_COMM",
+	"IB_AE_QP_APM",
+	"IB_AE_EEC_FATAL",
+	"IB_AE_EEC_COMM",
+	"IB_AE_EEC_APM",
+	"IB_AE_LOCAL_FATAL",
+	"IB_AE_PKEY_TRAP",
+	"IB_AE_QKEY_TRAP",
+	"IB_AE_MKEY_TRAP",
+	"IB_AE_PORT_TRAP",
+	"IB_AE_SYSIMG_GUID_TRAP",
+	"IB_AE_BUF_OVERRUN",
+	"IB_AE_LINK_INTEGRITY",
+	"IB_AE_FLOW_CTRL_ERROR",
+	"IB_AE_BKEY_TRAP",
+	"IB_AE_QP_APM_ERROR",
+	"IB_AE_EEC_APM_ERROR",
+	"IB_AE_WQ_REQ_ERROR",
+	"IB_AE_WQ_ACCESS_ERROR",
+	"IB_AE_PORT_ACTIVE",	/* ACTIVE STATE */
+	"IB_AE_PORT_DOWN",	/* INIT", ARMED", DOWN */
+	"IB_AE_UNKNOWN"
+};
+
+const char *ib_wc_status_str[] = {
+	"IB_WCS_SUCCESS",
+	"IB_WCS_LOCAL_LEN_ERR",
+	"IB_WCS_LOCAL_OP_ERR",
+	"IB_WCS_LOCAL_EEC_OP_ERR",
+	"IB_WCS_LOCAL_PROTECTION_ERR",
+	"IB_WCS_WR_FLUSHED_ERR",
+	"IB_WCS_MEM_WINDOW_BIND_ERR",
+	"IB_WCS_REM_ACCESS_ERR",
+	"IB_WCS_REM_OP_ERR",
+	"IB_WCS_RNR_RETRY_ERR",
+	"IB_WCS_TIMEOUT_RETRY_ERR",
+	"IB_WCS_REM_INVALID_REQ_ERR",
+	"IB_WCS_REM_INVALID_RD_REQ_ERR",
+	"IB_WCS_INVALID_EECN",
+	"IB_WCS_INVALID_EEC_STATE",
+	"IB_WCS_UNMATCHED_RESPONSE",	/* InfiniBand Access Layer */
+	"IB_WCS_CANCELED",	/* InfiniBand Access Layer */
+	"IB_WCS_UNKNOWN"
+};
diff --git a/complib/libosmcomp.map b/complib/libosmcomp.map
new file mode 100644
index 0000000..788eb2a
--- /dev/null
+++ b/complib/libosmcomp.map
@@ -0,0 +1,154 @@
+OSMCOMP_2.3 {
+	global:
+		complib_init;
+		complib_exit;
+		cl_is_debug;
+		cl_disp_construct;
+		cl_disp_init;
+		cl_disp_destroy;
+		cl_disp_register;
+		cl_disp_unregister;
+		cl_disp_post;
+		cl_disp_shutdown;
+		cl_disp_get_queue_status;
+		cl_event_construct;
+		cl_event_init;
+		cl_event_destroy;
+		cl_event_signal;
+		cl_event_reset;
+		cl_event_wait_on;
+		cl_event_wheel_construct;
+		cl_event_wheel_init;
+		cl_event_wheel_init_ex;
+		cl_event_wheel_destroy;
+		cl_event_wheel_dump;
+		cl_event_wheel_reg;
+		cl_event_wheel_unreg;
+		cl_event_wheel_num_regs;
+		cl_qlist_insert_array_head;
+		cl_qlist_insert_array_tail;
+		cl_qlist_insert_list_head;
+		cl_qlist_insert_list_tail;
+		cl_is_item_in_qlist;
+		cl_qlist_find_next;
+		cl_qlist_find_prev;
+		cl_qlist_apply_func;
+		cl_qlist_move_items;
+		cl_list_construct;
+		cl_list_init;
+		cl_list_destroy;
+		cl_list_remove_object;
+		cl_is_object_in_list;
+		cl_list_insert_array_head;
+		cl_list_insert_array_tail;
+		cl_list_find_from_head;
+		cl_list_find_from_tail;
+		cl_list_apply_func;
+		cl_log_event;
+		cl_qmap_init;
+		cl_qmap_get;
+		cl_qmap_get_next;
+		cl_qmap_apply_func;
+		cl_qmap_insert;
+		cl_qmap_remove_item;
+		cl_qmap_remove;
+		cl_qmap_merge;
+		cl_qmap_delta;
+		cl_map_construct;
+		cl_map_init;
+		cl_map_destroy;
+		cl_map_insert;
+		cl_map_get;
+		cl_map_get_next;
+		cl_map_remove_item;
+		cl_map_remove;
+		cl_map_remove_all;
+		cl_map_merge;
+		cl_map_delta;
+		cl_fmap_init;
+		cl_fmap_get;
+		cl_fmap_get_next;
+		cl_fmap_apply_func;
+		cl_fmap_insert;
+		cl_fmap_remove_item;
+		cl_fmap_remove;
+		cl_fmap_merge;
+		cl_fmap_delta;
+		cl_qcpool_construct;
+		cl_qcpool_init;
+		cl_qcpool_destroy;
+		cl_qcpool_grow;
+		cl_qcpool_get;
+		cl_qcpool_get_tail;
+		cl_qpool_construct;
+		cl_qpool_init;
+		cl_cpool_construct;
+		cl_cpool_init;
+		cl_pool_construct;
+		cl_pool_init;
+		cl_ptr_vector_construct;
+		cl_ptr_vector_init;
+		cl_ptr_vector_destroy;
+		cl_ptr_vector_at;
+		cl_ptr_vector_set;
+		cl_ptr_vector_remove;
+		cl_ptr_vector_set_capacity;
+		cl_ptr_vector_set_size;
+		cl_ptr_vector_set_min_size;
+		cl_ptr_vector_apply_func;
+		cl_ptr_vector_find_from_start;
+		cl_ptr_vector_find_from_end;
+		cl_spinlock_construct;
+		cl_spinlock_init;
+		cl_spinlock_destroy;
+		cl_spinlock_acquire;
+		cl_spinlock_release;
+		cl_status_text;
+		cl_thread_construct;
+		cl_thread_init;
+		cl_thread_destroy;
+		cl_thread_suspend;
+		cl_thread_stall;
+		cl_proc_count;
+		cl_is_current_thread;
+		cl_thread_pool_construct;
+		cl_thread_pool_init;
+		cl_thread_pool_destroy;
+		cl_thread_pool_signal;
+		__cl_timer_prov_create;
+		__cl_timer_prov_destroy;
+		cl_timer_construct;
+		cl_timer_init;
+		cl_timer_destroy;
+		cl_timer_start;
+		cl_timer_stop;
+		cl_timer_trim;
+		cl_get_time_stamp;
+		cl_get_time_stamp_sec;
+		cl_vector_copy_general;
+		cl_vector_copy16;
+		cl_vector_copy32;
+		cl_vector_copy64;
+		cl_vector_construct;
+		cl_vector_init;
+		cl_vector_destroy;
+		cl_vector_at;
+		cl_vector_set;
+		cl_vector_set_capacity;
+		cl_vector_set_size;
+		cl_vector_set_min_size;
+		cl_vector_apply_func;
+		cl_vector_find_from_start;
+		cl_vector_find_from_end;
+		cl_atomic_spinlock;
+		cl_atomic_dec;
+		ib_error_str;
+		ib_async_event_str;
+		ib_wc_status_str;
+		open_node_name_map;
+		close_node_name_map;
+		parse_node_map;
+		remap_node_name;
+		clean_nodedesc;
+	local: *;
+};
diff --git a/complib/libosmcomp.ver b/complib/libosmcomp.ver
new file mode 100644
index 0000000..f076585
--- /dev/null
+++ b/complib/libosmcomp.ver
@@ -0,0 +1,9 @@
+# In this file we track the current API version
+# of the complib library interface
+# The version is built of the following
+# tree numbers:
+# API_REV:RUNNING_REV:AGE
+# API_REV - advance on any added API
+# RUNNING_REV - advance any change to the vendor files
+# AGE - number of backward versions the API still supports
+LIBVERSION=2:4:0
diff --git a/config/config.guess b/config/config.guess
new file mode 100755
index 0000000..202f698
--- /dev/null
+++ b/config/config.guess
@@ -0,0 +1,1548 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-09-28'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per at bothner.com>.
+# Please send patches to <config-patches at gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+if [ "${UNAME_SYSTEM}" = "Linux" ] ; then
+	eval $set_cc_for_build
+	cat << EOF > $dummy.c
+	#include <features.h>
+	#ifdef __UCLIBC__
+	# ifdef __UCLIBC_CONFIG_VERSION__
+	LIBC=uclibc __UCLIBC_CONFIG_VERSION__
+	# else
+	LIBC=uclibc
+	# endif
+	#else
+	LIBC=gnu
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'`
+fi
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd | genuineintel)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld"
+		exit ;;
+	esac
+	# This should get integrated into the C code below, but now we hack
+	if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel at ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes at openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf at swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/config.sub b/config/config.sub
new file mode 100755
index 0000000..66f218c
--- /dev/null
+++ b/config/config.sub
@@ -0,0 +1,1695 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-09-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx | dvp \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+        cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsEE* | ee | ps2)
+		basic_machine=mips64r5900el-scei
+		case $os in
+		    -linux*)
+			;;
+		    *)
+			os=-elf
+			;;
+		esac
+		;;
+	iop)
+		basic_machine=mipsel-scei
+		os=-irx
+		;;
+	dvp)
+		basic_machine=dvp-scei
+		os=-elf
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/depcomp b/config/depcomp
new file mode 100755
index 0000000..e5f9736
--- /dev/null
+++ b/config/depcomp
@@ -0,0 +1,589 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2007-03-29.01
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva at dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+    # That's a tab and a space in the [].
+    sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no
+  for arg in "$@"; do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix="`echo $object | sed 's/^.*\././'`"
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  "$@" || exit $?
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+	set fnord "$@"
+	shift
+	shift
+	;;
+    *)
+	set fnord "$@" "$arg"
+	shift
+	shift
+	;;
+    esac
+  done
+  "$@" -E |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config/install-sh b/config/install-sh
new file mode 100755
index 0000000..a5897de
--- /dev/null
+++ b/config/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	-*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config/libtool.m4 b/config/libtool.m4
new file mode 100644
index 0000000..2f42cf8
--- /dev/null
+++ b/config/libtool.m4
@@ -0,0 +1,7370 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+		   [m4_fatal([Libtool version $1 or higher is required],
+		             63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\	*)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+_LT_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+	[m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+	[tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+	   m4_quote(lt_decl_varnames),
+	m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+					   [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+	dnl If the libtool generation code has been placed in $CONFIG_LT,
+	dnl instead of duplicating it all over again into config.status,
+	dnl then we will have config.status run $CONFIG_LT later, so it
+	dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+  ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool at gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+if test "$no_create" != yes; then
+  lt_cl_success=:
+  test "$silent" = yes &&
+    lt_config_lt_args="$lt_config_lt_args --quiet"
+  exec AS_MESSAGE_LOG_FD>/dev/null
+  $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+  exec AS_MESSAGE_LOG_FD>>config.log
+  $lt_cl_success || AS_EXIT(1)
+fi
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_XSI_SHELLFNS
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],			[_LT_LANG(C)],
+  [C++],		[_LT_LANG(CXX)],
+  [Java],		[_LT_LANG(GCJ)],
+  [Fortran 77],		[_LT_LANG(F77)],
+  [Fortran],		[_LT_LANG(FC)],
+  [Windows Resource],	[_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi])
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+	[lt_cv_ld_exported_symbols_list=yes],
+	[lt_cv_ld_exported_symbols_list=no])
+	LDFLAGS="$save_LDFLAGS"
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[[012]]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=echo
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+	     [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+	 [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<_LT_EOF
+[$]*
+_LT_EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+  if test "X${echo_test_string+set}" != Xset; then
+    # find a string as large as possible, as long as the shell can cope with it
+    for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+      then
+        break
+      fi
+    done
+  fi
+
+  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+     test "X$echo_testing_string" = "X$echo_test_string"; then
+    :
+  else
+    # The Solaris, AIX, and Digital Unix default echo programs unquote
+    # backslashes.  This makes it impossible to quote backslashes using
+    #   echo "$something" | sed 's/\\/\\\\/g'
+    #
+    # So, first we look for a working echo in the user's PATH.
+
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for dir in $PATH /usr/ucb; do
+      IFS="$lt_save_ifs"
+      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        ECHO="$dir/echo"
+        break
+      fi
+    done
+    IFS="$lt_save_ifs"
+
+    if test "X$ECHO" = Xecho; then
+      # We didn't find a better echo, so look for alternatives.
+      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        # This shell has a builtin print -r that does the trick.
+        ECHO='print -r'
+      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+	   test "X$CONFIG_SHELL" != X/bin/ksh; then
+        # If we have ksh, try running configure again with it.
+        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+        export ORIGINAL_CONFIG_SHELL
+        CONFIG_SHELL=/bin/ksh
+        export CONFIG_SHELL
+        exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+      else
+        # Try using printf.
+        ECHO='printf %s\n'
+        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	  # Cool, printf works
+	  :
+        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	  export CONFIG_SHELL
+	  SHELL="$CONFIG_SHELL"
+	  export SHELL
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        else
+	  # maybe with a smaller string...
+	  prev=:
+
+	  for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+	    then
+	      break
+	    fi
+	    prev="$cmd"
+	  done
+
+	  if test "$prev" != 'sed 50q "[$]0"'; then
+	    echo_test_string=`eval $prev`
+	    export echo_test_string
+	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+	  else
+	    # Oops.  We lost completely, so just stick with echo.
+	    ECHO=echo
+	  fi
+        fi
+      fi
+    fi
+  fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+    [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  ppc64-*linux*|powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  ppc*-*linux*|powerpc*-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+	  [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+	    [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen="dlopen"],
+	  [AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+	    [AC_CHECK_LIB([svld], [dlopen],
+		  [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+	      [AC_CHECK_LIB([dld], [dld_link],
+		    [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+	  lt_cv_dlopen_self_static, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+	 [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+	 [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+	 [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+	[Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+	[], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  # Handle Gentoo/FreeBSD as it was Linux
+  case $host_vendor in
+    gentoo)
+      version_type=linux ;;
+    *)
+      version_type=freebsd-$objformat ;;
+  esac
+
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+    linux)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+      soname_spec='${libname}${release}${shared_ext}$major'
+      need_lib_prefix=no
+      need_version=no
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # Some binutils ld are patched to set DT_RUNPATH
+  save_LDFLAGS=$LDFLAGS
+  save_libdir=$libdir
+  eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+       LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+    [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+       [shlibpath_overrides_runpath=yes])])
+  LDFLAGS=$save_LDFLAGS
+  libdir=$save_libdir
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+	[Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    if test "$host_cpu" != ia64; then
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64 which still supported -KPIC.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  xlc* | xlC*)
+	    # IBM XL 8.0 on PPC
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd*)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl*)
+	# IBM XL C 8.0/Fortran 10.1 on PPC
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)
+	  # Sun C 5.9
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  ;;
+	*Sun\ F*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+	[Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+	[Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw* | cegcc*)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+	  tmp_sharedflag='--shared' ;;
+	xl[[cC]]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 _LT_SYS_MODULE_PATH_AIX
+	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	  # Exported symbols can be pulled into shared objects from archives
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	*)
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        AC_LINK_IFELSE(int foo(void) {},
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+        )
+        LDFLAGS="$save_LDFLAGS"
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	     _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	     ;;
+	   *)
+	     _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $RM conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+        _LT_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+        then
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $RM conftest*
+      AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+    [[If ld is used when linking, flag to hardcode $libdir into a binary
+    during linking.  This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+    [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag="$shared_flag "'${wl}-G'
+	  fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test "$aix_use_runtimelinking" = yes; then
+	      shared_flag='${wl}-G'
+	    else
+	      shared_flag='${wl}-bM:SRE'
+	    fi
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    _LT_SYS_MODULE_PATH_AIX
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	    # This is similar to how AIX traditionally builds its shared
+	    # libraries.
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+        # as there is no search path for DLLs.
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+        _LT_TAGVAR(always_export_symbols, $1)=no
+        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+          # If the export-symbols file already is a .def file (1st line
+          # is EXPORTS), use it as is; otherwise, prepend...
+          _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    cp $export_symbols $output_objdir/$soname.def;
+          else
+	    echo EXPORTS > $output_objdir/$soname.def;
+	    cat $export_symbols >> $output_objdir/$soname.def;
+          fi~
+          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+        else
+          _LT_TAGVAR(ld_shlibs, $1)=no
+        fi
+        ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      freebsd[[12]]*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      gnu*)
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test $with_gnu_ld = no; then
+	        case $host_cpu in
+	          hppa*64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test "$with_gnu_ld" = no; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	      else
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+	      fi
+	    fi
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+	    ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$RANLIB $oldlib'
+	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 will use weak symbols
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  xl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    if test "x$supports_anon_versioning" = xyes; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+		echo "local: *; };" >> $output_objdir/$libname.ver~
+		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='echo'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+	;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      openbsd*)
+	if test -f /usr/libexec/ld.so; then
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=echo
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+		;;
+	      *)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	          echo "-hidden">> $lib.exp~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $RM $lib.exp'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+		;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  *)
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	      case $host in
+	        osf3*)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	        *)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	    case $host_os in
+	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands `-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+	    output_verbose_link_cmd='echo'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      else
+	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	        # platform.
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      fi
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+	      case $host_os in
+		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+		*)
+		  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We can NOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+	_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+	_LT_TAGVAR(link_all_deplibs, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	  *)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+	   else
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+	   _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+	 else
+	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+	 fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+	   _LT_TAGVAR(predep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+	   _LT_TAGVAR(postdep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${F77-"f77"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${FC-"f95"}
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]+=\$[2]"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+    ;;
+  esac
+])
diff --git a/config/ltmain.sh b/config/ltmain.sh
new file mode 100755
index 0000000..0634c4b
--- /dev/null
+++ b/config/ltmain.sh
@@ -0,0 +1,8461 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.6
+# Written by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#     --config             show all configuration variables
+#     --debug              enable verbose shell tracing
+# -n, --dry-run            display commands without modifying any files
+#     --features           display basic configuration information and exit
+#     --mode=MODE          use operation mode MODE
+#     --preserve-dup-deps  don't remove duplicate dependency libraries
+#     --quiet, --silent    don't print informational messages
+#     --tag=TAG            use configuration variables from tag TAG
+# -v, --verbose            print informational messages (default)
+#     --version            print version information
+# -h, --help               print short or long help message
+#
+# MODE must be one of the following:
+#
+#       clean              remove files from the build directory
+#       compile            compile a source file into a libtool object
+#       execute            automatically set library path, then run a program
+#       finish             complete the installation of libtool libraries
+#       install            install libraries or executables
+#       link               create a library or an executable
+#       uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#       host-triplet:	$host
+#       shell:		$SHELL
+#       compiler:		$LTCC
+#       compiler flags:		$LTCFLAGS
+#       linker:		$LD (gnu? $with_gnu_ld)
+#       $progname:		(GNU libtool) 2.2.6
+#       automake:		$automake_version
+#       autoconf:		$autoconf_version
+#
+# Report bugs to <bug-libtool at gnu.org>.
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=2.2.6
+TIMESTAMP=""
+package_revision=1.3012
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+: ${CP="cp -f"}
+: ${ECHO="echo"}
+: ${EGREP="/usr/bin/grep -E"}
+: ${FGREP="/usr/bin/grep -F"}
+: ${GREP="/usr/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/opt/local/bin/gsed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+# In the unlikely event $progname began with a '-', it would play havoc with
+# func_echo (imagine progname=-n), so we prepend ./ in that case:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+case $progname in
+  -*) progname=./$progname ;;
+esac
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=:
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "X$my_tmpdir" | $Xsed
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "X$1" | $Xsed \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $SED -n '/^# Usage:/,/# -h/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    $ECHO
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help
+# Echo long help message to standard output and exit.
+func_help ()
+{
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+	p
+     }' < "$progpath"
+    exit $?
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    func_error "missing argument for $1"
+    exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+# Check that we have a working $ECHO.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell, and then maybe $ECHO will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+# Same for EGREP, and just to be sure, do LTCC as well
+if test "x$EGREP" = x ; then
+    EGREP=egrep
+fi
+if test "x$LTCC" = x ; then
+    LTCC=${CC-gcc}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    $ECHO "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $ECHO "enable shared libraries"
+    else
+      $ECHO "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $ECHO "enable static libraries"
+    else
+      $ECHO "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# Parse options once, thoroughly.  This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+  # Shorthand for --mode=foo, only valid as the first argument
+  case $1 in
+  clean|clea|cle|cl)
+    shift; set dummy --mode clean ${1+"$@"}; shift
+    ;;
+  compile|compil|compi|comp|com|co|c)
+    shift; set dummy --mode compile ${1+"$@"}; shift
+    ;;
+  execute|execut|execu|exec|exe|ex|e)
+    shift; set dummy --mode execute ${1+"$@"}; shift
+    ;;
+  finish|finis|fini|fin|fi|f)
+    shift; set dummy --mode finish ${1+"$@"}; shift
+    ;;
+  install|instal|insta|inst|ins|in|i)
+    shift; set dummy --mode install ${1+"$@"}; shift
+    ;;
+  link|lin|li|l)
+    shift; set dummy --mode link ${1+"$@"}; shift
+    ;;
+  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+    shift; set dummy --mode uninstall ${1+"$@"}; shift
+    ;;
+  esac
+
+  # Parse non-mode specific arguments:
+  while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+      --config)		func_config					;;
+
+      --debug)		preserve_args="$preserve_args $opt"
+			func_echo "enabling shell trace mode"
+			opt_debug='set -x'
+			$opt_debug
+			;;
+
+      -dlopen)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			execute_dlfiles="$execute_dlfiles $1"
+			shift
+			;;
+
+      --dry-run | -n)	opt_dry_run=:					;;
+      --features)       func_features					;;
+      --finish)		mode="finish"					;;
+
+      --mode)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			case $1 in
+			  # Valid mode arguments:
+			  clean)	;;
+			  compile)	;;
+			  execute)	;;
+			  finish)	;;
+			  install)	;;
+			  link)		;;
+			  relink)	;;
+			  uninstall)	;;
+
+			  # Catch anything else as an error
+			  *) func_error "invalid argument for $opt"
+			     exit_cmd=exit
+			     break
+			     ;;
+		        esac
+
+			mode="$1"
+			shift
+			;;
+
+      --preserve-dup-deps)
+			opt_duplicate_deps=:				;;
+
+      --quiet|--silent)	preserve_args="$preserve_args $opt"
+			opt_silent=:
+			;;
+
+      --verbose| -v)	preserve_args="$preserve_args $opt"
+			opt_silent=false
+			;;
+
+      --tag)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			preserve_args="$preserve_args $opt $1"
+			func_enable_tag "$1"	# tagname is set here
+			shift
+			;;
+
+      # Separate optargs to long options:
+      -dlopen=*|--mode=*|--tag=*)
+			func_opt_split "$opt"
+			set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+			shift
+			;;
+
+      -\?|-h)		func_usage					;;
+      --help)		opt_help=:					;;
+      --version)	func_version					;;
+
+      -*)		func_fatal_help "unrecognized option \`$opt'"	;;
+
+      *)		nonopt="$opt"
+			break
+			;;
+    esac
+  done
+
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      ;;
+  esac
+
+  # Having warned about all mis-specified options, bail out if
+  # anything was wrong.
+  $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+$opt_help || {
+  # Sanity checks first:
+  func_check_version_match
+
+  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+    func_fatal_configuration "not configured to build any kind of library"
+  fi
+
+  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+  # Darwin sucks
+  eval std_shrext=\"$shrext_cmds\"
+
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    func_error "unrecognized option \`-dlopen'"
+    $ECHO "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_ltwrapper_scriptname_result=""
+    if func_ltwrapper_executable_p "$1"; then
+	func_dirname_and_basename "$1" "" "."
+	func_stripname '' '.exe' "$func_basename_result"
+	func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+    fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+        func_quote_for_eval "$arg"
+	CC_quoted="$CC_quoted $func_quote_for_eval_result"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_quote_for_eval "$arg"
+	      CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	    done
+	    case "$@ " in
+	      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          pie_flag="$pie_flag $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_quote_for_eval "$arg"
+	    lastarg="$lastarg $func_quote_for_eval_result"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.obj | *.sx)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      removelist="$removelist $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist="$removelist $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$mode'"
+        ;;
+    esac
+
+    $ECHO
+    $ECHO "Try \`$progname --help' for more information about other modes."
+
+    exit $?
+}
+
+  # Now that we've collected a possible --mode arg, show help if necessary
+  $opt_help && func_mode_help
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_quote_for_eval "$file"
+      args="$args $func_quote_for_eval_result"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	$ECHO "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    $ECHO "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $ECHO "   $libdir"
+    done
+    $ECHO
+    $ECHO "If you ever happen to want to link against installed libraries"
+    $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
+    $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $ECHO "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $ECHO "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $ECHO "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $ECHO "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $ECHO "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $ECHO "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $ECHO
+
+    $ECHO "See any operating system documentation about shared libraries for"
+    case $host in
+      solaris2.[6789]|solaris2.1[0-9])
+        $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	$ECHO "pages."
+	;;
+      *)
+        $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
+        ;;
+    esac
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog="$install_prog$func_quote_for_eval_result"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	case " $install_prog " in
+	*[\\\ /]cp\ *) ;;
+	*) prev=$arg ;;
+	esac
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog="$install_prog $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_verbose "extracting global C symbols from \`$progfile'"
+	    $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	      case $host in
+	        *cygwin | *mingw* | *cegcc* )
+	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+	  $opt_dry_run || {
+	    eval '$ECHO ": $name " >> "$nlist"'
+	    eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	  }
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+"
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc* )
+	    $ECHO >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs.  */"
+	    lt_dlsym_const= ;;
+	  *osf5*)
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+	    lt_dlsym_const= ;;
+	  *)
+	    lt_dlsym_const=const ;;
+	  esac
+
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) symtab_cflags="$symtab_cflags $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+
+# func_emit_wrapper_part1 [arg=no]
+#
+# Emit the first part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part1 ()
+{
+	func_emit_wrapper_part1_arg1=no
+	if test -n "$1" ; then
+	  func_emit_wrapper_part1_arg1=$1
+	fi
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    ECHO=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$ECHO works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$ECHO will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+	$ECHO "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+"
+}
+# end: func_emit_wrapper_part1
+
+# func_emit_wrapper_part2 [arg=no]
+#
+# Emit the second part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part2 ()
+{
+	func_emit_wrapper_part2_arg1=no
+	if test -n "$1" ; then
+	  func_emit_wrapper_part2_arg1=$1
+	fi
+
+	$ECHO "\
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2* | *-cegcc*)
+	  $ECHO "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $ECHO "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+# end: func_emit_wrapper_part2
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=no
+	if test -n "$1" ; then
+	  func_emit_wrapper_arg1=$1
+	fi
+
+	# split this up so that func_emit_cwrapperexe_src
+	# can call each part independently.
+	func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
+	func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin.  Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+  func_to_host_path_result="$1"
+  if test -n "$1" ; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        case $build in
+          *mingw* ) # actually, msys
+            # awkward: cmd appends spaces to result
+            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+            func_to_host_path_tmp1=`( cmd //c echo "$1" |\
+              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_path_tmp1=`cygpath -w "$1"`
+            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # Unfortunately, winepath does not exit with a non-zero
+            # error code, so we are forced to check the contents of
+            # stdout. On the other hand, if the command is not
+            # found, the shell will set an exit code of 127 and print
+            # *an error message* to stdout. So we must check for both
+            # error code of zero AND non-empty stdout, which explains
+            # the odd construction:
+            func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+            if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+              func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+                $SED -e "$lt_sed_naive_backslashify"`
+            else
+              # Allow warning below.
+              func_to_host_path_result=""
+            fi
+            ;;
+        esac
+        if test -z "$func_to_host_path_result" ; then
+          func_error "Could not determine host path corresponding to"
+          func_error "  '$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback:
+          func_to_host_path_result="$1"
+        fi
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+#
+# Path separators are also converted from $build format to
+# $host format. If ARG begins or ends with a path separator
+# character, it is preserved (but converted to $host format)
+# on output.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+  func_to_host_pathlist_result="$1"
+  if test -n "$1" ; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        # Remove leading and trailing path separator characters from
+        # ARG. msys behavior is inconsistent here, cygpath turns them
+        # into '.;' and ';.', and winepath ignores them completely.
+        func_to_host_pathlist_tmp2="$1"
+        # Once set for this call, this variable should not be
+        # reassigned. It is used in tha fallback case.
+        func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
+          $SED -e 's|^:*||' -e 's|:*$||'`
+        case $build in
+          *mingw* ) # Actually, msys.
+            # Awkward: cmd appends spaces to result.
+            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+            func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
+              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
+            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # unfortunately, winepath doesn't convert pathlists
+            func_to_host_pathlist_result=""
+            func_to_host_pathlist_oldIFS=$IFS
+            IFS=:
+            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+              IFS=$func_to_host_pathlist_oldIFS
+              if test -n "$func_to_host_pathlist_f" ; then
+                func_to_host_path "$func_to_host_pathlist_f"
+                if test -n "$func_to_host_path_result" ; then
+                  if test -z "$func_to_host_pathlist_result" ; then
+                    func_to_host_pathlist_result="$func_to_host_path_result"
+                  else
+                    func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
+                  fi
+                fi
+              fi
+              IFS=:
+            done
+            IFS=$func_to_host_pathlist_oldIFS
+            ;;
+        esac
+        if test -z "$func_to_host_pathlist_result" ; then
+          func_error "Could not determine the host path(s) corresponding to"
+          func_error "  '$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback. This may break if $1 contains DOS-style drive
+          # specifications. The fix is not to complicate the expression
+          # below, but for the user to provide a working wine installation
+          # with winepath so that path translation in the cross-to-mingw
+          # case works properly.
+          lt_replace_pathsep_nix_to_dos="s|:|;|g"
+          func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+            $SED -e "$lt_replace_pathsep_nix_to_dos"`
+        fi
+        # Now, add the leading and trailing path separators back
+        case "$1" in
+          :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+            ;;
+        esac
+        case "$1" in
+          *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
+            ;;
+        esac
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_pathlist
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+#  define HAVE_SETENV
+#  ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+#  endif
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+#ifdef _MSC_VER
+# define S_IXUSR _S_IEXEC
+# define stat _stat
+# ifndef _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifdef __CYGWIN__
+# define FOPEN_WB "wb"
+#endif
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    (void) vfprintf (stderr, fmt, args);
+    va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_opt_process_env_set (const char *arg);
+void lt_opt_process_env_prepend (const char *arg);
+void lt_opt_process_env_append (const char *arg);
+int lt_split_name_value (const char *arg, char** name, char** value);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+
+static const char *script_text_part1 =
+EOF
+
+	    func_emit_wrapper_part1 yes |
+	        $SED -e 's/\([\\"]\)/\\\1/g' \
+	             -e 's/^/  "/' -e 's/$/\\n"/'
+	    echo ";"
+	    cat <<EOF
+
+static const char *script_text_part2 =
+EOF
+	    func_emit_wrapper_part2 yes |
+	        $SED -e 's/\([\\"]\)/\\\1/g' \
+	             -e 's/^/  "/' -e 's/$/\\n"/'
+	    echo ";"
+
+	    cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test "$fast_install" = yes; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len     = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt          = LTWRAPPER_OPTION_PREFIX "env-set";
+  /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt      = LTWRAPPER_OPTION_PREFIX "env-prepend";
+  /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len  = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt       = LTWRAPPER_OPTION_PREFIX "env-append";
+  /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  printf ("%s", script_text_part1);
+	  printf ("%s", script_text_part2);
+	  return 0;
+	}
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+			  tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+			  actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+			  target_name));
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+        {
+          if (argv[i][env_set_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_set_opt_len + 1;
+              lt_opt_process_env_set (p);
+            }
+          else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_set (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_set_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+        {
+          if (argv[i][env_prepend_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_prepend_opt_len + 1;
+              lt_opt_process_env_prepend (p);
+            }
+          else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_prepend_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+        {
+          if (argv[i][env_append_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_append_opt_len + 1;
+              lt_opt_process_env_append (p);
+            }
+          else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_append (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_append_opt);
+          continue;
+        }
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
+			  wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal ("getcwd failed");
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+			      tmp_pathspec));
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  char *errstr = strerror (errno);
+	  lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal ("Could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+int
+lt_split_name_value (const char *arg, char** name, char** value)
+{
+  const char *p;
+  int len;
+  if (!arg || !*arg)
+    return 1;
+
+  p = strchr (arg, (int)'=');
+
+  if (!p)
+    return 1;
+
+  *value = xstrdup (++p);
+
+  len = strlen (arg) - strlen (*value);
+  *name = XMALLOC (char, len);
+  strncpy (*name, arg, len-1);
+  (*name)[len - 1] = '\0';
+
+  return 0;
+}
+
+void
+lt_opt_process_env_set (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
+    }
+
+  lt_setenv (name, value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_opt_process_env_prepend (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+  char *new_value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
+    }
+
+  new_value = lt_extend_str (getenv (name), value, 0);
+  lt_setenv (name, new_value);
+  XFREE (new_value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_opt_process_env_append (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+  char *new_value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
+    }
+
+  new_value = lt_extend_str (getenv (name), value, 1);
+  lt_setenv (name, new_value);
+  XFREE (new_value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  weak_libs="$weak_libs $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname '-L' '' "$arg"
+	dir=$func_stripname_result
+	if test -z "$dir"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between \`-L' and \`$1'"
+	  else
+	    func_fatal_error "need path for \`-L' option"
+	  fi
+	fi
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+	  linker_flags="$linker_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_duplicate_deps ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  case $lib in
+	  *.la)	func_source "$lib" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+            deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) deplibs="$deplibs $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags="$compiler_flags $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    dir=$func_stripname_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		$ECHO
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because the file extensions .$libext of this argument makes me believe"
+		$ECHO "*** that it is just a static archive that I should not use here."
+	      else
+		$ECHO
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	    # Keep a list of preopened convenience libraries to check
+	    # that they are being used correctly in the link pass.
+	    test -z "$libdir" && \
+		dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         newlib_search_path="$newlib_search_path $func_stripname_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) temp_rpath="$temp_rpath$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc*)
+	      # No point in relinking DLLs because paths are not encoded
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    $ECHO
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    libname=`eval "\\$ECHO \"$libname_spec\""`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  $ECHO
+			  $ECHO "*** And there doesn't seem to be a static archive available"
+			  $ECHO "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$dir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    $ECHO
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    $ECHO "*** I have the capability to make that library automatically link in when"
+	    $ECHO "*** you link to this library.  But I can only do this if you have a"
+	    $ECHO "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      $ECHO "*** But as you try to build a module library, libtool will still create "
+	      $ECHO "*** a static module, that should work as long as the dlopening application"
+	      $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		$ECHO
+		$ECHO "*** However, this would only work if libtool was able to extract symbol"
+		$ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		$ECHO "*** not find such a program.  So, this module is probably useless."
+		$ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_dirname "$deplib" "" "."
+		dir="$func_dirname_result"
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  $ECHO
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs="$libobjs $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
+      #	deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  libname=`eval "\\$ECHO \"$libname_spec\""`
+		  deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    $ECHO
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    $ECHO "*** I have the capability to make that library automatically link in when"
+		    $ECHO "*** you link to this library.  But I can only do this if you have a"
+		    $ECHO "*** shared version of the library, which I believe you do not have"
+		    $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+		    $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval "\\$ECHO \"$libname_spec\""`
+		    deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      $ECHO
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      $ECHO "*** I have the capability to make that library automatically link in when"
+		      $ECHO "*** you link to this library.  But I can only do this if you have a"
+		      $ECHO "*** shared version of the library, which you do not appear to have"
+		      $ECHO "*** because a test_compile did reveal that the linker did not use this one"
+		      $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  $ECHO
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  $ECHO "*** make it link in!  You will probably need to install it or some"
+		  $ECHO "*** library that it depends on before this library will be fully"
+		  $ECHO "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$ECHO
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$ECHO
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
+	      -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+	    done
+	  fi
+	  if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[	 ]//g' |
+	     $GREP . >/dev/null; then
+	    $ECHO
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      $ECHO "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    $ECHO "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	  fi
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    $ECHO
+	    $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    $ECHO "*** a static module, that should work as long as the dlopening"
+	    $ECHO "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      $ECHO
+	      $ECHO "*** However, this would only work if libtool was able to extract symbol"
+	      $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      $ECHO "*** not find such a program.  So, this module is probably useless."
+	      $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    $ECHO "*** The inter-library dependencies that have been dropped here will be"
+	    $ECHO "*** automatically added whenever a program is linked with this library"
+	    $ECHO "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      $ECHO
+	      $ECHO "*** Since this library must not contain undefined symbols,"
+	      $ECHO "*** because either the platform does not support them or"
+	      $ECHO "*** it was explicitly requested with -no-undefined,"
+	      $ECHO "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+	    else
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  delfiles="$delfiles $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      eval cmd=\"$cmd\"
+	      func_len " $cmd"
+	      len=$func_len_result
+	      if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    tmp_deplibs="$tmp_deplibs $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval test_cmds=\"$archive_expsym_cmds\"
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval test_cmds=\"$archive_cmds\"
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    $ECHO 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    $ECHO ')' >> $output
+	    delfiles="$delfiles $output"
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    delfiles="$delfiles $output"
+	    output=$firstobj\"$file_list_spec$output\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval test_cmds=\"$reload_cmds\"
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=$obj
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+	      if test -n "$last_robj"; then
+	        eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+	      fi
+	      delfiles="$delfiles $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+	      if test -n "$last_robj"; then
+		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval cmds=\"\$cmds~\$RM $delfiles\"
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  libobjs="$libobjs $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+	  reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      compile_command="$compile_command ${wl}-bind_at_load"
+	      finalize_command="$finalize_command ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *cegcc)
+        # Disable wrappers for cegcc, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $ECHO for shipping.
+      if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
+	case $progpath in
+	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+	esac
+	qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+	qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    oldobjs="$oldobjs $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated="$generated $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  oldobjs="$oldobjs $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  $ECHO "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+	eval cmds=\"$old_archive_cmds\"
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval test_cmds=\"$old_archive_cmds\"
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		if test "x$EGREP" = x ; then
+			EGREP=egrep
+		fi
+		# We do not want portage's install root ($D) present.  Check only for
+		# this if the .la is being installed.
+		if test "$installed" = yes && test "$D"; then
+		  eval mynewdependency_lib=`echo "$libdir/$name" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
+		else
+		  mynewdependency_lib="$libdir/$name"
+		fi
+		# Do not add duplicates
+		if test "$mynewdependency_lib"; then
+		  my_little_ninja_foo_1=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
+		  if test -z "$my_little_ninja_foo_1"; then
+		    newdependency_libs="$newdependency_libs $mynewdependency_lib"
+		  fi
+		fi
+		;;
+		  *)
+		if test "$installed" = yes; then
+		  # Rather use S=WORKDIR if our version of portage supports it.
+		  # This is because some ebuild (gcc) do not use $S as buildroot.
+		  if test "$PWORKDIR"; then
+		    S="$PWORKDIR"
+		  fi
+		  # We do not want portage's build root ($S) present.
+		  my_little_ninja_foo_2=`echo $deplib |$EGREP -e "$S"`
+		  # We do not want portage's install root ($D) present.
+		  my_little_ninja_foo_3=`echo $deplib |$EGREP -e "$D"`
+		  if test -n "$my_little_ninja_foo_2" && test "$S"; then
+		    mynewdependency_lib=""
+		  elif test -n "$my_little_ninja_foo_3" && test "$D"; then
+		    eval mynewdependency_lib=`echo "$deplib" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
+		  else
+		    mynewdependency_lib="$deplib"
+		  fi
+		else
+		  mynewdependency_lib="$deplib"
+		fi
+		# Do not add duplicates
+		if test "$mynewdependency_lib"; then
+		  my_little_ninja_foo_4=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
+		  if test -z "$my_little_ninja_foo_4"; then
+			newdependency_libs="$newdependency_libs $mynewdependency_lib"
+		  fi
+		fi
+		;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlfiles="$newdlfiles $libdir/$name"
+		;;
+	      *) newdlfiles="$newdlfiles $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlprefiles="$newdlprefiles $libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	  esac
+	  # Do not add duplicates
+	  if test "$installed" = yes && test "$D"; then
+	    install_libdir=`echo "$install_libdir" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
+	  fi
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM="$RM $arg"; rmforce=yes ;;
+      -*) RM="$RM $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+	  case "$mode" in
+	  clean)
+	    case "  $library_names " in
+	    # "  " in the beginning catches empty $dlname
+	    *" $dlname "*) ;;
+	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/config/ltoptions.m4 b/config/ltoptions.m4
new file mode 100644
index 0000000..34151a3
--- /dev/null
+++ b/config/ltoptions.m4
@@ -0,0 +1,368 @@
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+		      [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+  		   [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+	[Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+	[Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+	 [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+		 [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+		 [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+		 [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+		 [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+		 [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/config/ltsugar.m4 b/config/ltsugar.m4
new file mode 100644
index 0000000..9000a05
--- /dev/null
+++ b/config/ltsugar.m4
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+	     [m4_foreach([_Lt_suffix],
+		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+		 [lt_append([$1], [$2], [$3])$4],
+		 [$5])],
+	  [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+	[$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/config/ltversion.m4 b/config/ltversion.m4
new file mode 100644
index 0000000..b8e154f
--- /dev/null
+++ b/config/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers			-*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 3012 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.6])
+m4_define([LT_PACKAGE_REVISION], [1.3012])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.6'
+macro_revision='1.3012'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/config/lt~obsolete.m4 b/config/lt~obsolete.m4
new file mode 100644
index 0000000..637bb20
--- /dev/null
+++ b/config/lt~obsolete.m4
@@ -0,0 +1,92 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_RC],		[AC_DEFUN([AC_LIBTOOL_RC])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
diff --git a/config/missing b/config/missing
new file mode 100755
index 0000000..1c8ff70
--- /dev/null
+++ b/config/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+#   Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake at gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+  lex|yacc)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f y.tab.h; then
+	echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f lex.yy.c; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit 1
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+	/^@setfilename/{
+	  s/.* \([^ ]*\) *$/\1/
+	  p
+	  q
+	}' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case $firstarg in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case $firstarg in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config/osmvsel.m4 b/config/osmvsel.m4
new file mode 100644
index 0000000..c7798cc
--- /dev/null
+++ b/config/osmvsel.m4
@@ -0,0 +1,259 @@
+
+dnl osmvsel.m4: an autoconf for OpenSM Vendor Selection option
+dnl
+dnl To use this macro, just do OPENIB_APP_OSMV_SEL.
+dnl the new configure option --with-osmv will be defined.
+dnl current supported values are: openib(default),sim,gen1
+dnl The following variables are defined:
+dnl OSMV_LDADD - LDADD additional libs for linking the vendor lib
+AC_DEFUN([OPENIB_APP_OSMV_SEL], [
+# --- BEGIN OPENIB_APP_OSMV_SEL ---
+
+dnl Define a way for the user to provide the osm vendor type
+AC_ARG_WITH(osmv,
+    AC_HELP_STRING([--with-osmv=<type>],
+                   [define the osm vendor type to build]),
+AC_MSG_NOTICE(Using OSM Vendor Type:$with_osmv),
+with_osmv="openib")
+
+dnl Define a way for the user to provide the path to the ibumad installation
+AC_ARG_WITH(umad-prefix,
+    AC_HELP_STRING([--with-umad-prefix=<dir>],
+                   [define the dir used as prefix for ibumad installation]),
+AC_MSG_NOTICE(Using ibumad installation prefix:$with_umad_prefix),
+with_umad_prefix="")
+
+dnl Define a way for the user to provide the path to the ibumad includes
+AC_ARG_WITH(umad-includes,
+    AC_HELP_STRING([--with-umad-includes=<dir>],
+                   [define the dir where ibumad includes are installed]),
+AC_MSG_NOTICE(Using ibumad includes from:$with_umad_includes),
+with_umad_includes="")
+
+if test x$with_umad_includes = x; then
+   if test x$with_umad_prefix != x; then
+      with_umad_includes=$with_umad_prefix/include
+   fi
+fi
+
+dnl Define a way for the user to provide the path to the ibumad libs
+AC_ARG_WITH(umad-libs,
+    AC_HELP_STRING([--with-umad-libs=<dir>],
+                   [define the dir where ibumad libs are installed]),
+AC_MSG_NOTICE(Using ibumad libs from:$with_umad_libs),
+with_umad_libs="")
+
+if test x$with_umad_libs = x; then
+   if test x$with_umad_prefix != x; then
+dnl Should we use lib64 or lib
+      if test "$(uname -m)" = "x86_64" -o "$(uname -m)" = "ppc64"; then
+         with_umad_libs=$with_umad_prefix/lib64
+      else
+         with_umad_libs=$with_umad_prefix/lib
+      fi
+   fi
+fi
+
+dnl Define a way for the user to provide the path to the simulator installation
+AC_ARG_WITH(sim,
+    AC_HELP_STRING([--with-sim=<dir>],
+                   [define the simulator prefix for building sim vendor (default /usr)]),
+AC_MSG_NOTICE(Using Simulator from:$with_sim),
+with_sim="/usr")
+
+dnl based on the with_osmv we can try the vendor flag
+if test $with_osmv = "openib"; then
+   AC_DEFINE(OSM_VENDOR_INTF_OPENIB, 1, [Define as 1 for OpenIB vendor])
+   OSMV_INCLUDES="-I\$(srcdir)/../include -I\$(srcdir)/../../libibcommon/include -I\$(srcdir)/../../libibumad/include -I\$(includedir)"
+   OSMV_LDADD="-L\$(abs_srcdir)/../../libibumad/.libs -L\$(abs_srcdir)/../../libibcommon/.libs -L\$(libdir) -libumad -libcommon"
+
+   if test "x$with_umad_libs" != "x"; then
+      OSMV_LDADD="-L$with_umad_libs $OSMV_LDADD"
+   fi
+
+   if test "x$with_umad_includes" != "x"; then
+      OSMV_INCLUDES="-I$with_umad_includes $OSMV_INCLUDES"
+   fi
+   AC_DEFINE(DUAL_SIDED_RMPP, 1, [Define as 1 if you want Dual Sided RMPP Support])
+elif test $with_osmv = "sim" ; then
+   AC_DEFINE(OSM_VENDOR_INTF_SIM, 1, [Define as 1 for sim vendor])
+   OSMV_INCLUDES="-I$with_sim/include -I\$(srcdir)/../include"
+   OSMV_LDADD="-L$with_sim/lib -libmscli"
+elif test $with_osmv = "gen1"; then
+   AC_DEFINE(OSM_VENDOR_INTF_TS, 1, [Define as 1 for ts vendor])
+
+   if test -z $MTHOME; then
+      MTHOME=/usr/local/ibgd/driver/infinihost
+   fi
+
+   OSMV_INCLUDES="-I$MTHOME/include -I\$(srcdir)/../include"
+
+   dnl we need to find the TS includes somewhere...
+   osmv_found=0
+   if test -z $TSHOME; then
+      osmv_dir=`uname -r|sed 's/-smp//'`
+      osmv_dir_smp=`uname -r`
+      for d in /usr/src/linux-$osmv_dir /usr/src/linux-$osmv_dir_smp /lib/modules/$osmv_dir/build /lib/modules/$osmv_dir_smp/build/; do
+         if test -f $d/drivers/infiniband/include/ts_ib_useraccess.h; then
+            OSMV_INCLUDES="$OSMV_INCLUDES -I$d/drivers/infiniband/include"
+            osmv_found=1
+         fi
+      done
+   else
+      if test -f  $TSHOME/ts_ib_useraccess.h; then
+         OSMV_INCLUDES="$OSMV_INCLUDES -I$TSHOME"
+         osmv_found=1
+      fi
+   fi
+   if test $osmv_found = 0; then
+      AC_MSG_ERROR([Fail to find gen1 include files dir])
+   fi
+   OSMV_LDADD="-L/usr/local/ibgd/driver/infinihost/lib -lvapi -lmosal -lmtl_common -lmpga"
+elif test $with_osmv = "vapi"; then
+   AC_DEFINE(OSM_VENDOR_INTF_MTL, 1, [Define as 1 for vapi vendor])
+   OSMV_INCLUDES="-I/usr/mellanox/include -I/usr/include -I\$(srcdir)/../include"
+   OSMV_LDADD="-L/usr/lib -L/usr/mellanox/lib -lib_mgt -lvapi -lmosal -lmtl_common -lmpga"
+else
+   AC_MSG_ERROR([Invalid Vendor Type provided:$with_osmv should be either openib,sim,gen1])
+fi
+
+AM_CONDITIONAL(OSMV_VAPI, test $with_osmv = "vapi")
+AM_CONDITIONAL(OSMV_GEN1, test $with_osmv = "gen1")
+AM_CONDITIONAL(OSMV_SIM, test $with_osmv = "sim")
+AM_CONDITIONAL(OSMV_OPENIB, test $with_osmv = "openib")
+AC_DEFINE(VENDOR_RMPP_SUPPORT, 1, [Define as 1 if you want Vendor RMPP Support])
+
+AC_SUBST(OSMV_LDADD)
+AC_SUBST(OSMV_INCLUDES)
+
+# --- END OPENIB_APP_OSMV_SEL ---
+]) dnl OPENIB_APP_OSMV_SEL
+
+dnl Check for the vendor lib dependency
+AC_DEFUN([OPENIB_APP_OSMV_CHECK_LIB], [
+# --- BEGIN OPENIB_APP_OSMV_CHECK_LIB ---
+if test "$disable_libcheck" != "yes"; then
+
+ dnl based on the with_osmv we can try the vendor flag
+ if test $with_osmv = "openib"; then
+   LDADD="$LDADD $OSMV_LDADD"
+   AC_CHECK_LIB(ibumad, umad_init, [],
+	 AC_MSG_ERROR([umad_init() not found. libosmvendor of type openib requires libibumad.]))
+ elif test $with_osmv = "sim" ; then
+   LDFLAGS="$LDFLAGS -L$with_sim/lib"
+   AC_CHECK_FILE([$with_sim/lib/libibmscli.a], [],
+    AC_MSG_ERROR([ibms_bind() not found. libosmvendor of type sim requires libibmscli.]))
+ elif test $with_osmv = "gen1"; then
+   LDFLAGS="$LDFLAGS -L$MTHOME/lib -L$MTHOME/lib64 -lmosal -lmtl_common -lmpga"
+   AC_CHECK_LIB(vapi, vipul_init, [],
+    AC_MSG_ERROR([vipul_init() not found. libosmvendor of type gen1 requires libvapi.]))
+ elif test $with_osmv != "vapi"; then
+   AC_MSG_ERROR([OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_LIB])
+ fi
+fi
+# --- END OPENIB_APP_OSMV_CHECK_LIB ---
+]) dnl OPENIB_APP_OSMV_CHECK_LIB
+
+dnl Check for the vendor lib dependency
+AC_DEFUN([OPENIB_APP_OSMV_CHECK_HEADER], [
+# --- BEGIN OPENIB_APP_OSMV_CHECK_HEADER ---
+
+dnl we might be required to ignore this check
+if test "$disable_libcheck" != "yes"; then
+ if test $with_osmv = "openib"; then
+   osmv_headers=infiniband/umad.h
+ elif test $with_osmv = "sim" ; then
+   osmv_headers=ibmgtsim/ibms_client_api.h
+ elif test $with_osmv = "gen1"; then
+   osmv_headers=
+ elif test $with_osmv = "vapi"; then
+   osmv_headers=vapi.h
+ else
+   AC_MSG_ERROR([OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_HEADER])
+ fi
+ if test "x$osmv_headers" != "x"; then
+   AC_CHECK_HEADERS($osmv_headers)
+ fi
+fi
+# --- END OPENIB_APP_OSMV_CHECK_HEADER ---
+]) dnl OPENIB_APP_OSMV_CHECK_HEADER
+
+dnl Check if they want the socket console
+AC_DEFUN([OPENIB_OSM_CONSOLE_SOCKET_SEL], [
+# --- BEGIN OPENIB_OSM_CONSOLE_SOCKET_SEL ---
+
+dnl Console over a socket connection
+AC_ARG_ENABLE(console-socket,
+[  --enable-console-socket Enable a console socket, requires tcp_wrappers (default no)],
+[case $enableval in
+     yes) console_socket=yes ;;
+     no)  console_socket=no ;;
+   esac],
+   console_socket=no)
+if test $console_socket = yes; then
+  AC_CHECK_LIB(wrap, request_init, [],
+ 	AC_MSG_ERROR([request_init() not found. console-socket requires libwrap.]))
+  AC_DEFINE(ENABLE_OSM_CONSOLE_SOCKET,
+	    1,
+	    [Define as 1 if you want to enable a console on a socket connection])
+fi
+# --- END OPENIB_OSM_CONSOLE_SOCKET_SEL ---
+]) dnl OPENIB_OSM_CONSOLE_SOCKET_SEL
+
+dnl Check if they want the PerfMgr
+AC_DEFUN([OPENIB_OSM_PERF_MGR_SEL], [
+# --- BEGIN OPENIB_OSM_PERF_MGR_SEL ---
+
+dnl enable the perf-mgr
+AC_ARG_ENABLE(perf-mgr,
+[  --enable-perf-mgr Enable the performance manager (default no)],
+   [case $enableval in
+     yes) perf_mgr=yes ;;
+     no)  perf_mgr=no ;;
+   esac],
+   perf_mgr=no)
+AC_ARG_ENABLE(perf-mgr-profile,
+[  --enable-perf-mgr-profile Enable the performance manager profiling (default no)],
+	[case $enableval in
+	yes) perf_mgr_profile=yes ;;
+	no)  perf_mgr_profile=no ;;
+	esac],
+	perf_mgr_profile=no)
+if test $perf_mgr = yes; then
+  AC_DEFINE(ENABLE_OSM_PERF_MGR,
+	1,
+	[Define as 1 if you want to enable the performance manager])
+  if test $perf_mgr_profile = yes; then
+	AC_DEFINE(ENABLE_OSM_PERF_MGR_PROFILE,
+		1,
+		[Define as 1 if you want to enable the performance manager profiling code])
+  fi
+fi
+# --- END OPENIB_OSM_PERF_MGR_SEL ---
+]) dnl OPENIB_OSM_PERF_MGR_SEL
+
+
+dnl Check if they want the event plugin
+AC_DEFUN([OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL], [
+# --- BEGIN OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL ---
+
+dnl enable the default-event-plugin
+AC_ARG_ENABLE(default-event-plugin,
+[  --enable-default-event-plugin  Enable a default event plugin "osmeventplugin" (default no)],
+   [case $enableval in
+     yes) default_event_plugin=yes ;;
+     no)  default_event_plugin=no ;;
+   esac],
+   default_event_plugin=no)
+if test $default_event_plugin = yes; then
+  AC_DEFINE(ENABLE_OSM_DEFAULT_EVENT_PLUGIN,
+	    1,
+	    [Define as 1 if you want to enable the event plugin])
+  DEFAULT_EVENT_PLUGIN=osmeventplugin
+else
+  DEFAULT_EVENT_PLUGIN=
+fi
+AC_SUBST([DEFAULT_EVENT_PLUGIN])
+
+# --- END OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL ---
+]) dnl OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL
diff --git a/config/ylwrap b/config/ylwrap
new file mode 100755
index 0000000..7278b6a
--- /dev/null
+++ b/config/ylwrap
@@ -0,0 +1,223 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2007-11-22.22
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
+# 2007  Free Software Foundation, Inc.
+#
+# Written by Tom Tromey <tromey at cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+case "$1" in
+  '')
+    echo "$0: No files given.  Try \`$0 --help' for more information." 1>&2
+    exit 1
+    ;;
+  --basedir)
+    basedir=$2
+    shift 2
+    ;;
+  -h|--h*)
+    cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+  INPUT is the input file
+  OUTPUT is one file PROG generates
+  DESIRED is the file we actually want instead of OUTPUT
+  PROGRAM is program to run
+  ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v|--v*)
+    echo "ylwrap $scriptversion"
+    exit $?
+    ;;
+esac
+
+
+# The input.
+input="$1"
+shift
+case "$input" in
+  [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+  *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+pairlist=
+while test "$#" -ne 0; do
+  if test "$1" = "--"; then
+    shift
+    break
+  fi
+  pairlist="$pairlist $1"
+  shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+  [\\/]* | ?:[\\/]*) ;;
+  *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd '`pwd`'; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+case $# in
+  0) "$prog" "$input" ;;
+  *) "$prog" "$@" "$input" ;;
+esac
+ret=$?
+
+if test $ret -eq 0; then
+  set X $pairlist
+  shift
+  first=yes
+  # Since DOS filename conventions don't allow two dots,
+  # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+  # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+  y_tab_nodot="no"
+  if test -f y_tab.c || test -f y_tab.h; then
+    y_tab_nodot="yes"
+  fi
+
+  # The directory holding the input.
+  input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+  # Quote $INPUT_DIR so we can use it in a regexp.
+  # FIXME: really we should care about more than `.' and `\'.
+  input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+  while test "$#" -ne 0; do
+    from="$1"
+    # Handle y_tab.c and y_tab.h output by DOS
+    if test $y_tab_nodot = "yes"; then
+      if test $from = "y.tab.c"; then
+    	from="y_tab.c"
+      else
+    	if test $from = "y.tab.h"; then
+    	  from="y_tab.h"
+    	fi
+      fi
+    fi
+    if test -f "$from"; then
+      # If $2 is an absolute path name, then just use that,
+      # otherwise prepend `../'.
+      case "$2" in
+    	[\\/]* | ?:[\\/]*) target="$2";;
+    	*) target="../$2";;
+      esac
+
+      # We do not want to overwrite a header file if it hasn't
+      # changed.  This avoid useless recompilations.  However the
+      # parser itself (the first file) should always be updated,
+      # because it is the destination of the .y.c rule in the
+      # Makefile.  Divert the output of all other files to a temporary
+      # file so we can compare them to existing versions.
+      if test $first = no; then
+	realtarget="$target"
+	target="tmp-`echo $target | sed s/.*[\\/]//g`"
+      fi
+      # Edit out `#line' or `#' directives.
+      #
+      # We don't want the resulting debug information to point at
+      # an absolute srcdir; it is better for it to just mention the
+      # .y file with no path.
+      #
+      # We want to use the real output file name, not yy.lex.c for
+      # instance.
+      #
+      # We want the include guards to be adjusted too.
+      FROM=`echo "$from" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+      TARGET=`echo "$2" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+      sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+          -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
+
+      # Check whether header files must be updated.
+      if test $first = no; then
+	if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+	  echo "$2" is unchanged
+	  rm -f "$target"
+	else
+          echo updating "$2"
+          mv -f "$target" "$realtarget"
+        fi
+      fi
+    else
+      # A missing file is only an error for the first file.  This
+      # is a blatant hack to let us support using "yacc -d".  If -d
+      # is not specified, we don't want an error when the header
+      # file is "missing".
+      if test $first = yes; then
+        ret=1
+      fi
+    fi
+    shift
+    shift
+    first=no
+  done
+else
+  ret=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..4e59ab4
--- /dev/null
+++ b/configure
@@ -0,0 +1,15736 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.63 for opensm 3.2.6_20090317.
+#
+# Report bugs to <general at lists.openfabrics.org>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+	do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+	done
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell bug-autoconf at gnu.org about your system,
+  echo including any error possibly output before this message.
+  echo This can help us improve future autoconf versions.
+  echo Configuration will now proceed without shell functions.
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<_LT_EOF
+$*
+_LT_EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+  if test "X${echo_test_string+set}" != Xset; then
+    # find a string as large as possible, as long as the shell can cope with it
+    for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+      then
+        break
+      fi
+    done
+  fi
+
+  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+     test "X$echo_testing_string" = "X$echo_test_string"; then
+    :
+  else
+    # The Solaris, AIX, and Digital Unix default echo programs unquote
+    # backslashes.  This makes it impossible to quote backslashes using
+    #   echo "$something" | sed 's/\\/\\\\/g'
+    #
+    # So, first we look for a working echo in the user's PATH.
+
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for dir in $PATH /usr/ucb; do
+      IFS="$lt_save_ifs"
+      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        ECHO="$dir/echo"
+        break
+      fi
+    done
+    IFS="$lt_save_ifs"
+
+    if test "X$ECHO" = Xecho; then
+      # We didn't find a better echo, so look for alternatives.
+      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        # This shell has a builtin print -r that does the trick.
+        ECHO='print -r'
+      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+	   test "X$CONFIG_SHELL" != X/bin/ksh; then
+        # If we have ksh, try running configure again with it.
+        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+        export ORIGINAL_CONFIG_SHELL
+        CONFIG_SHELL=/bin/ksh
+        export CONFIG_SHELL
+        exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+      else
+        # Try using printf.
+        ECHO='printf %s\n'
+        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	  # Cool, printf works
+	  :
+        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	  export CONFIG_SHELL
+	  SHELL="$CONFIG_SHELL"
+	  export SHELL
+	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
+        elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
+        else
+	  # maybe with a smaller string...
+	  prev=:
+
+	  for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+	    then
+	      break
+	    fi
+	    prev="$cmd"
+	  done
+
+	  if test "$prev" != 'sed 50q "$0"'; then
+	    echo_test_string=`eval $prev`
+	    export echo_test_string
+	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+	  else
+	    # Oops.  We lost completely, so just stick with echo.
+	    ECHO=echo
+	  fi
+        fi
+      fi
+    fi
+  fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='opensm'
+PACKAGE_TARNAME='opensm'
+PACKAGE_VERSION='3.2.6_20090317'
+PACKAGE_STRING='opensm 3.2.6_20090317'
+PACKAGE_BUGREPORT='general at lists.openfabrics.org'
+
+ac_unique_file="opensm/osm_opensm.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+OSMV_INCLUDES
+OSMV_LDADD
+OSMV_OPENIB_FALSE
+OSMV_OPENIB_TRUE
+OSMV_SIM_FALSE
+OSMV_SIM_TRUE
+OSMV_GEN1_FALSE
+OSMV_GEN1_TRUE
+OSMV_VAPI_FALSE
+OSMV_VAPI_TRUE
+DEFAULT_EVENT_PLUGIN
+PREFIX_ROUTES_FILE
+QOS_POLICY_FILE
+PARTITION_CONFIG_FILE
+NODENAMEMAPFILE
+OPENSM_CONFIG_FILE
+OPENSM_CONFIG_DIR
+OPENSM_CONFIG_SUB_DIR
+DEBUG_FALSE
+DEBUG_TRUE
+HAVE_LD_VERSION_SCRIPT_FALSE
+HAVE_LD_VERSION_SCRIPT_TRUE
+_LEX_
+_YACC_
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+YFLAGS
+YACC
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+lt_ECHO
+RANLIB
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+TARBALL
+RELEASE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_dependency_tracking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+enable_libtool_lock
+enable_debug
+enable_libcheck
+enable_console_socket
+enable_perf_mgr
+enable_perf_mgr_profile
+with_opensm_conf_sub_dir
+with_opensm_conf_file
+with_node_name_map
+with_partitions_conf
+with_qos_policy_conf
+with_prefix_routes_conf
+enable_default_event_plugin
+with_osmv
+with_umad_prefix
+with_umad_includes
+with_umad_libs
+with_sim
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+YACC
+YFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { $as_echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { $as_echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2
+   { (exit 1); exit 1; }; } ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { $as_echo "$as_me: error: working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { $as_echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures opensm 3.2.6_20090317 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/opensm]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of opensm 3.2.6_20090317:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-debug          Turn on debugging
+  --disable-libcheck      do not test for presence of ib libraries
+  --enable-console-socket Enable a console socket, requires tcp_wrappers (default no)
+  --enable-perf-mgr Enable the performance manager (default no)
+  --enable-perf-mgr-profile Enable the performance manager profiling (default no)
+  --enable-default-event-plugin  Enable a default event plugin "osmeventplugin" (default no)
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-opensm-conf-sub-dir=dir
+                          define a directory name for opensm's conf files
+                          <sysconfdir>/<dir> (default "opensm")
+  --with-opensm-conf-file=file
+                          define a default OpenSM config file (default
+                          opensm.conf)
+  --with-node-name-map=file
+                          define a default node name map file (default
+                          ib-node-name-map)
+  --with-partitions-conf=file
+                          define a partitions config file (default
+                          partitions.conf)
+  --with-qos-policy-conf=file
+                          define a QOS policy config file (default
+                          qos-policy.conf)
+  --with-prefix-routes-conf=file
+                          define a Prefix Routes config file (default is
+                          prefix-routes.conf)
+  --with-osmv=<type>      define the osm vendor type to build
+  --with-umad-prefix=<dir>
+                          define the dir used as prefix for ibumad
+                          installation
+  --with-umad-includes=<dir>
+                          define the dir where ibumad includes are installed
+  --with-umad-libs=<dir>  define the dir where ibumad libs are installed
+  --with-sim=<dir>        define the simulator prefix for building sim vendor
+                          (default /usr)
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  YACC        The `Yet Another C Compiler' implementation to use. Defaults to
+              the first program found out of: `bison -y', `byacc', `yacc'.
+  YFLAGS      The list of arguments that will be passed by default to $YACC.
+              This script will default YFLAGS to the empty string to avoid a
+              default value of `-d' given by some make applications.
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <general at lists.openfabrics.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+opensm configure 3.2.6_20090317
+generated by GNU Autoconf 2.63
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by opensm $as_me 3.2.6_20090317, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  $as_echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:$LINENO:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:$LINENO:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_aux_dir=
+for ac_dir in config "$srcdir"/config; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&5
+$as_echo "$as_me: error: cannot find install-sh or install.sh in config \"$srcdir\"/config" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+ac_config_headers="$ac_config_headers include/config.h include/opensm/osm_config.h"
+
+am__api_version='1.10'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { $as_echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+$as_echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { $as_echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+$as_echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:$LINENO: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    { { $as_echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+$as_echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='opensm'
+ VERSION='3.2.6_20090317'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+RELEASE=${RELEASE:-unknown}
+
+TARBALL=${TARBALL:-${PACKAGE}-${VERSION}.tar.gz}
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _OSM_CONFIG_H_ 1
+_ACEOF
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:$LINENO: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:$LINENO: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+{ $as_echo "$as_me:$LINENO: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:$LINENO: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.6'
+macro_revision='1.3012'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+$as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ $as_echo "$as_me:$LINENO: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+$as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+$as_echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:$LINENO: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+$as_echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     $as_unset ac_script || ac_script=
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable sed could be found in \$PATH" >&5
+$as_echo "$as_me: error: no acceptable sed could be found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:$LINENO: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+$as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+{ $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:$LINENO: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:4454: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:4457: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:4460: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:$LINENO: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:$LINENO: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:$LINENO: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:$LINENO: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:$LINENO: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:$LINENO: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:$LINENO: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 5666 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  ppc64-*linux*|powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  ppc*-*linux*|powerpc*-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  lt_cv_cc_needs_belf=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	lt_cv_cc_needs_belf=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:$LINENO: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:$LINENO: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:$LINENO: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:$LINENO: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:$LINENO: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:$LINENO: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+    { $as_echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  lt_cv_ld_exported_symbols_list=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	lt_cv_ld_exported_symbols_list=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+# Set options
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:$LINENO: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+  { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7523: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7527: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl*)
+	# IBM XL C 8.0/Fortran 10.1 on PPC
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+	*Sun\ F*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7862: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7866: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7967: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:7971: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:8022: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:8026: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:$LINENO: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec=
+	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  # Exported symbols can be pulled into shared objects from archives
+	  whole_archive_flag_spec='$convenience'
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  whole_archive_flag_spec=''
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=echo
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld='+b $libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat >conftest.$ac_ext <<_ACEOF
+int foo(void) {}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+      $RM conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl
+	pic_flag=$lt_prog_compiler_pic
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag
+        allow_undefined_flag=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+	  archive_cmds_need_lc=no
+        else
+	  archive_cmds_need_lc=yes
+        fi
+        allow_undefined_flag=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $RM conftest*
+      { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+$as_echo "$archive_cmds_need_lc" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  # Handle Gentoo/FreeBSD as it was Linux
+  case $host_vendor in
+    gentoo)
+      version_type=linux ;;
+    *)
+      version_type=freebsd-$objformat ;;
+  esac
+
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+    linux)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+      soname_spec='${libname}${release}${shared_ext}$major'
+      need_lib_prefix=no
+      need_version=no
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # Some binutils ld are patched to set DT_RUNPATH
+  save_LDFLAGS=$LDFLAGS
+  save_libdir=$libdir
+  eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+       LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then
+  shlibpath_overrides_runpath=yes
+fi
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  LDFLAGS=$save_LDFLAGS
+  libdir=$save_libdir
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:$LINENO: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dl_dlopen=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    { $as_echo "$as_me:$LINENO: checking for shl_load" >&5
+$as_echo_n "checking for shl_load... " >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_func_shl_load=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_shl_load=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+$as_echo "$ac_cv_func_shl_load" >&6; }
+if test "x$ac_cv_func_shl_load" = x""yes; then
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_dld_shl_load=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dld_shl_load=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  { $as_echo "$as_me:$LINENO: checking for dlopen" >&5
+$as_echo_n "checking for dlopen... " >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_func_dlopen=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_dlopen=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+$as_echo "$ac_cv_func_dlopen" >&6; }
+if test "x$ac_cv_func_dlopen" = x""yes; then
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dl_dlopen=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_svld_dlopen=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_svld_dlopen=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_dld_dld_link=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dld_dld_link=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 10835 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 10931 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:$LINENO: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_YACC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_YACC="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { $as_echo "$as_me:$LINENO: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+for ac_prog in flex lex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LEX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LEX="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  { $as_echo "$as_me:$LINENO: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+  cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { yyless (input () != 0); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+  return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ (ac_try="$LEX conftest.l"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$LEX conftest.l") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ $as_echo "$as_me:$LINENO: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if test "${ac_cv_prog_lex_root+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  { { $as_echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5
+$as_echo "$as_me: error: cannot find output from $LEX; giving up" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+  { $as_echo "$as_me:$LINENO: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if test "${ac_cv_lib_lex+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS=$LIBS
+    ac_cv_lib_lex='none needed'
+    for ac_lib in '' -lfl -ll; do
+      LIBS="$ac_lib $ac_save_LIBS"
+      cat >conftest.$ac_ext <<_ACEOF
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_lex=$ac_lib
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+      test "$ac_cv_lib_lex" != 'none needed' && break
+    done
+    LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+  test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent.  Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define YYTEXT_POINTER 1
+_ACEOF
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+
+for ac_prog in $YACC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog__YACC_+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$_YACC_"; then
+  ac_cv_prog__YACC_="$_YACC_" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog__YACC_="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+_YACC_=$ac_cv_prog__YACC_
+if test -n "$_YACC_"; then
+  { $as_echo "$as_me:$LINENO: result: $_YACC_" >&5
+$as_echo "$_YACC_" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$_YACC_" && break
+done
+test -n "$_YACC_" || _YACC_="none"
+
+if test "$_YACC_" = "none"
+then
+  { { $as_echo "$as_me:$LINENO: error: No bison/byacc/yacc found." >&5
+$as_echo "$as_me: error: No bison/byacc/yacc found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+for ac_prog in $LEX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog__LEX_+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$_LEX_"; then
+  ac_cv_prog__LEX_="$_LEX_" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog__LEX_="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+_LEX_=$ac_cv_prog__LEX_
+if test -n "$_LEX_"; then
+  { $as_echo "$as_me:$LINENO: result: $_LEX_" >&5
+$as_echo "$_LEX_" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$_LEX_" && break
+done
+test -n "$_LEX_" || _LEX_="none"
+
+if test "$_LEX_" = "none"
+then
+  { { $as_echo "$as_me:$LINENO: error: No flex/lex found." >&5
+$as_echo "$as_me: error: No flex/lex found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5
+$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
+if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_pthread_pthread_mutex_init=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_pthread_pthread_mutex_init=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_mutex_init" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+  LIBS="-lpthread $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: pthread_mutex_init() not found.  libosmcomp requires libpthread." >&5
+$as_echo "$as_me: error: pthread_mutex_init() not found.  libosmcomp requires libpthread." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dl_dlopen=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: dlopen() not found. OpenSM requires libdl." >&5
+$as_echo "$as_me: error: dlopen() not found. OpenSM requires libdl." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const /**/
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+{ $as_echo "$as_me:$LINENO: checking for pid_t" >&5
+$as_echo_n "checking for pid_t... " >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_type_pid_t=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if (sizeof (pid_t))
+       return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if (sizeof ((pid_t)))
+	  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_pid_t=yes
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+$as_echo "$ac_cv_type_pid_t" >&6; }
+if test "x$ac_cv_type_pid_t" = x""yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for size_t" >&5
+$as_echo_n "checking for size_t... " >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_type_size_t=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if (sizeof (size_t))
+       return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if (sizeof ((size_t)))
+	  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_size_t=yes
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+$as_echo "$ac_cv_type_size_t" >&6; }
+if test "x$ac_cv_type_size_t" = x""yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_time=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if test "${ac_cv_struct_tm+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+				     int *p = &tm.tm_sec;
+				     return !p;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_struct_tm=time.h
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_struct_tm=sys/time.h
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+$as_echo "$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for working volatile" >&5
+$as_echo_n "checking for working volatile... " >&6; }
+if test "${ac_cv_c_volatile+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_volatile=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_volatile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_volatile" >&5
+$as_echo "$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define volatile /**/
+_ACEOF
+
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking whether ld accepts --version-script" >&5
+$as_echo_n "checking whether ld accepts --version-script... " >&6; }
+if test "${ac_cv_version_script+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "`$LD --help < /dev/null 2>/dev/null | grep version-script`"; then
+	ac_cv_version_script=yes
+else
+	ac_cv_version_script=no
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_version_script" >&5
+$as_echo "$ac_cv_version_script" >&6; }
+ if test "$ac_cv_version_script" = "yes"; then
+  HAVE_LD_VERSION_SCRIPT_TRUE=
+  HAVE_LD_VERSION_SCRIPT_FALSE='#'
+else
+  HAVE_LD_VERSION_SCRIPT_TRUE='#'
+  HAVE_LD_VERSION_SCRIPT_FALSE=
+fi
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval=$enable_debug; case "${enableval}" in
+	yes) debug=true ;;
+	no)  debug=false ;;
+	*) { { $as_echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-debug" >&5
+$as_echo "$as_me: error: bad value ${enableval} for --enable-debug" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  debug=false
+fi
+
+if test x$debug = xtrue ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSM_DEBUG 1
+_ACEOF
+
+fi
+ if test x$debug = xtrue; then
+  DEBUG_TRUE=
+  DEBUG_FALSE='#'
+else
+  DEBUG_TRUE='#'
+  DEBUG_FALSE=
+fi
+
+
+# Check whether --enable-libcheck was given.
+if test "${enable_libcheck+set}" = set; then
+  enableval=$enable_libcheck; if test x$enableval = xno ; then
+	disable_libcheck=yes
+fi
+fi
+
+
+
+# --- BEGIN OPENIB_OSM_CONSOLE_SOCKET_SEL ---
+
+# Check whether --enable-console-socket was given.
+if test "${enable_console_socket+set}" = set; then
+  enableval=$enable_console_socket; case $enableval in
+     yes) console_socket=yes ;;
+     no)  console_socket=no ;;
+   esac
+else
+  console_socket=no
+fi
+
+if test $console_socket = yes; then
+
+{ $as_echo "$as_me:$LINENO: checking for request_init in -lwrap" >&5
+$as_echo_n "checking for request_init in -lwrap... " >&6; }
+if test "${ac_cv_lib_wrap_request_init+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lwrap  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char request_init ();
+int
+main ()
+{
+return request_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_wrap_request_init=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_wrap_request_init=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_wrap_request_init" >&5
+$as_echo "$ac_cv_lib_wrap_request_init" >&6; }
+if test "x$ac_cv_lib_wrap_request_init" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBWRAP 1
+_ACEOF
+
+  LIBS="-lwrap $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: request_init() not found. console-socket requires libwrap." >&5
+$as_echo "$as_me: error: request_init() not found. console-socket requires libwrap." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_OSM_CONSOLE_SOCKET 1
+_ACEOF
+
+fi
+# --- END OPENIB_OSM_CONSOLE_SOCKET_SEL ---
+
+
+
+# --- BEGIN OPENIB_OSM_PERF_MGR_SEL ---
+
+# Check whether --enable-perf-mgr was given.
+if test "${enable_perf_mgr+set}" = set; then
+  enableval=$enable_perf_mgr; case $enableval in
+     yes) perf_mgr=yes ;;
+     no)  perf_mgr=no ;;
+   esac
+else
+  perf_mgr=no
+fi
+
+# Check whether --enable-perf-mgr-profile was given.
+if test "${enable_perf_mgr_profile+set}" = set; then
+  enableval=$enable_perf_mgr_profile; case $enableval in
+	yes) perf_mgr_profile=yes ;;
+	no)  perf_mgr_profile=no ;;
+	esac
+else
+  perf_mgr_profile=no
+fi
+
+if test $perf_mgr = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_OSM_PERF_MGR 1
+_ACEOF
+
+  if test $perf_mgr_profile = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_OSM_PERF_MGR_PROFILE 1
+_ACEOF
+
+  fi
+fi
+# --- END OPENIB_OSM_PERF_MGR_SEL ---
+
+
+conf_dir_tmp1="`eval echo ${sysconfdir} | sed 's/^NONE/$ac_default_prefix/'`"
+SYS_CONFIG_DIR="`eval echo $conf_dir_tmp1`"
+
+OPENSM_CONFIG_SUB_DIR=opensm
+{ $as_echo "$as_me:$LINENO: checking for --with-opensm-conf-sub-dir" >&5
+$as_echo_n "checking for --with-opensm-conf-sub-dir... " >&6; }
+
+# Check whether --with-opensm-conf-sub-dir was given.
+if test "${with_opensm_conf_sub_dir+set}" = set; then
+  withval=$with_opensm_conf_sub_dir;  case "$withval" in
+    no)
+        ;;
+    *)
+        OPENSM_CONFIG_SUB_DIR=$withval
+        ;;
+    esac
+
+fi
+
+
+
+OPENSM_CONFIG_DIR=$SYS_CONFIG_DIR/$OPENSM_CONFIG_SUB_DIR
+{ $as_echo "$as_me:$LINENO: result: $OPENSM_CONFIG_DIR" >&5
+$as_echo "$OPENSM_CONFIG_DIR" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define OPENSM_CONFIG_DIR "$OPENSM_CONFIG_DIR"
+_ACEOF
+
+
+
+OPENSM_CONFIG_FILE=opensm.conf
+{ $as_echo "$as_me:$LINENO: checking for --with-opensm-conf-file " >&5
+$as_echo_n "checking for --with-opensm-conf-file ... " >&6; }
+
+# Check whether --with-opensm-conf-file was given.
+if test "${with_opensm_conf_file+set}" = set; then
+  withval=$with_opensm_conf_file;  case "$withval" in
+    no)
+        ;;
+    *)
+        OPENSM_CONFIG_FILE=$withval
+        ;;
+    esac
+
+fi
+
+{ $as_echo "$as_me:$LINENO: result: ${OPENSM_CONFIG_FILE}" >&5
+$as_echo "${OPENSM_CONFIG_FILE}" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEFAULT_OPENSM_CONFIG_FILE "$OPENSM_CONFIG_DIR/$OPENSM_CONFIG_FILE"
+_ACEOF
+
+
+
+NODENAMEMAPFILE=ib-node-name-map
+{ $as_echo "$as_me:$LINENO: checking for --with-node-name-map " >&5
+$as_echo_n "checking for --with-node-name-map ... " >&6; }
+
+# Check whether --with-node-name-map was given.
+if test "${with_node_name_map+set}" = set; then
+  withval=$with_node_name_map;  case "$withval" in
+    no)
+        ;;
+    *)
+        NODENAMEMAPFILE=$withval
+        ;;
+    esac
+
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $NODENAMEMAPFILE" >&5
+$as_echo "$NODENAMEMAPFILE" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEFAULT_NODENAME_MAP "$OPENSM_CONFIG_DIR/$NODENAMEMAPFILE"
+_ACEOF
+
+
+
+PARTITION_CONFIG_FILE=partitions.conf
+{ $as_echo "$as_me:$LINENO: checking for --with-partitions-conf" >&5
+$as_echo_n "checking for --with-partitions-conf... " >&6; }
+
+# Check whether --with-partitions-conf was given.
+if test "${with_partitions_conf+set}" = set; then
+  withval=$with_partitions_conf;  case "$withval" in
+    no)
+        ;;
+    *)
+        PARTITION_CONFIG_FILE=$withval
+        ;;
+    esac
+
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $PARTITION_CONFIG_FILE" >&5
+$as_echo "$PARTITION_CONFIG_FILE" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEFAULT_PARTITION_CONFIG_FILE "$OPENSM_CONFIG_DIR/$PARTITION_CONFIG_FILE"
+_ACEOF
+
+
+
+QOS_POLICY_FILE=qos-policy.conf
+{ $as_echo "$as_me:$LINENO: checking for --with-qos-policy-conf" >&5
+$as_echo_n "checking for --with-qos-policy-conf... " >&6; }
+
+# Check whether --with-qos-policy-conf was given.
+if test "${with_qos_policy_conf+set}" = set; then
+  withval=$with_qos_policy_conf;  case "$withval" in
+    no)
+        ;;
+    *)
+        QOS_POLICY_FILE=$withval
+        ;;
+    esac
+
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $QOS_POLICY_FILE" >&5
+$as_echo "$QOS_POLICY_FILE" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEFAULT_QOS_POLICY_FILE "$OPENSM_CONFIG_DIR/$QOS_POLICY_FILE"
+_ACEOF
+
+
+
+PREFIX_ROUTES_FILE=prefix-routes.conf
+{ $as_echo "$as_me:$LINENO: checking for --with-prefix-routes-conf" >&5
+$as_echo_n "checking for --with-prefix-routes-conf... " >&6; }
+
+# Check whether --with-prefix-routes-conf was given.
+if test "${with_prefix_routes_conf+set}" = set; then
+  withval=$with_prefix_routes_conf;  case "$withval" in
+    no)
+        ;;
+    *)
+        PREFIX_ROUTES_FILE=$withval
+        ;;
+    esac
+
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $PREFIX_ROUTES_FILE" >&5
+$as_echo "$PREFIX_ROUTES_FILE" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEFAULT_PREFIX_ROUTES_FILE "$OPENSM_CONFIG_DIR/$PREFIX_ROUTES_FILE"
+_ACEOF
+
+
+
+
+# --- BEGIN OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL ---
+
+# Check whether --enable-default-event-plugin was given.
+if test "${enable_default_event_plugin+set}" = set; then
+  enableval=$enable_default_event_plugin; case $enableval in
+     yes) default_event_plugin=yes ;;
+     no)  default_event_plugin=no ;;
+   esac
+else
+  default_event_plugin=no
+fi
+
+if test $default_event_plugin = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_OSM_DEFAULT_EVENT_PLUGIN 1
+_ACEOF
+
+  DEFAULT_EVENT_PLUGIN=osmeventplugin
+else
+  DEFAULT_EVENT_PLUGIN=
+fi
+
+
+# --- END OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL ---
+
+
+
+# --- BEGIN OPENIB_APP_OSMV_SEL ---
+
+
+# Check whether --with-osmv was given.
+if test "${with_osmv+set}" = set; then
+  withval=$with_osmv; { $as_echo "$as_me:$LINENO: Using OSM Vendor Type:$with_osmv" >&5
+$as_echo "$as_me: Using OSM Vendor Type:$with_osmv" >&6;}
+else
+  with_osmv="openib"
+fi
+
+
+
+# Check whether --with-umad-prefix was given.
+if test "${with_umad_prefix+set}" = set; then
+  withval=$with_umad_prefix; { $as_echo "$as_me:$LINENO: Using ibumad installation prefix:$with_umad_prefix" >&5
+$as_echo "$as_me: Using ibumad installation prefix:$with_umad_prefix" >&6;}
+else
+  with_umad_prefix=""
+fi
+
+
+
+# Check whether --with-umad-includes was given.
+if test "${with_umad_includes+set}" = set; then
+  withval=$with_umad_includes; { $as_echo "$as_me:$LINENO: Using ibumad includes from:$with_umad_includes" >&5
+$as_echo "$as_me: Using ibumad includes from:$with_umad_includes" >&6;}
+else
+  with_umad_includes=""
+fi
+
+
+if test x$with_umad_includes = x; then
+   if test x$with_umad_prefix != x; then
+      with_umad_includes=$with_umad_prefix/include
+   fi
+fi
+
+
+# Check whether --with-umad-libs was given.
+if test "${with_umad_libs+set}" = set; then
+  withval=$with_umad_libs; { $as_echo "$as_me:$LINENO: Using ibumad libs from:$with_umad_libs" >&5
+$as_echo "$as_me: Using ibumad libs from:$with_umad_libs" >&6;}
+else
+  with_umad_libs=""
+fi
+
+
+if test x$with_umad_libs = x; then
+   if test x$with_umad_prefix != x; then
+      if test "$(uname -m)" = "x86_64" -o "$(uname -m)" = "ppc64"; then
+         with_umad_libs=$with_umad_prefix/lib64
+      else
+         with_umad_libs=$with_umad_prefix/lib
+      fi
+   fi
+fi
+
+
+# Check whether --with-sim was given.
+if test "${with_sim+set}" = set; then
+  withval=$with_sim; { $as_echo "$as_me:$LINENO: Using Simulator from:$with_sim" >&5
+$as_echo "$as_me: Using Simulator from:$with_sim" >&6;}
+else
+  with_sim="/usr"
+fi
+
+
+if test $with_osmv = "openib"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSM_VENDOR_INTF_OPENIB 1
+_ACEOF
+
+   OSMV_INCLUDES="-I\$(srcdir)/../include -I\$(srcdir)/../../libibcommon/include -I\$(srcdir)/../../libibumad/include -I\$(includedir)"
+   OSMV_LDADD="-L\$(abs_srcdir)/../../libibumad/.libs -L\$(abs_srcdir)/../../libibcommon/.libs -L\$(libdir) -libumad -libcommon"
+
+   if test "x$with_umad_libs" != "x"; then
+      OSMV_LDADD="-L$with_umad_libs $OSMV_LDADD"
+   fi
+
+   if test "x$with_umad_includes" != "x"; then
+      OSMV_INCLUDES="-I$with_umad_includes $OSMV_INCLUDES"
+   fi
+
+cat >>confdefs.h <<\_ACEOF
+#define DUAL_SIDED_RMPP 1
+_ACEOF
+
+elif test $with_osmv = "sim" ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSM_VENDOR_INTF_SIM 1
+_ACEOF
+
+   OSMV_INCLUDES="-I$with_sim/include -I\$(srcdir)/../include"
+   OSMV_LDADD="-L$with_sim/lib -libmscli"
+elif test $with_osmv = "gen1"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSM_VENDOR_INTF_TS 1
+_ACEOF
+
+
+   if test -z $MTHOME; then
+      MTHOME=/usr/local/ibgd/driver/infinihost
+   fi
+
+   OSMV_INCLUDES="-I$MTHOME/include -I\$(srcdir)/../include"
+
+      osmv_found=0
+   if test -z $TSHOME; then
+      osmv_dir=`uname -r|sed 's/-smp//'`
+      osmv_dir_smp=`uname -r`
+      for d in /usr/src/linux-$osmv_dir /usr/src/linux-$osmv_dir_smp /lib/modules/$osmv_dir/build /lib/modules/$osmv_dir_smp/build/; do
+         if test -f $d/drivers/infiniband/include/ts_ib_useraccess.h; then
+            OSMV_INCLUDES="$OSMV_INCLUDES -I$d/drivers/infiniband/include"
+            osmv_found=1
+         fi
+      done
+   else
+      if test -f  $TSHOME/ts_ib_useraccess.h; then
+         OSMV_INCLUDES="$OSMV_INCLUDES -I$TSHOME"
+         osmv_found=1
+      fi
+   fi
+   if test $osmv_found = 0; then
+      { { $as_echo "$as_me:$LINENO: error: Fail to find gen1 include files dir" >&5
+$as_echo "$as_me: error: Fail to find gen1 include files dir" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+   OSMV_LDADD="-L/usr/local/ibgd/driver/infinihost/lib -lvapi -lmosal -lmtl_common -lmpga"
+elif test $with_osmv = "vapi"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSM_VENDOR_INTF_MTL 1
+_ACEOF
+
+   OSMV_INCLUDES="-I/usr/mellanox/include -I/usr/include -I\$(srcdir)/../include"
+   OSMV_LDADD="-L/usr/lib -L/usr/mellanox/lib -lib_mgt -lvapi -lmosal -lmtl_common -lmpga"
+else
+   { { $as_echo "$as_me:$LINENO: error: Invalid Vendor Type provided:$with_osmv should be either openib,sim,gen1" >&5
+$as_echo "$as_me: error: Invalid Vendor Type provided:$with_osmv should be either openib,sim,gen1" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ if test $with_osmv = "vapi"; then
+  OSMV_VAPI_TRUE=
+  OSMV_VAPI_FALSE='#'
+else
+  OSMV_VAPI_TRUE='#'
+  OSMV_VAPI_FALSE=
+fi
+
+ if test $with_osmv = "gen1"; then
+  OSMV_GEN1_TRUE=
+  OSMV_GEN1_FALSE='#'
+else
+  OSMV_GEN1_TRUE='#'
+  OSMV_GEN1_FALSE=
+fi
+
+ if test $with_osmv = "sim"; then
+  OSMV_SIM_TRUE=
+  OSMV_SIM_FALSE='#'
+else
+  OSMV_SIM_TRUE='#'
+  OSMV_SIM_FALSE=
+fi
+
+ if test $with_osmv = "openib"; then
+  OSMV_OPENIB_TRUE=
+  OSMV_OPENIB_FALSE='#'
+else
+  OSMV_OPENIB_TRUE='#'
+  OSMV_OPENIB_FALSE=
+fi
+
+
+cat >>confdefs.h <<\_ACEOF
+#define VENDOR_RMPP_SUPPORT 1
+_ACEOF
+
+
+
+
+
+# --- END OPENIB_APP_OSMV_SEL ---
+
+
+
+# --- BEGIN OPENIB_APP_OSMV_CHECK_HEADER ---
+
+if test "$disable_libcheck" != "yes"; then
+ if test $with_osmv = "openib"; then
+   osmv_headers=infiniband/umad.h
+ elif test $with_osmv = "sim" ; then
+   osmv_headers=ibmgtsim/ibms_client_api.h
+ elif test $with_osmv = "gen1"; then
+   osmv_headers=
+ elif test $with_osmv = "vapi"; then
+   osmv_headers=vapi.h
+ else
+   { { $as_echo "$as_me:$LINENO: error: OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_HEADER" >&5
+$as_echo "$as_me: error: OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_HEADER" >&2;}
+   { (exit 1); exit 1; }; }
+ fi
+ if test "x$osmv_headers" != "x"; then
+
+for ac_header in $osmv_headers
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
+$as_echo_n "checking $ac_header usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
+$as_echo_n "checking $ac_header presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------------------- ##
+## Report this to general at lists.openfabrics.org ##
+## -------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+
+fi
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ fi
+fi
+# --- END OPENIB_APP_OSMV_CHECK_HEADER ---
+
+
+# --- BEGIN OPENIB_APP_OSMV_CHECK_LIB ---
+if test "$disable_libcheck" != "yes"; then
+
+  if test $with_osmv = "openib"; then
+   LDADD="$LDADD $OSMV_LDADD"
+
+{ $as_echo "$as_me:$LINENO: checking for umad_init in -libumad" >&5
+$as_echo_n "checking for umad_init in -libumad... " >&6; }
+if test "${ac_cv_lib_ibumad_umad_init+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-libumad  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char umad_init ();
+int
+main ()
+{
+return umad_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_ibumad_umad_init=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_ibumad_umad_init=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ibumad_umad_init" >&5
+$as_echo "$ac_cv_lib_ibumad_umad_init" >&6; }
+if test "x$ac_cv_lib_ibumad_umad_init" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBIBUMAD 1
+_ACEOF
+
+  LIBS="-libumad $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: umad_init() not found. libosmvendor of type openib requires libibumad." >&5
+$as_echo "$as_me: error: umad_init() not found. libosmvendor of type openib requires libibumad." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ elif test $with_osmv = "sim" ; then
+   LDFLAGS="$LDFLAGS -L$with_sim/lib"
+   as_ac_File=`$as_echo "ac_cv_file_$with_sim/lib/libibmscli.a" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $with_sim/lib/libibmscli.a" >&5
+$as_echo_n "checking for $with_sim/lib/libibmscli.a... " >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  test "$cross_compiling" = yes &&
+  { { $as_echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+$as_echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+if test -r "$with_sim/lib/libibmscli.a"; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval 'as_val=${'$as_ac_File'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_File'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: ibms_bind() not found. libosmvendor of type sim requires libibmscli." >&5
+$as_echo "$as_me: error: ibms_bind() not found. libosmvendor of type sim requires libibmscli." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ elif test $with_osmv = "gen1"; then
+   LDFLAGS="$LDFLAGS -L$MTHOME/lib -L$MTHOME/lib64 -lmosal -lmtl_common -lmpga"
+
+{ $as_echo "$as_me:$LINENO: checking for vipul_init in -lvapi" >&5
+$as_echo_n "checking for vipul_init in -lvapi... " >&6; }
+if test "${ac_cv_lib_vapi_vipul_init+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lvapi  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char vipul_init ();
+int
+main ()
+{
+return vipul_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_vapi_vipul_init=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_vapi_vipul_init=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_vapi_vipul_init" >&5
+$as_echo "$ac_cv_lib_vapi_vipul_init" >&6; }
+if test "x$ac_cv_lib_vapi_vipul_init" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBVAPI 1
+_ACEOF
+
+  LIBS="-lvapi $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: vipul_init() not found. libosmvendor of type gen1 requires libvapi." >&5
+$as_echo "$as_me: error: vipul_init() not found. libosmvendor of type gen1 requires libvapi." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ elif test $with_osmv != "vapi"; then
+   { { $as_echo "$as_me:$LINENO: error: OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_LIB" >&5
+$as_echo "$as_me: error: OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_LIB" >&2;}
+   { (exit 1); exit 1; }; }
+ fi
+fi
+# --- END OPENIB_APP_OSMV_CHECK_LIB ---
+
+
+ac_config_files="$ac_config_files man/opensm.8 scripts/opensm.init scripts/redhat-opensm.init scripts/sldd.sh"
+
+
+ac_config_files="$ac_config_files include/opensm/osm_version.h Makefile include/Makefile complib/Makefile libvendor/Makefile opensm/Makefile osmeventplugin/Makefile osmtest/Makefile opensm.spec"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OSMV_VAPI_TRUE}" && test -z "${OSMV_VAPI_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"OSMV_VAPI\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"OSMV_VAPI\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OSMV_GEN1_TRUE}" && test -z "${OSMV_GEN1_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"OSMV_GEN1\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"OSMV_GEN1\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OSMV_SIM_TRUE}" && test -z "${OSMV_SIM_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"OSMV_SIM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"OSMV_SIM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OSMV_OPENIB_TRUE}" && test -z "${OSMV_OPENIB_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"OSMV_OPENIB\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"OSMV_OPENIB\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by opensm $as_me 3.2.6_20090317, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTION]... [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf at gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+opensm config.status 3.2.6_20090317
+configured by $0, generated by GNU Autoconf 2.63,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_FILES="$CONFIG_FILES '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { $as_echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { $as_echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
+enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
+host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
+host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
+host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
+build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
+build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
+build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
+SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
+Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
+GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
+EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
+FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
+LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
+NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
+LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
+exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
+AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
+GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
+SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
+ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
+need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
+LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
+libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
+version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
+striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+SHELL \
+ECHO \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\$0 --fallback-echo"')  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
+  ;;
+esac
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;;
+    "include/opensm/osm_config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/opensm/osm_config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "man/opensm.8") CONFIG_FILES="$CONFIG_FILES man/opensm.8" ;;
+    "scripts/opensm.init") CONFIG_FILES="$CONFIG_FILES scripts/opensm.init" ;;
+    "scripts/redhat-opensm.init") CONFIG_FILES="$CONFIG_FILES scripts/redhat-opensm.init" ;;
+    "scripts/sldd.sh") CONFIG_FILES="$CONFIG_FILES scripts/sldd.sh" ;;
+    "include/opensm/osm_version.h") CONFIG_FILES="$CONFIG_FILES include/opensm/osm_version.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "complib/Makefile") CONFIG_FILES="$CONFIG_FILES complib/Makefile" ;;
+    "libvendor/Makefile") CONFIG_FILES="$CONFIG_FILES libvendor/Makefile" ;;
+    "opensm/Makefile") CONFIG_FILES="$CONFIG_FILES opensm/Makefile" ;;
+    "osmeventplugin/Makefile") CONFIG_FILES="$CONFIG_FILES osmeventplugin/Makefile" ;;
+    "osmtest/Makefile") CONFIG_FILES="$CONFIG_FILES osmtest/Makefile" ;;
+    "opensm.spec") CONFIG_FILES="$CONFIG_FILES opensm.spec" ;;
+
+  *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   $as_echo "$as_me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr='
'
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5
+$as_echo "$as_me: error: could not setup config files machinery" >&2;}
+   { (exit 1); exit 1; }; }
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5
+$as_echo "$as_me: error: could not setup config headers machinery" >&2;}
+   { (exit 1); exit 1; }; }
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5
+$as_echo "$as_me: error: invalid tag $ac_tag" >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      ac_file_inputs="$ac_file_inputs '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:$LINENO: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; } ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5
+$as_echo "$as_me: error: could not create -" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || # Autoconf 2.62 quotes --file arguments for eval, but not when files
+# are listed without --file.  Let's play safe and only enable the eval
+# if we detect the quoting.
+case $CONFIG_FILES in
+*\'*) eval set x "$CONFIG_FILES" ;;
+*)   set x $CONFIG_FILES ;;
+esac
+shift
+for mf
+do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+    dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    { as_dir=$dirpart/$fdir
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that does not interpret backslashes.
+ECHO=$lt_ECHO
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1+=\$2"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+    ;;
+  esac
+
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..74e2d69
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,232 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.57)
+AC_INIT(opensm, 3.2.6_20090317, general at lists.openfabrics.org)
+AC_CONFIG_SRCDIR([opensm/osm_opensm.c])
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_HEADERS(include/config.h include/opensm/osm_config.h)
+AM_INIT_AUTOMAKE
+
+AC_SUBST(RELEASE, ${RELEASE:-unknown})
+AC_SUBST(TARBALL, ${TARBALL:-${PACKAGE}-${VERSION}.tar.gz})
+
+dnl NOTE: AC_DEFINE's and AC_DEFINE_UNQUOTED's which are used in header files
+dnl       MUST have a corresponding entry in include/opensm/osm_config.h.in to
+dnl       ensure plugin compatibility.
+AC_DEFINE(_OSM_CONFIG_H_, 1, mark config.h inclusion)
+
+dnl Defines the Language
+AC_LANG_C
+
+dnl Required for cases make defines a MAKE=make ??? Why
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_YACC
+AC_PROG_LEX
+
+AC_CHECK_PROGS(_YACC_,$YACC,none)
+if test "$_YACC_" = "none"
+then
+  AC_MSG_ERROR([No bison/byacc/yacc found.])
+fi
+
+AC_CHECK_PROGS(_LEX_,$LEX,none)
+if test "$_LEX_" = "none"
+then
+  AC_MSG_ERROR([No flex/lex found.])
+fi
+
+dnl Checks for libraries
+AC_CHECK_LIB(pthread, pthread_mutex_init, [],
+	AC_MSG_ERROR([pthread_mutex_init() not found.  libosmcomp requires libpthread.]))
+AC_CHECK_LIB(dl, dlopen, [],
+	AC_MSG_ERROR([dlopen() not found. OpenSM requires libdl.]))
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_C_VOLATILE
+
+dnl We use --version-script with ld if possible
+AC_CACHE_CHECK(whether ld accepts --version-script, ac_cv_version_script,
+if test -n "`$LD --help < /dev/null 2>/dev/null | grep version-script`"; then
+	ac_cv_version_script=yes
+else
+	ac_cv_version_script=no
+fi)
+AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$ac_cv_version_script" = "yes")
+
+dnl Define an input config option to control debug compile
+AC_ARG_ENABLE(debug,    [  --enable-debug          Turn on debugging],
+[case "${enableval}" in
+	yes) debug=true ;;
+	no)  debug=false ;;
+	*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+esac],debug=false)
+if test x$debug = xtrue ; then
+	AC_DEFINE(OSM_DEBUG, 1, [ define 1 if OpenSM build is in a debug mode ])
+fi
+AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
+
+AC_ARG_ENABLE(libcheck, [  --disable-libcheck      do not test for presence of ib libraries],
+[if test x$enableval = xno ; then
+	disable_libcheck=yes
+fi])
+
+dnl check if they want the socket console
+OPENIB_OSM_CONSOLE_SOCKET_SEL
+
+dnl select performance manager or not
+OPENIB_OSM_PERF_MGR_SEL
+
+dnl resolve <sysconfdir> config dir.
+conf_dir_tmp1="`eval echo ${sysconfdir} | sed 's/^NONE/$ac_default_prefix/'`"
+SYS_CONFIG_DIR="`eval echo $conf_dir_tmp1`"
+
+dnl Check for a different subdir for the config files.
+OPENSM_CONFIG_SUB_DIR=opensm
+AC_MSG_CHECKING(for --with-opensm-conf-sub-dir)
+AC_ARG_WITH(opensm-conf-sub-dir,
+    AC_HELP_STRING([--with-opensm-conf-sub-dir=dir],
+                   [define a directory name for opensm's conf files <sysconfdir>/<dir> (default "opensm")]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        OPENSM_CONFIG_SUB_DIR=$withval
+        ;;
+    esac ]
+)
+dnl this needs to be configured for rpmbuilds separate from the full path
+dnl "OPENSM_CONFIG_DIR"
+AC_SUBST(OPENSM_CONFIG_SUB_DIR)
+
+OPENSM_CONFIG_DIR=$SYS_CONFIG_DIR/$OPENSM_CONFIG_SUB_DIR
+AC_MSG_RESULT($OPENSM_CONFIG_DIR)
+AC_DEFINE_UNQUOTED(OPENSM_CONFIG_DIR,
+	["$OPENSM_CONFIG_DIR"],
+	[Define OpenSM config directory])
+AC_SUBST(OPENSM_CONFIG_DIR)
+
+dnl Check for a different default OpenSm config file
+OPENSM_CONFIG_FILE=opensm.conf
+AC_MSG_CHECKING(for --with-opensm-conf-file )
+AC_ARG_WITH(opensm-conf-file,
+    AC_HELP_STRING([--with-opensm-conf-file=file],
+                   [define a default OpenSM config file (default opensm.conf)]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        OPENSM_CONFIG_FILE=$withval
+        ;;
+    esac ]
+)
+AC_MSG_RESULT(${OPENSM_CONFIG_FILE})
+AC_DEFINE_UNQUOTED(HAVE_DEFAULT_OPENSM_CONFIG_FILE,
+	["$OPENSM_CONFIG_DIR/$OPENSM_CONFIG_FILE"],
+	[Define a default OpenSM config file])
+AC_SUBST(OPENSM_CONFIG_FILE)
+
+dnl Check for a different default node name map file
+NODENAMEMAPFILE=ib-node-name-map
+AC_MSG_CHECKING(for --with-node-name-map )
+AC_ARG_WITH(node-name-map,
+    AC_HELP_STRING([--with-node-name-map=file],
+                   [define a default node name map file (default ib-node-name-map)]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        NODENAMEMAPFILE=$withval
+        ;;
+    esac ]
+)
+AC_MSG_RESULT($NODENAMEMAPFILE)
+AC_DEFINE_UNQUOTED(HAVE_DEFAULT_NODENAME_MAP,
+	["$OPENSM_CONFIG_DIR/$NODENAMEMAPFILE"],
+	[Define a default node name map file])
+AC_SUBST(NODENAMEMAPFILE)
+
+dnl Check for a different partition conf file
+PARTITION_CONFIG_FILE=partitions.conf
+AC_MSG_CHECKING(for --with-partitions-conf)
+AC_ARG_WITH(partitions-conf,
+    AC_HELP_STRING([--with-partitions-conf=file],
+                   [define a partitions config file (default partitions.conf)]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        PARTITION_CONFIG_FILE=$withval
+        ;;
+    esac ]
+)
+AC_MSG_RESULT($PARTITION_CONFIG_FILE)
+AC_DEFINE_UNQUOTED(HAVE_DEFAULT_PARTITION_CONFIG_FILE,
+	["$OPENSM_CONFIG_DIR/$PARTITION_CONFIG_FILE"],
+	[Define a Partition config file])
+AC_SUBST(PARTITION_CONFIG_FILE)
+
+dnl Check for a different QOS policy file
+QOS_POLICY_FILE=qos-policy.conf
+AC_MSG_CHECKING(for --with-qos-policy-conf)
+AC_ARG_WITH(qos-policy-conf,
+    AC_HELP_STRING([--with-qos-policy-conf=file],
+                   [define a QOS policy config file (default qos-policy.conf)]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        QOS_POLICY_FILE=$withval
+        ;;
+    esac ]
+)
+AC_MSG_RESULT($QOS_POLICY_FILE)
+AC_DEFINE_UNQUOTED(HAVE_DEFAULT_QOS_POLICY_FILE,
+	["$OPENSM_CONFIG_DIR/$QOS_POLICY_FILE"],
+	[Define a QOS policy config file])
+AC_SUBST(QOS_POLICY_FILE)
+
+dnl Check for a different prefix-routes file
+PREFIX_ROUTES_FILE=prefix-routes.conf
+AC_MSG_CHECKING(for --with-prefix-routes-conf)
+AC_ARG_WITH(prefix-routes-conf,
+    AC_HELP_STRING([--with-prefix-routes-conf=file],
+                   [define a Prefix Routes config file (default is prefix-routes.conf)]),
+    [ case "$withval" in
+    no)
+        ;;
+    *)
+        PREFIX_ROUTES_FILE=$withval
+        ;;
+    esac ]
+)
+AC_MSG_RESULT($PREFIX_ROUTES_FILE)
+AC_DEFINE_UNQUOTED(HAVE_DEFAULT_PREFIX_ROUTES_FILE,
+	["$OPENSM_CONFIG_DIR/$PREFIX_ROUTES_FILE"],
+	[Define a Prefix Routes config file])
+AC_SUBST(PREFIX_ROUTES_FILE)
+
+dnl select example event plugin or not
+OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL
+
+dnl Provide user option to select vendor
+OPENIB_APP_OSMV_SEL
+
+dnl Checks for headers and libraries
+OPENIB_APP_OSMV_CHECK_HEADER
+OPENIB_APP_OSMV_CHECK_LIB
+
+AC_CONFIG_FILES([man/opensm.8 scripts/opensm.init scripts/redhat-opensm.init scripts/sldd.sh])
+
+dnl Create the following Makefiles
+AC_OUTPUT([include/opensm/osm_version.h Makefile include/Makefile complib/Makefile libvendor/Makefile opensm/Makefile osmeventplugin/Makefile osmtest/Makefile opensm.spec])
diff --git a/doc/QoS_management_in_OpenSM.txt b/doc/QoS_management_in_OpenSM.txt
new file mode 100644
index 0000000..8c9915f
--- /dev/null
+++ b/doc/QoS_management_in_OpenSM.txt
@@ -0,0 +1,492 @@
+
+                    QoS Management in OpenSM
+
+==============================================================================
+ Table of contents
+==============================================================================
+
+1. Overview
+2. Full QoS Policy File
+3. Simplified QoS Policy Definition
+4. Policy File Syntax Guidelines
+5. Examples of Full Policy File
+6. Simplified QoS Policy - Details and Examples
+7. SL2VL Mapping and VL Arbitration
+
+
+==============================================================================
+ 1. Overview
+==============================================================================
+
+When QoS in OpenSM is enabled (-Q or --qos), OpenSM looks for QoS Policy file.
+The default name of OpenSM QoS policy file is
+/usr/local/etc/opensm/qos-policy.conf. The default may be changed by using -Y
+or --qos_policy_file option with OpenSM.
+
+During fabric initialization and at every heavy sweep OpenSM parses the QoS
+policy file, applies its settings to the discovered fabric elements, and
+enforces the provided policy on client requests. The overall flow for such
+requests is:
+ - The request is matched against the defined matching rules such that the
+   QoS Level definition is found.
+ - Given the QoS Level, path(s) search is performed with the given
+   restrictions imposed by that level.
+
+There are two ways to define QoS policy:
+ - Full policy, where the policy file syntax provides an administrator
+   various ways to match PathRecord/MultiPathRecord (PR/MPR) request and
+   enforce various QoS constraints on the requested PR/MPR
+ - Simplified QoS policy definition, where an administrator would be able to
+   match PR/MPR requests by various ULPs and applications running on top of
+   these ULPs.
+
+While the full policy syntax is very flexible, in many cases the simplified
+policy definition would be sufficient.
+
+
+==============================================================================
+ 2. Full QoS Policy File
+==============================================================================
+
+QoS policy file has the following sections:
+
+I) Port Groups (denoted by port-groups).
+This section defines zero or more port groups that can be referred later by
+matching rules (see below). Port group lists ports by:
+  - Port GUID
+  - Port name, which is a combination of NodeDescription and IB port number
+  - PKey, which means that all the ports in the subnet that belong to
+    partition with a given PKey belong to this port group
+  - Partition name, which means that all the ports in the subnet that belong
+    to partition with a given name belong to this port group
+  - Node type, where possible node types are: CA, SWITCH, ROUTER, ALL, and
+    SELF (SM's port).
+
+II) QoS Setup (denoted by qos-setup).
+This section describes how to set up SL2VL and VL Arbitration tables on
+various nodes in the fabric.
+However, this is not supported in OpenSM currently.
+SL2VL and VLArb tables should be configured in the OpenSM options file
+(default location - /usr/local/etc/opensm/opensm.conf).
+
+III) QoS Levels (denoted by qos-levels).
+Each QoS Level defines Service Level (SL) and a few optional fields:
+  - MTU limit
+  - Rate limit
+  - PKey
+  - Packet lifetime
+When path(s) search is performed, it is done with regards to restriction that
+these QoS Level parameters impose.
+One QoS level that is mandatory to define is a DEFAULT QoS level. It is
+applied to a PR/MPR query that does not match any existing match rule.
+Similar to any other QoS Level, it can also be explicitly referred by any
+match rule.
+
+IV) QoS Matching Rules (denoted by qos-match-rules).
+Each PathRecord/MultiPathRecord query that OpenSM receives is matched against
+the set of matching rules. Rules are scanned in order of appearance in the QoS
+policy file such as the first match takes precedence.
+Each rule has a name of QoS level that will be applied to the matching query.
+A default QoS level is applied to a query that did not match any rule.
+Queries can be matched by:
+ - Source port group (whether a source port is a member of a specified group)
+ - Destination port group (same as above, only for destination port)
+ - PKey
+ - QoS class
+ - Service ID
+To match a certain matching rule, PR/MPR query has to match ALL the rule's
+criteria. However, not all the fields of the PR/MPR query have to appear in
+the matching rule.
+For instance, if the rule has a single criterion - Service ID, it will match
+any query that has this Service ID, disregarding rest of the query fields.
+However, if a certain query has only Service ID (which means that this is the
+only bit in the PR/MPR component mask that is on), it will not match any rule
+that has other matching criteria besides Service ID.
+
+
+==============================================================================
+ 3. Simplified QoS Policy Definition
+==============================================================================
+
+Simplified QoS policy definition comprises of a single section denoted by
+qos-ulps. Similar to the full QoS policy, it has a list of match rules and
+their QoS Level, but in this case a match rule has only one criterion - its
+goal is to match a certain ULP (or a certain application on top of this ULP)
+PR/MPR request, and QoS Level has only one constraint - Service Level (SL).
+The simplified policy section may appear in the policy file in combine with
+the full policy, or as a stand-alone policy definition.
+See more details and list of match rule criteria below.
+
+
+==============================================================================
+ 4. Policy File Syntax Guidelines
+==============================================================================
+
+- Empty lines are ignored.
+- Leading and trailing blanks, as well as empty lines, are ignored, so
+  the indentation in the example is just for better readability.
+- Comments are started with the pound sign (#) and terminated by EOL.
+- Any keyword should be the first non-blank in the line, unless it's a
+  comment.
+- Keywords that denote section/subsection start have matching closing
+  keywords.
+- Having a QoS Level named "DEFAULT" is a must - it is applied to PR/MPR
+  requests that didn't match any of the matching rules.
+- Any section/subsection of the policy file is optional.
+
+
+==============================================================================
+ 5. Examples of Full Policy File
+==============================================================================
+
+As mentioned earlier, any section of the policy file is optional, and
+the only mandatory part of the policy file is a default QoS Level.
+Here's an example of the shortest policy file:
+
+    qos-levels
+        qos-level
+            name: DEFAULT
+            sl: 0
+        end-qos-level
+    end-qos-levels
+
+Port groups section is missing because there are no match rules, which means
+that port groups are not referred anywhere, and there is no need defining
+them. And since this policy file doesn't have any matching rules, PR/MPR query
+won't match any rule, and OpenSM will enforce default QoS level.
+Essentially, the above example is equivalent to not having QoS policy file
+at all.
+
+The following example shows all the possible options and keywords in the
+policy file and their syntax:
+
+    #
+    # See the comments in the following example.
+    # They explain different keywords and their meaning.
+    #
+    port-groups
+
+        port-group # using port GUIDs
+            name: Storage
+            # "use" is just a description that is used for logging
+            #  Other than that, it is just a comment
+            use: SRP Targets
+            port-guid: 0x10000000000001, 0x10000000000005-0x1000000000FFFA
+            port-guid: 0x1000000000FFFF
+        end-port-group
+
+        port-group
+            name: Virtual Servers
+            # The syntax of the port name is as follows:
+            #   "node_description/Pnum".
+            # node_description is compared to the NodeDescription of the node,
+            # and "Pnum" is a port number on that node.
+            port-name: vs1 HCA-1/P1, vs2 HCA-1/P1
+        end-port-group
+
+        # using partitions defined in the partition policy
+        port-group
+            name: Partitions
+            partition: Part1
+            pkey: 0x1234
+        end-port-group
+
+        # using node types: CA, ROUTER, SWITCH, SELF (for node that runs SM)
+        # or ALL (for all the nodes in the subnet)
+        port-group
+            name: CAs and SM
+            node-type: CA, SELF
+        end-port-group
+
+    end-port-groups
+
+    qos-setup
+        # This section of the policy file describes how to set up SL2VL and VL
+        # Arbitration tables on various nodes in the fabric.
+        # However, this is not supported in OpenSM currently - the section is
+        # parsed and ignored. SL2VL and VLArb tables should be configured in the
+        # OpenSM options file (by default - /usr/local/etc/opensm/opensm.conf).
+    end-qos-setup
+
+    qos-levels
+
+        # Having a QoS Level named "DEFAULT" is a must - it is applied to
+        # PR/MPR requests that didn't match any of the matching rules.
+        qos-level
+            name: DEFAULT
+            use: default QoS Level
+            sl: 0
+        end-qos-level
+
+        # the whole set: SL, MTU-Limit, Rate-Limit, PKey, Packet Lifetime
+        qos-level
+            name: WholeSet
+            sl: 1
+            mtu-limit: 4
+            rate-limit: 5
+            pkey: 0x1234
+            packet-life: 8
+        end-qos-level
+
+    end-qos-levels
+
+    # Match rules are scanned in order of their apperance in the policy file.
+    # First matched rule takes precedence.
+    qos-match-rules
+
+        # matching by single criteria: QoS class
+        qos-match-rule
+            use: by QoS class
+            qos-class: 7-9,11
+            # Name of qos-level to apply to the matching PR/MPR
+            qos-level-name: WholeSet
+        end-qos-match-rule
+
+        # show matching by destination group and service id
+        qos-match-rule
+            use: Storage targets
+            destination: Storage
+            service-id: 0x10000000000001, 0x10000000000008-0x10000000000FFF
+            qos-level-name: WholeSet
+        end-qos-match-rule
+
+        qos-match-rule
+            source: Storage
+            use: match by source group only
+            qos-level-name: DEFAULT
+        end-qos-match-rule
+
+        qos-match-rule
+            use: match by all parameters
+            qos-class: 7-9,11
+            source: Virtual Servers
+            destination: Storage
+            service-id: 0x0000000000010000-0x000000000001FFFF
+            pkey: 0x0F00-0x0FFF
+            qos-level-name: WholeSet
+        end-qos-match-rule
+
+    end-qos-match-rules
+
+
+==============================================================================
+ 6. Simplified QoS Policy - Details and Examples
+==============================================================================
+
+Simplified QoS policy match rules are tailored for matching ULPs (or some
+application on top of a ULP) PR/MPR requests. This section has a list of
+per-ULP (or per-application) match rules and the SL that should be enforced
+on the matched PR/MPR query.
+
+Match rules include:
+ - Default match rule that is applied to PR/MPR query that didn't match any
+   of the other match rules
+ - SDP
+ - SDP application with a specific target TCP/IP port range
+ - SRP with a specific target IB port GUID
+ - RDS
+ - iSER
+ - iSER application with a specific target TCP/IP port range
+ - IPoIB with a default PKey
+ - IPoIB with a specific PKey
+ - any ULP/application with a specific Service ID in the PR/MPR query
+ - any ULP/application with a specific PKey in the PR/MPR query
+ - any ULP/application with a specific target IB port GUID in the PR/MPR query
+
+Since any section of the policy file is optional, as long as basic rules of
+the file are kept (such as no referring to nonexisting port group, having
+default QoS Level, etc), the simplified policy section (qos-ulps) can serve
+as a complete QoS policy file.
+The shortest policy file in this case would be as follows:
+
+    qos-ulps
+        default  : 0 #default SL
+    end-qos-ulps
+
+It is equivalent to the previous example of the shortest policy file, and it
+is also equivalent to not having policy file at all.
+
+Below is an example of simplified QoS policy with all the possible keywords:
+
+    qos-ulps
+        default                       : 0 # default SL
+        sdp, port-num 30000           : 0 # SL for application running on top
+                                          # of SDP when a destination
+                                          # TCP/IPport is 30000
+        sdp, port-num 10000-20000     : 0
+        sdp                           : 1 # default SL for any other
+                                          # application running on top of SDP
+        rds                           : 2 # SL for RDS traffic
+        iser, port-num 900            : 0 # SL for iSER with a specific target
+                                          # port
+        iser                          : 3 # default SL for iSER
+        ipoib, pkey 0x0001            : 0 # SL for IPoIB on partition with
+                                          # pkey 0x0001
+        ipoib                         : 4 # default IPoIB partition,
+                                          # pkey=0x7FFF
+        any, service-id 0x6234        : 6 # match any PR/MPR query with a
+                                          # specific Service ID
+        any, pkey 0x0ABC              : 6 # match any PR/MPR query with a
+                                          # specific PKey
+        srp, target-port-guid 0x1234  : 5 # SRP when SRP Target is located on
+                                          # a specified IB port GUID
+        any, target-port-guid 0x0ABC-0xFFFFF : 6 # match any PR/MPR query with
+                                          # a specific target port GUID
+    end-qos-ulps
+
+
+Similar to the full policy definition, matching of PR/MPR queries is done in
+order of appearance in the QoS policy file such as the first match takes
+precedence, except for the "default" rule, which is applied only if the query
+didn't match any other rule.
+
+All other sections of the QoS policy file take precedence over the qos-ulps
+section. That is, if a policy file has both qos-match-rules and qos-ulps
+sections, then any query is matched first against the rules in the
+qos-match-rules section, and only if there was no match, the query is matched
+against the rules in qos-ulps section.
+
+Note that some of these match rules may overlap, so in order to use the
+simplified QoS definition effectively, it is important to understand how each
+of the ULPs is matched:
+
+6.1  IPoIB
+IPoIB query is matched by PKey. Default PKey for IPoIB partition is 0x7fff, so
+the following three match rules are equivalent:
+
+    ipoib              : <SL>
+    ipoib, pkey 0x7fff : <SL>
+    any,   pkey 0x7fff : <SL>
+
+6.2  SDP
+SDP PR query is matched by Service ID. The Service-ID for SDP is
+0x000000000001PPPP, where PPPP are 4 hex digits holding the remote TCP/IP Port
+Number to connect to. The following two match rules are equivalent:
+
+    sdp                                                   : <SL>
+    any, service-id 0x0000000000010000-0x000000000001ffff : <SL>
+
+6.3  RDS
+Similar to SDP, RDS PR query is matched by Service ID. The Service ID for RDS
+is 0x000000000106PPPP, where PPPP are 4 hex digits holding the remote TCP/IP
+Port Number to connect to. Default port number for RDS is 0x48CA, which makes
+a default Service-ID 0x00000000010648CA. The following two match rules are
+equivalent:
+
+    rds                                : <SL>
+    any, service-id 0x00000000010648CA : <SL>
+
+6.4  iSER
+Similar to RDS, iSER query is matched by Service ID, where the the Service ID
+is also 0x000000000106PPPP. Default port number for iSER is 0x0CBC, which makes
+a default Service-ID 0x0000000001060CBC. The following two match rules are
+equivalent:
+
+    iser                               : <SL>
+    any, service-id 0x0000000001060CBC : <SL>
+
+6.5  SRP
+Service ID for SRP varies from storage vendor to vendor, thus SRP query is
+matched by the target IB port GUID. The following two match rules are
+equivalent:
+
+    srp, target-port-guid 0x1234  : <SL>
+    any, target-port-guid 0x1234  : <SL>
+
+Note that any of the above ULPs might contain target port GUID in the PR
+query, so in order for these queries not to be recognized by the QoS manager
+as SRP, the SRP match rule (or any match rule that refers to the target port
+guid only) should be placed at the end of the qos-ulps match rules.
+
+6.6  MPI
+SL for MPI is manually configured by MPI admin. OpenSM is not forcing any SL
+on the MPI traffic, and that's why it is the only ULP that did not appear in
+the qos-ulps section.
+
+
+==============================================================================
+ 7. SL2VL Mapping and VL Arbitration
+==============================================================================
+
+OpenSM cached options file has a set of QoS related configuration parameters,
+that are used to configure SL2VL mapping and VL arbitration on IB ports.
+These parameters are:
+ - Max VLs: the maximum number of VLs that will be on the subnet.
+ - High limit: the limit of High Priority component of VL Arbitration
+   table (IBA 7.6.9).
+ - VLArb low table: Low priority VL Arbitration table (IBA 7.6.9) template.
+ - VLArb high table: High priority VL Arbitration table (IBA 7.6.9) template.
+ - SL2VL: SL2VL Mapping table (IBA 7.6.6) template. It is a list of VLs
+   corresponding to SLs 0-15 (Note that VL15 used here means drop this SL).
+
+There are separate QoS configuration parameters sets for various target types:
+CAs, routers, switch external ports, and switch's enhanced port 0. The names
+of such parameters are prefixed by "qos_<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.
+
+Here's the example of typical default values for CAs and switches' external
+ports (hard-coded in OpenSM initialization):
+
+    qos_ca_max_vls 15
+    qos_ca_high_limit 0
+    qos_ca_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0
+    qos_ca_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4
+    qos_ca_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+    qos_swe_max_vls 15
+    qos_swe_high_limit 0
+    qos_swe_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0
+    qos_swe_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4
+    qos_swe_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+VL arbitration tables (both high and low) are lists of VL/Weight pairs.
+Each list entry contains a VL number (values from 0-14), and a weighting value
+(values 0-255), indicating the number of 64 byte units (credits) which may be
+transmitted from that VL when its turn in the arbitration occurs. A weight
+of 0 indicates that this entry should be skipped. If a list entry is
+programmed for VL15 or for a VL that is not supported or is not currently
+configured by the port, the port may either skip that entry or send from any
+supported VL for that entry.
+
+Note, that the same VLs may be listed multiple times in the High or Low
+priority arbitration tables, and, further, it can be listed in both tables.
+
+The limit of high-priority VLArb table (qos_<type>_high_limit) indicates the
+number of high-priority packets that can be transmitted without an opportunity
+to send a low-priority packet. Specifically, the number of bytes that can be
+sent is high_limit times 4K bytes.
+
+A high_limit value of 255 indicates that the byte limit is unbounded.
+Note: if the 255 value is used, the low priority VLs may be starved.
+A value of 0 indicates that only a single packet from the high-priority table
+may be sent before an opportunity is given to the low-priority table.
+
+Keep in mind that ports usually transmit packets of size equal to MTU.
+For instance, for 4KB MTU a single packet will require 64 credits, so in order
+to achieve effective VL arbitration for packets of 4KB MTU, the weighting
+values for each VL should be multiples of 64.
+
+Below is an example of SL2VL and VL Arbitration configuration on subnet:
+
+    qos_ca_max_vls 15
+    qos_ca_high_limit 6
+    qos_ca_vlarb_high 0:4
+    qos_ca_vlarb_low 0:0,1:64,2:128,3:192,4:0,5:64,6:64,7:64
+    qos_ca_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+    qos_swe_max_vls 15
+    qos_swe_high_limit 6
+    qos_swe_vlarb_high 0:4
+    qos_swe_vlarb_low 0:0,1:64,2:128,3:192,4:0,5:64,6:64,7:64
+    qos_swe_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+In this example, there are 8 VLs configured on subnet: VL0 to VL7. VL0 is
+defined as a high priority VL, and it is limited to 6 x 4KB = 24KB in a single
+transmission burst. Such configuration would suilt VL that needs low latency
+and uses small MTU when transmitting packets. Rest of VLs are defined as low
+priority VLs with different weights, while VL4 is effectively turned off.
diff --git a/doc/opensm_release_notes-3.2.txt b/doc/opensm_release_notes-3.2.txt
new file mode 100644
index 0000000..f530b95
--- /dev/null
+++ b/doc/opensm_release_notes-3.2.txt
@@ -0,0 +1,626 @@
+                        OpenSM Release Notes 3.2
+                       =============================
+
+Version: OpenSM 3.2.x
+Repo:    git://git.openfabrics.org/~sashak/management.git
+Date:    Mar 2009
+
+1 Overview
+----------
+This document describes the contents of the OpenSM 3.2 release.
+OpenSM is an InfiniBand compliant Subnet Manager and Administration,
+and runs on top of OpenIB. The OpenSM version for this release
+is opensm-3.2.6
+
+This document includes the following sections:
+1 This Overview section (describing new features and software
+  dependencies)
+2 Known Issues And Limitations
+3 Unsupported IB compliance statements
+4 Bug Fixes
+5 Main Verification Flows
+6 Qualified Software Stacks and Devices
+
+1.1 Major New Features
+
+* Cached Routing
+  OpenSM provides an optional unicast routing cache (enabled by '-A' or
+  '--ucast_cache' options). When enabled, unicast routing cache prevents
+  routing recalculation (which is a heavy task in a large cluster) when
+  there was no topology change detected during the heavy sweep, or when
+  the topology change does not require new routing calculation, e.g. when
+  one or more CAs/RTRs/leaf switches going down, or one or more of these
+  nodes coming back after being down.
+
+* Routing Chaining
+  Routing chaining is the ability to configure the order in which routing
+  algorithms are applied in opensm, i.e. '-R ftree,updn,minhop' - try
+  using ftree routing. If ftree fails, try updn. If updn fails, try
+  minhop.
+
+* IPv6 Solicited Node Multicast addresses consolidation
+  When this mode is used (enabled with --consolidate_ipv6_snm_req option)
+  OpenSM will map all IPv6 Solicited Node Multicast address join requests
+  into a single Multicast group with address ff10:601b::1:ff00:0. In this
+  way limited MLID space is saved. This IBA noncompliant feature is very
+  useful with large (~> 1024 nodes) clusters.
+
+* OpenSM sweep state machine rework
+  Huge and buggy OpenSM sweep state machine was fully rewritten in safer
+  and more effective synchronous manner.
+
+* Multi lid routing balancing for updn/minhop routing algorithms
+  When LMC > 0 is used OpenSM will ensure to generate routing paths via
+  different switches and when possible chassis.
+
+* Preserve base lid routes when LMC > 0
+  When LMC > 0 is used OpenSM will preserve routing paths for base lids
+  as it would be with LMC = 0. In this way traffic on each LID level is
+  not affected by LMC changes.
+
+* Ordered routing paths balancing
+  This adds ability to predefine the port order in which routing paths
+  balancing is performed by OpenSM. Helps to improve performance
+  dramatically (40-50%) for applications with known communication
+  pattern. Activated with --guid_routing_order_file command line option.
+
+* Unified OpenSM configuration
+  Now there is "conventional" config file instead of hidden option cache
+  file (opensm.opts). OpenSM will find this in a default place (consult
+  man page for exact value) or the file name can be specified with '-F'
+  command line option. Also there is an option ('-c') to generate config
+  file template.
+
+* Query remote SMs during light sweep
+  Master OpenSM will query remote standby SMs periodically to catch its
+  possible state changes and react accordingly (as required by IBA spec).
+
+* Predefined port ids for Up/Down algorithm
+  This is useful as Up/Down fine tuning tool - the algorithm will use
+  predefined port IDs instead of GUIDs for its decision about direction.
+  Activated with --ids_guid_file command line option.
+
+* Improved plugin API version 2.
+  Now OpenSM will provide to plugins the access to all data structures.
+  This make it possible to implement powerful multi purpose plugins. All
+  OpenSM header files are installed now and specific configuration/build
+  options are exported via generated osm_config.h header file.
+
+* Many code improvements, optimizations and cleanups
+
+* Automatic daily snapshots generation.
+  This is is not a "feature", but simplifies the access to recent OpenSM
+  bits.
+
+1.2 Minor New Features:
+
+* Cleanup cl_qlock_pool memory allocator - speedup memory allocations
+
+* Support for configurable (via OSM_UMAD_MAX_PENDING environment variable)
+  size of pending MADs pool.
+
+* Set packet life time to subnet timeout option rather than default
+
+* Enforce routing paths rebalancing on switch reconnection
+
+* In Up/Down routing algorithm compare GUID values in host byte order
+
+* Add 'switchbalance' and 'lidbalance' commands for OpenSM console
+
+* Respond to new trap 144 node description update flag
+
+* Add '--connect_roots' command line options. This preserves connectivity
+  between root nodes in Up/Down routing algorithm
+
+* Setting SL in the IPoIB MCast groups in accordance with QoS policy
+
+* Dump auto detected root node guids in Up/Down routing algorithm
+
+* Unify OpenSM dumpers code
+
+* Unify various guid files parsers - add generic nodenamemap style parser
+
+* When root node guids were provided in file update the list on each
+  Up/Down run
+
+* During ./configure show values of configuration dirs and files
+
+* Make prefix routes config file name configurable
+
+* Add a Performance Manager HOWTO to the docs and the dist
+
+* Support separate SA and SM keys as clarified in IBA 1.2.1
+
+* Remove AM_MAINTAINER_MODE in ./configure
+
+* Make vendor type OSM_VENDOR_INTF_OPENIB (libibumad) to be default
+
+* Build osm_perfmgr_db.* content only when PerfMgr is enabled.
+
+* Move PerfMgr event_db_dump_file to common OpenSM dump dir
+
+* Allow space separated strings as values in OpenSM config
+
+* Support for multiple event plugins
+
+* Add '--version' command line option
+
+* Add '--create-config <file-name>' command line option
+
+* Speedup and simplify logging code
+
+* Speedup multicast processing in SA DB
+
+* In log messages convert unicast LIDs from hex to decimal format and
+  GIDs from hex to IPv6 address format
+
+* Handle all possible ports in "ignore-guids" file
+
+* Add 'reroute' console command
+
+* Remove many install-exec-hook from Makefiles
+
+* Some cleanups in LASH routing algorithm code
+
+* In Makefiles remove -rpath and explicit -lpthread, -ldl from LDFLAGS
+  (move to configurator)
+
+* Install all OpenSM header files
+
+* Improve locking in SM Info receiver
+
+* Add new OSM_EVENT_ID_SUBNET_UP event for plugins
+
+* Redo lex and yacc files generation in conventional way
+
+* Add a missing Node Description check on light sweep.
+
+* Move vendor specific compilation defines from command to generated
+  config.h file
+
+* Provide useful error message when log file opening fails
+
+* Add generated osm_config.h file with OpenSM specific defines
+
+* Display port number in decimal in log messages
+
+* Replace osm_vendor_select.h by generated osm_config.h
+
+* Unify options listing in OpenSM usage message
+
+* LFT buffers handling simplification
+
+* Add 'dump_conf' console command
+
+* OpenSM performs sweep on SIGCONT (coming out of suspend).
+
+* When our SM is in Standby state and its priority is increased
+  (via console command), notify master SM by sending Trap 144.
+
+* When entering standby state (after discovery) notify master SM
+  with Trap 144.
+
+* support more PortInfo:CapabilityMask bits
+
+* When babbling port policy is on disable the port with the least hop
+  count.
+
+1.3 Library API Changes
+
+  None
+
+1.4 Software Dependencies
+
+OpenSM depends on the installation of either OFED 1.x, 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".
+
+Also, building of QoS manager policy file parser requires flex, and either
+bison or byacc installed.
+
+1.5 Supported Devices Firmware
+
+The main task of OpenSM is to initialize InfiniBand devices. The
+qualified devices and their corresponding firmware versions
+are listed in Table 3.
+
+2 Known Issues And Limitations
+------------------------------
+
+* No Service / Key associations:
+  There is no way to manage Service access by Keys.
+
+* No SM to SM SMDB synchronization:
+  Puts the burden of re-registering services, multicast groups, and
+  inform-info on the client application (or IB access layer core).
+
+3 Unsupported IB Compliance Statements
+--------------------------------------
+The following section lists all the IB compliance statements which
+OpenSM does not support. Please refer to the IB specification for detailed
+information regarding each compliance statement.
+
+* C14-22 (Authentication):
+  M_Key M_KeyProtectBits and M_KeyLeasePeriod shall be set in one
+  SubnSet method. As a work-around, an OpenSM option is provided for
+  defining the protect bits.
+
+* C14-67 (Authentication):
+  On SubnGet(SMInfo) and SubnSet(SMInfo) - if M_Key is not zero then
+  the SM shall generate a SubnGetResp if the M_Key matches, or
+  silently drop the packet if M_Key does not match.
+
+* C15-0.1.23.4 (Authentication):
+  InformInfoRecords shall always be provided with the QPN set to 0,
+  except for the case of a trusted request, in which case the actual
+  subscriber QPN shall be returned.
+
+* o13-17.1.2 (Event-FWD):
+  If no permission to forward, the subscription should be removed and
+  no further forwarding should occur.
+
+* C14-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 Bug Fixes
+-----------
+
+4.1 Major Bug Fixes
+
+* Set SA attribute offset to 0 when no records are returned
+
+* Send trap 64 only after new ports are in ACTIVE state.
+
+* Fix in sending client reregistration bit
+
+* Fix default OpenSM SM (and SA) Key byte order
+
+* Fix in sending Multicast groups creation/deletion notification (Traps
+  66,67)
+
+* Don't startup automatically on SuSE based systems
+
+* Discovery bug, where some ports were leaved unlinked (without remote side).
+
+4.2 Other Bug Fixes
+
+* opensm/osm_console.c: fix seg fault when running "portstatus ca" in
+  the console
+
+* opensm: fix potential core dumps where osm_node_get_physp_ptr can
+  return NULL
+
+* opensm/osm_mcast_mgr: limit spanning tree creation recursion to value
+  of max hops (64)
+
+* opensm: switch LFTs incremental update fix
+
+* opensm/osm_state_mgr.c: fix segmentation fault
+
+* opensm: eliminate some potential NULL pointer dereferences
+
+* opensm/osm_console.c: fix guid parsing
+
+* opensm: fix off by 1 issue with max_lid and max_multicat_lid_ho
+
+* opensm: fix potentially wrong port_guid initialization
+
+* opensm/configure.in: fix wrong HAVE_DEFAULT_OPENSM_CONFIG_FILE define
+  generation
+
+* opensm: fix snprintf() usage
+
+* opensm/osm_sa_lft_record: validate LFT block number
+
+* opensm/osm_sa_lft_record: pass block parameter in host byte order
+
+* opensm/include/Makefile.am: don't duplicate header files in EXTRA_DIST
+
+* opensm/osm_sa_class_port_info.c: fix over bound array access
+
+* osmtest/osmt_service.c: fix over bound array access
+
+* osmtest: fix qpn encoding in osmtest_informinfo_request()
+
+* opensm/osm_vendor_mlx_sa.c: handling attribute offset of 0
+
+* opensm: fix segfault corner case when osm_console_init fails
+
+* opensm/console: close console socket on cleanup path
+
+* opensm/osm_ucast_lash: fix buffer overflow
+
+* opensm: fix broken IPv6 SNM consolidation code
+
+* opensm/osm_sa_lft_record.c: fix block number encoding byte order
+
+* opensm/osm_sa: fix memory leak in SA responder
+
+* opensm/osm_mcast_mgr: fix memory leak
+
+* opensm: fix qos config parsing bugs
+
+* opensm/osm_mcast_tbl.c: fix sending invalid MF block due to max mlid
+  overflow
+
+* opensm: log_max_size config parameter in MB
+
+* opensm/osm_ucast_lash: fix extra memory allocations
+
+* opensm: fix race in main OpenSM flow
+
+* opensm/ftree: fix GUID check against cn_guid_file
+
+* opensm/ftree: save FLT buffers memory allocations
+
+* opensm/osm_sa_link_record.c: prevent potential endless recursion
+
+* opensm: remove SM from sm_guid_tbl when IsSM port capability flag is
+  not set
+
+* opensm: fix QoS config bug
+
+* opensm: don't reassign zeroed params from config file
+
+* opensm: update LFTs when entering master
+
+* opensm: invalidate routing cache when entering master state
+
+* opensm/osm_port_info_rcv.c: don't clear sw->need_update if port 0 is active
+
+* Other less critical or visible bugs were also fixed.
+
+5 Main Verification Flows
+-------------------------
+
+OpenSM verification is run using the following activities:
+* osmtest - a stand-alone program
+* ibmgtsim (IB management simulator) based - a set of flows that
+  simulate clusters, inject errors and verify OpenSM capability to
+  respond and bring up the network correctly.
+* small cluster regression testing - where the SM is used on back to
+  back or single switch configurations. The regression includes
+  multiple OpenSM dedicated tests.
+* cluster testing - when we run OpenSM to setup a large cluster, perform
+  hand-off, reboots and reconnects, verify routing correctness and SA
+  responsiveness at the ULP level (IPoIB and SDP).
+
+5.1 osmtest
+
+osmtest is an automated verification tool used for OpenSM
+testing. Its verification flows are described by list below.
+
+* Inventory File: Obtain and verify all port info, node info, link and path
+  records parameters.
+
+* Service Record:
+   - Register new service
+   - Register another service (with a lease period)
+   - Register another service (with service p_key set to zero)
+   - Get all services by name
+   - Delete the first service
+   - Delete the third service
+   - Added bad flows of get/delete  non valid service
+   - Add / Get same service with different data
+   - Add / Get / Delete by different component  mask values (services
+     by Name & Key / Name & Data / Name & Id / Id only )
+
+* Multicast Member Record:
+   - Query of existing Groups (IPoIB)
+   - BAD Join with insufficient comp mask (o15.0.1.3)
+   - Create given MGID=0 (o15.0.1.4)
+   - Create given MGID=0xFF12A01C,FE800000,00000000,12345678 (o15.0.1.4)
+   - Create BAD MGID=0xFA. (o15.0.1.6)
+   - Create BAD MGID=0xFF12A01B w/ link-local not set (o15.0.1.6)
+   - New MGID with invalid join state (o15.0.1.9)
+   - Retry of existing MGID - See JoinState update (o15.0.1.11)
+   - BAD RATE when connecting to existing MGID (o15.0.1.13)
+   - Partial JoinState delete request - removing FullMember (o15.0.1.14)
+   - Full Delete of a group (o15.0.1.14)
+   - Verify Delete by trying to Join deleted group (o15.0.1.14)
+   - BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)
+
+* GUIDInfo Record:
+   - All GUIDInfoRecords in subnet are obtained
+
+* MultiPathRecord:
+   - Perform some compliant and noncompliant MultiPathRecord requests
+   - Validation is via status in responses and IB analyzer
+
+* PKeyTableRecord:
+  - Perform some compliant and noncompliant PKeyTableRecord queries
+  - Validation is via status in responses and IB analyzer
+
+* LinearForwardingTableRecord:
+  - Perform some compliant and noncompliant LinearForwardingTableRecord queries
+  - Validation is via status in responses and IB analyzer
+
+* Event Forwarding: Register for trap forwarding using reports
+   - Send a trap and wait for report
+   - Unregister non-existing
+
+* Trap 64/65 Flow: Register to Trap 64-65, create traps (by
+  disconnecting/connecting ports) and wait for report, then unregister.
+
+* Stress Test: send PortInfoRecord queries, both single and RMPP and
+  check for the rate of responses as well as their validity.
+
+
+5.2 IB Management Simulator OpenSM Test Flows:
+
+The simulator provides ability to simulate the SM handling of virtual
+topologies that are not limited to actual lab equipment availability.
+OpenSM was simulated to bring up clusters of up to 10,000 nodes. Daily
+regressions use smaller (16 and 128 nodes clusters).
+
+The following test flows are run on the IB management simulator:
+
+* Stability:
+  Up to 12 links from the fabric are randomly selected to drop packets
+  at drop rates up to 90%. The SM is required to succeed in bringing the
+  fabric up. The resulting routing is verified to be correct as well.
+
+* LID Manager:
+  Using LMC = 2 the fabric is initialized with LIDs. Faults such as
+  zero LID, Duplicated LID, non-aligned (to LMC) LIDs are
+  randomly assigned to various nodes and other errors are randomly
+  output to the guid2lid cache file. The SM sweep is run 5 times and
+  after each iteration a complete verification is made to ensure that all
+  LIDs that could possibly be maintained are kept, as well as that all nodes
+  were assigned a legal LID range.
+
+* Multicast Routing:
+  Nodes randomly join the 0xc000 group and eventually the
+  resulting routing is verified for completeness and adherence to
+  Up/Down routing rules.
+
+* osmtest:
+  The complete osmtest flow as described in the previous table is run on
+  the simulated fabrics.
+
+* Stress Test:
+  This flow merges fabric, LID and stability issues with continuous
+  PathRecord, ServiceRecord and Multicast Join/Leave activity to
+  stress the SM/SA during continuous sweeps. InformInfo Set/Delete/Get
+  were added to the test such both existing and non existing nodes
+  perform them in random order.
+
+5.3 OpenSM Regression
+
+Using a back-to-back or single switch connection, the following set of
+tests is run nightly on the stacks described in table 2. The included
+tests are:
+
+* Stress Testing: Flood the SA with queries from multiple channel
+  adapters to check the robustness of the entire stack up to the SA.
+
+* Dynamic Changes: Dynamic Topology changes, through randomly
+  dropping SMP packets, used to test OpenSM adaptation to an unstable
+  network & verify DB correctness.
+
+* Trap Injection: This flow injects traps to the SM and verifies that it
+  handles them gracefully.
+
+* SA Query Test: This test exhaustively checks the SA responses to all
+  possible single component mask. To do that the test examines the
+  entire set of records the SA can provide, classifies them by their
+  field values and then selects every field (using component mask and a
+  value) and verifies that the response matches the expected set of records.
+  A random selection using multiple component mask bits is also performed.
+
+5.4 Cluster testing:
+
+Cluster testing is usually run before a distribution release. It
+involves real hardware setups of 16 to 32 nodes (or more if a beta site
+is available). Each test is validated by running all-to-all ping through the IB
+interface. The test procedure includes:
+
+* Cluster bringup
+
+* Hand-off between 2 or 3 SM's while performing:
+  - Node reboots
+  - Switch power cycles (disconnecting the SM's)
+
+* Unresponsive port detection and recovery
+
+* osmtest from multiple nodes
+
+* Trap injection and recovery
+
+
+6 Qualified Software Stacks and Devices
+---------------------------------------
+
+OpenSM Compatibility
+--------------------
+Note that OpenSM version 3.2.1 and earlier used a value of 1 in host
+byte order for the default SM_Key, so there is a compatibility issue
+with these earlier versions of OpenSM when the 3.2.2 or later version
+is running on a little endian machine. This affects SM handover as well
+as SA queries (saquery tool in infiniband-diags).
+
+
+Table 2 - Qualified IB Stacks
+=============================
+
+Stack                                    | Version
+-----------------------------------------|--------------------------
+OFED                                     |   1.4
+OFED                                     |   1.3
+OFED                                     |   1.2
+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
+------------------------------------|-------------------------------
+InfiniScale                         | fw-43132  5.2.000 (and later)
+InfiniScale III                     | fw-47396  0.5.000 (and later)
+InfiniScale IV                      | fw-48436  7.1.000 (and later)
+InfiniHost                          | fw-23108  3.5.000 (and later)
+InfiniHost III Lx                   | fw-25204  1.2.000 (and later)
+InfiniHost III Ex (InfiniHost Mode) | fw-25208  4.8.200 (and later)
+InfiniHost III Ex (MemFree Mode)    | fw-25218  5.3.000 (and later)
+ConnectX IB                         | fw-25408  2.3.000 (and later)
+
+QLogic/PathScale
+Device  |   Note
+--------|-----------------------------------------------------------
+iPath   | QHT6040 (PathScale InfiniPath HT-460)
+iPath   | QHT6140 (PathScale InfiniPath HT-465)
+iPath   | QLE6140 (PathScale InfiniPath PE-880)
+iPath   | QLE7240
+iPath   | QLE7280
+
+Note 1: OpenSM does not run on an IBM Galaxy (eHCA) as it does not expose
+QP0 and QP1. However, it does support it as a device on the subnet.
+
+Note 2: QoS firmware and Mellanox devices
+
+HCAs: QoS supported by ConnectX. QoS-enabled FW release is 2_5_000 and
+later.
+
+Switches: QoS supported by InfiniScale III
+Any InfiniScale III FW that is supported by OpenSM supports QoS.
diff --git a/doc/performance-manager-HOWTO.txt b/doc/performance-manager-HOWTO.txt
new file mode 100644
index 0000000..0b35e5f
--- /dev/null
+++ b/doc/performance-manager-HOWTO.txt
@@ -0,0 +1,153 @@
+OpenSM Performance manager HOWTO
+================================
+
+Introduction
+============
+
+OpenSM now includes a performance manager which collects Port counters from
+the subnet and stores them internally in OpenSM.
+
+Some of the features of the performance manager are:
+
+	1) Collect port data and error counters per v1.2 spec and store in
+	   64bit internal counts.
+	2) Automatic reset of counters when they reach approximatly 3/4 full.
+	   (While not guarenteeing that counts will not be missed this does
+	   keep counts incrementing as best as possible given the current
+	   hardware limitations.)
+	3) Basic warnings in the OpenSM log on "critical" errors like symbol
+	   errors.
+	4) Automatically detects "outside" resets of counters and adjusts to
+	   continue collecting data.
+	5) Can be run when OpenSM is in standby or inactive states.
+
+Known issues are:
+
+	1) Data counters will be lost on high data rate links.  Sweeping the
+	   fabric fast enough for a DDR link is not practical.
+	2) Default partition support only.
+
+
+Setup and Usage
+===============
+
+Using the Performance Manager consists of 3 steps:
+
+	1) compiling in support for the perfmgr (Optionally: the console
+	   socket as well)
+	2) enabling the perfmgr and console in opensm.conf
+	3) retrieving data which has been collected.
+	   3a) using console to "dump data"
+	   3b) using a plugin module to store the data to your own
+	       "database"
+
+Step 1: Compile in support for the Performance Manager
+------------------------------------------------------
+
+Because of the performance manager's experimental status, it is not enabled at
+compile time by default.  (This will hopefully soon change as more people use
+it and confirm that it does not break things...  ;-)  The configure option is
+"--enable-perf-mgr".
+
+At this time it is really best to enable the console socket option as well.
+OpenSM can be run in an "interactive" mode.  But with the console socket option
+turned on one can also make a connection to a running OpenSM.  The console
+option is "--enable-console-socket".  This option requires the use of
+tcp_wrappers to ensure security.  Please be aware of your configuration for
+tcp_wrappers as the commands presented in the console can affect the operation
+of your subnet.
+
+The following configure line includes turning on the performance manager as
+well as the console:
+
+	./configure --enable-perf-mgr --enable-console-socket
+
+
+Step 2: Enable the perfmgr and console in opensm.conf
+-----------------------------------------------------
+
+Turning the Perfmorance Manager on is pretty easy, set the following options in
+the opensm.conf config file.  (Default location is
+/usr/local/etc/opensm/opensm.conf)
+
+	# Turn it all on.
+	perfmgr TRUE
+
+	# sweep time in seconds
+	perfmgr_sweep_time_s 180
+
+	# Dump file to dump the events to
+	event_db_dump_file /var/log/opensm_port_counters.log
+
+Also enable the console socket and configure the port for it to listen to if
+desired.
+
+	# console [off|local|socket]
+	console socket
+
+	# Telnet port for console (default 10000)
+	console_port 10000
+
+As noted above you also need to set up tcp_wrappers to prevent unauthorized
+users from connecting to the console.[*]
+
+	[*] As an alternate you can use the loopback mode but I noticed when
+	writing this (OpenSM v3.1.10; OFED 1.3) that there are some bugs in
+	specifying the loopback mode in the opensm.conf file.  Look for this to
+	be fixed in newer versions.
+
+	[**] Also you could use "local" but this is only useful if you run
+	OpenSM in the foreground of a terminal.  As OpenSM is usually started
+	as a daemon I left this out as an option.
+
+Step 3: retrieve data which has been collected
+----------------------------------------------
+
+Step 3a: Using console dump function
+------------------------------------
+
+The console command "perfmgr dump_counters" will dump counters to the file
+specified in the opensm.conf file.  In the example above
+"/var/log/opensm_port_counters.log"
+
+Example output is below:
+
+<snip>
+"SW1 wopr ISR9024D (MLX4 FW)" 0x8f10400411f56 port 1 (Since Mon May 12 13:27:14 2008)
+     symbol_err_cnt       : 0
+     link_err_recover     : 0
+     link_downed          : 0
+     rcv_err              : 0
+     rcv_rem_phys_err     : 0
+     rcv_switch_relay_err : 2
+     xmit_discards        : 0
+     xmit_constraint_err  : 0
+     rcv_constraint_err   : 0
+     link_integrity_err   : 0
+     buf_overrun_err      : 0
+     vl15_dropped         : 0
+     xmit_data            : 470435
+     rcv_data             : 405956
+     xmit_pkts            : 8954
+     rcv_pkts             : 6900
+     unicast_xmit_pkts    : 0
+     unicast_rcv_pkts     : 0
+     multicast_xmit_pkts  : 0
+     multicast_rcv_pkts   : 0
+</snip>
+
+
+Step 3b: Using a plugin module
+------------------------------
+
+If you want a more automated method of retrieving the data OpenSM provides a
+plugin interface to extend OpenSM.  The header file is osm_event_plugin.h.
+The functions you register with this interface will be called when data is
+collected.  You can then use that data as appropriate.
+
+An example plugin can be configured at compile time using the
+"--enable-default-event-plugin" option on the configure line.  This plugin is
+very simple.  It logs "events" recieved from the performance manager to a log
+file.  I don't recomend using this directly but rather use it as a templat to
+create your own plugin.
+
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..1df1abc
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,33 @@
+
+SUBDIRS = .
+
+nobase_pkginclude_HEADERS = iba/ib_types.h iba/ib_cm_types.h
+
+EXTRA_DIST = \
+	$(srcdir)/iba/ib_types.h \
+	$(srcdir)/iba/ib_cm_types.h \
+	$(srcdir)/vendor/osm_vendor_mlx_transport_anafa.h \
+	$(srcdir)/vendor/osm_vendor_mlx.h \
+	$(srcdir)/vendor/osm_vendor_mlx_sender.h \
+	$(srcdir)/vendor/osm_vendor_ibumad.h \
+	$(srcdir)/vendor/osm_vendor_mlx_defs.h \
+	$(srcdir)/vendor/osm_vendor_mtl_transaction_mgr.h \
+	$(srcdir)/vendor/osm_vendor_mlx_sar.h \
+	$(srcdir)/vendor/osm_vendor_mlx_dispatcher.h \
+	$(srcdir)/vendor/osm_vendor_umadt.h \
+	$(srcdir)/vendor/osm_vendor_mlx_svc.h \
+	$(srcdir)/vendor/osm_vendor_mlx_hca.h \
+	$(srcdir)/vendor/osm_vendor_mlx_rmpp_ctx.h \
+	$(srcdir)/vendor/osm_vendor_mlx_transport.h \
+	$(srcdir)/vendor/osm_vendor_mlx_inout.h \
+	$(srcdir)/vendor/osm_vendor_mtl_hca_guid.h \
+	$(srcdir)/vendor/osm_vendor_test.h \
+	$(srcdir)/vendor/osm_vendor_ts.h \
+	$(srcdir)/vendor/osm_vendor_mlx_txn.h \
+	$(srcdir)/vendor/osm_vendor_al.h \
+	$(srcdir)/vendor/osm_vendor_mtl.h \
+	$(srcdir)/vendor/osm_ts_useraccess.h \
+	$(srcdir)/vendor/osm_umadt.h \
+	$(srcdir)/vendor/osm_mtl_bind.h
+
+pkgincludedir = $(includedir)/infiniband
diff --git a/include/Makefile.in b/include/Makefile.in
new file mode 100644
index 0000000..20cfc1d
--- /dev/null
+++ b/include/Makefile.in
@@ -0,0 +1,587 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = include
+DIST_COMMON = $(nobase_pkginclude_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/config.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h $(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(pkgincludedir)"
+nobase_pkgincludeHEADERS_INSTALL = $(install_sh_DATA)
+HEADERS = $(nobase_pkginclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/infiniband
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+nobase_pkginclude_HEADERS = iba/ib_types.h iba/ib_cm_types.h
+EXTRA_DIST = \
+	$(srcdir)/iba/ib_types.h \
+	$(srcdir)/iba/ib_cm_types.h \
+	$(srcdir)/vendor/osm_vendor_mlx_transport_anafa.h \
+	$(srcdir)/vendor/osm_vendor_mlx.h \
+	$(srcdir)/vendor/osm_vendor_mlx_sender.h \
+	$(srcdir)/vendor/osm_vendor_ibumad.h \
+	$(srcdir)/vendor/osm_vendor_mlx_defs.h \
+	$(srcdir)/vendor/osm_vendor_mtl_transaction_mgr.h \
+	$(srcdir)/vendor/osm_vendor_mlx_sar.h \
+	$(srcdir)/vendor/osm_vendor_mlx_dispatcher.h \
+	$(srcdir)/vendor/osm_vendor_umadt.h \
+	$(srcdir)/vendor/osm_vendor_mlx_svc.h \
+	$(srcdir)/vendor/osm_vendor_mlx_hca.h \
+	$(srcdir)/vendor/osm_vendor_mlx_rmpp_ctx.h \
+	$(srcdir)/vendor/osm_vendor_mlx_transport.h \
+	$(srcdir)/vendor/osm_vendor_mlx_inout.h \
+	$(srcdir)/vendor/osm_vendor_mtl_hca_guid.h \
+	$(srcdir)/vendor/osm_vendor_test.h \
+	$(srcdir)/vendor/osm_vendor_ts.h \
+	$(srcdir)/vendor/osm_vendor_mlx_txn.h \
+	$(srcdir)/vendor/osm_vendor_al.h \
+	$(srcdir)/vendor/osm_vendor_mtl.h \
+	$(srcdir)/vendor/osm_ts_useraccess.h \
+	$(srcdir)/vendor/osm_umadt.h \
+	$(srcdir)/vendor/osm_mtl_bind.h
+
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  include/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status include/config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-nobase_pkgincludeHEADERS: $(nobase_pkginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)"
+	@$(am__vpath_adj_setup) \
+	list='$(nobase_pkginclude_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  $(am__vpath_adj) \
+	  echo " $(nobase_pkgincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+	  $(nobase_pkgincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgincludedir)/$$f"; \
+	done
+
+uninstall-nobase_pkgincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@$(am__vpath_adj_setup) \
+	list='$(nobase_pkginclude_HEADERS)'; for p in $$list; do \
+	  $(am__vpath_adj) \
+	  echo " rm -f '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(pkgincludedir)/$$f"; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(HEADERS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(pkgincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-nobase_pkgincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-nobase_pkgincludeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic clean-libtool \
+	ctags ctags-recursive distclean distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man \
+	install-nobase_pkgincludeHEADERS install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-nobase_pkgincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/complib/cl_atomic.h b/include/complib/cl_atomic.h
new file mode 100644
index 0000000..92620ee
--- /dev/null
+++ b/include/complib/cl_atomic.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of atomic manipulation functions.
+ */
+
+#ifndef _CL_ATOMIC_H_
+#define _CL_ATOMIC_H_
+
+#include <complib/cl_atomic_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Atomic Operations
+* NAME
+*	Atomic Operations
+*
+* DESCRIPTION
+*	The Atomic Operations functions allow callers to operate on
+*	32-bit signed integers in an atomic fashion.
+*********/
+/****f* Component Library: Atomic Operations/cl_atomic_inc
+* NAME
+*	cl_atomic_inc
+*
+* DESCRIPTION
+*	The cl_atomic_inc function atomically increments a 32-bit signed
+*	integer and returns the incremented value.
+*
+* SYNOPSIS
+*/
+int32_t cl_atomic_inc(IN atomic32_t * const p_value);
+/*
+* PARAMETERS
+*	p_value
+*		[in] Pointer to a 32-bit integer to increment.
+*
+* RETURN VALUE
+*	Returns the incremented value pointed to by p_value.
+*
+* NOTES
+*	The provided value is incremented and its value returned in one atomic
+*	operation.
+*
+*	cl_atomic_inc maintains data consistency without requiring additional
+*	synchronization mechanisms in multi-threaded environments.
+*
+* SEE ALSO
+*	Atomic Operations, cl_atomic_dec, cl_atomic_add, cl_atomic_sub,
+*	cl_atomic_xchg, cl_atomic_comp_xchg
+*********/
+
+/****f* Component Library: Atomic Operations/cl_atomic_dec
+* NAME
+*	cl_atomic_dec
+*
+* DESCRIPTION
+*	The cl_atomic_dec function atomically decrements a 32-bit signed
+*	integer and returns the decremented value.
+*
+* SYNOPSIS
+*/
+int32_t cl_atomic_dec(IN atomic32_t * const p_value);
+/*
+* PARAMETERS
+*	p_value
+*		[in] Pointer to a 32-bit integer to decrement.
+*
+* RETURN VALUE
+*	Returns the decremented value pointed to by p_value.
+*
+* NOTES
+*	The provided value is decremented and its value returned in one atomic
+*	operation.
+*
+*	cl_atomic_dec maintains data consistency without requiring additional
+*	synchronization mechanisms in multi-threaded environments.
+*
+* SEE ALSO
+*	Atomic Operations, cl_atomic_inc, cl_atomic_add, cl_atomic_sub,
+*	cl_atomic_xchg, cl_atomic_comp_xchg
+*********/
+
+/****f* Component Library: Atomic Operations/cl_atomic_add
+* NAME
+*	cl_atomic_add
+*
+* DESCRIPTION
+*	The cl_atomic_add function atomically adds a value to a
+*	32-bit signed integer and returns the resulting value.
+*
+* SYNOPSIS
+*/
+int32_t
+cl_atomic_add(IN atomic32_t * const p_value, IN const int32_t increment);
+/*
+* PARAMETERS
+*	p_value
+*		[in] Pointer to a 32-bit integer that will be added to.
+*
+*	increment
+*		[in] Value by which to increment the integer pointed to by p_value.
+*
+* RETURN VALUE
+*	Returns the value pointed to by p_value after the addition.
+*
+* NOTES
+*	The provided increment is added to the value and the result returned in
+*	one atomic operation.
+*
+*	cl_atomic_add maintains data consistency without requiring additional
+*	synchronization mechanisms in multi-threaded environments.
+*
+* SEE ALSO
+*	Atomic Operations, cl_atomic_inc, cl_atomic_dec, cl_atomic_sub,
+*	cl_atomic_xchg, cl_atomic_comp_xchg
+*********/
+
+/****f* Component Library: Atomic Operations/cl_atomic_sub
+* NAME
+*	cl_atomic_sub
+*
+* DESCRIPTION
+*	The cl_atomic_sub function atomically subtracts a value from a
+*	32-bit signed integer and returns the resulting value.
+*
+* SYNOPSIS
+*/
+int32_t
+cl_atomic_sub(IN atomic32_t * const p_value, IN const int32_t decrement);
+/*
+* PARAMETERS
+*	p_value
+*		[in] Pointer to a 32-bit integer that will be subtracted from.
+*
+*	decrement
+*		[in] Value by which to decrement the integer pointed to by p_value.
+*
+* RETURN VALUE
+*	Returns the value pointed to by p_value after the subtraction.
+*
+* NOTES
+*	The provided decrement is subtracted from the value and the result
+*	returned in one atomic operation.
+*
+*	cl_atomic_sub maintains data consistency without requiring additional
+*	synchronization mechanisms in multi-threaded environments.
+*
+* SEE ALSO
+*	Atomic Operations, cl_atomic_inc, cl_atomic_dec, cl_atomic_add,
+*	cl_atomic_xchg, cl_atomic_comp_xchg
+*********/
+
+END_C_DECLS
+#endif				/* _CL_ATOMIC_H_ */
diff --git a/include/complib/cl_atomic_osd.h b/include/complib/cl_atomic_osd.h
new file mode 100644
index 0000000..ac14f8a
--- /dev/null
+++ b/include/complib/cl_atomic_osd.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation specific header files for atomic operations.
+ */
+
+#ifndef _CL_ATOMIC_OSD_H_
+#define _CL_ATOMIC_OSD_H_
+
+#include <complib/cl_types.h>
+#include <complib/cl_spinlock.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 extern cl_spinlock_t cl_atomic_spinlock;
+
+static inline int32_t cl_atomic_inc(IN atomic32_t * const p_value)
+{
+	int32_t new_val;
+
+	cl_spinlock_acquire(&cl_atomic_spinlock);
+	new_val = *p_value + 1;
+	*p_value = new_val;
+	cl_spinlock_release(&cl_atomic_spinlock);
+	return (new_val);
+}
+
+static inline int32_t cl_atomic_dec(IN atomic32_t * const p_value)
+{
+	int32_t new_val;
+
+	cl_spinlock_acquire(&cl_atomic_spinlock);
+	new_val = *p_value - 1;
+	*p_value = new_val;
+	cl_spinlock_release(&cl_atomic_spinlock);
+	return (new_val);
+}
+
+static inline int32_t
+cl_atomic_add(IN atomic32_t * const p_value, IN const int32_t increment)
+{
+	int32_t new_val;
+
+	cl_spinlock_acquire(&cl_atomic_spinlock);
+	new_val = *p_value + increment;
+	*p_value = new_val;
+	cl_spinlock_release(&cl_atomic_spinlock);
+	return (new_val);
+}
+
+static inline int32_t
+cl_atomic_sub(IN atomic32_t * const p_value, IN const int32_t decrement)
+{
+	int32_t new_val;
+
+	cl_spinlock_acquire(&cl_atomic_spinlock);
+	new_val = *p_value + decrement;
+	*p_value = new_val;
+	cl_spinlock_release(&cl_atomic_spinlock);
+	return (new_val);
+}
+
+END_C_DECLS
+#endif				/* _CL_ATOMIC_OSD_H_ */
diff --git a/include/complib/cl_byteswap.h b/include/complib/cl_byteswap.h
new file mode 100644
index 0000000..bef24b0
--- /dev/null
+++ b/include/complib/cl_byteswap.h
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	provides byteswapping utilities. Basic functions are obtained from
+ *  platform specific implementations from byteswap_osd.h.
+ */
+
+#ifndef _CL_BYTESWAP_H_
+#define _CL_BYTESWAP_H_
+
+#include <string.h>
+#include <complib/cl_byteswap_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Byte Swapping
+* NAME
+*	Byte Swapping
+*
+* DESCRIPTION
+*	The byte swapping functions and macros allow swapping bytes from network
+*	byte order to host byte order.
+*
+*	All data transmitted between systems should be in network byte order.
+*	In order to utilize such data, it must be converted to host byte order
+*	before use.
+*
+* SEE ALSO
+*	Functions:
+*		cl_ntoh16, cl_hton16, cl_ntoh32, cl_hton32, cl_ntoh64, cl_hton64,
+*		cl_ntoh
+*
+*	Macros:
+*		CL_NTOH16, CL_HTON16, CL_NTOH32, CL_HTON32, CL_NTOH64, CL_HTON64
+*********/
+/*
+ * The byteswap_osd.h provides the following macros.
+ *		__LITTLE_ENDIAN
+ *		__BIG_ENDIAN
+ *		__BYTE_ORDER
+ *
+ * If the platform provides byte swapping functions, byteswap_osd.h also
+ * provides the following macros.
+ *		ntoh16, hton16
+ *		ntoh32, hton32
+ *		ntoh64, hton64
+ */
+#ifndef __BYTE_ORDER
+#error "__BYTE_ORDER macro undefined. Missing in endian.h?"
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define CPU_LE		1
+#define CPU_BE		0
+#else
+#define CPU_LE		0
+#define CPU_BE		1
+#endif
+/****d* Component Library: Byte Swapping/CL_NTOH16
+* NAME
+*	CL_NTOH16
+*
+* DESCRIPTION
+*	The CL_NTOH16 macro converts a 16-bit value from network byte order to
+*	host byte order.  The CL_NTOH16 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_NTOH16 is less efficient
+*	than the cl_ntoh16 function.
+*
+* SYNOPSIS
+*	CL_NTOH16( val );
+*
+* PARAMETERS
+*	val
+*		[in] 16-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*	Value of val converted to host byte order.
+*
+* NOTES
+*	This macro is analogous to CL_HTON16.
+*
+* SEE ALSO
+*	Byte Swapping, CL_HTON16, CL_NTOH32, CL_NTOH64,
+*	cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON16
+* NAME
+*	CL_HTON16
+*
+* DESCRIPTION
+*	The CL_HTON16 macro converts a 16-bit value from host byte order to
+*	network byte order.  The CL_HTON16 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_HTON16 is less efficient
+*	than the cl_hton16 function.
+*
+* SYNOPSIS
+*	CL_HTON16( val );
+*
+* PARAMETERS
+*	val
+*		[in] 16-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This macro is analogous to CL_NTOH16.
+*
+* SEE ALSO
+*	Byte Swapping, CL_NTOH16, CL_HTON32, CL_HTON64,
+*	cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+#define CL_NTOH16( x )		(uint16_t)(		\
+			(((uint16_t)(x) & 0x00FF) << 8) |		\
+			(((uint16_t)(x) & 0xFF00) >> 8) )
+#else
+#define CL_NTOH16( x )	(x)
+#endif
+#define CL_HTON16				CL_NTOH16
+/****f* Component Library: Byte Swapping/cl_ntoh16
+* NAME
+*	cl_ntoh16
+*
+* DESCRIPTION
+*	The cl_ntoh16 function converts a 16-bit value from network byte order to
+*	host byte order.
+*
+* SYNOPSIS
+*	uint16_t
+*	cl_ntoh16(
+*		IN	const uint16_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*	Value of val converted to host byte order.
+*
+* NOTES
+*	This function is analogous to cl_hton16.
+*
+* SEE ALSO
+*	Byte Swapping, cl_hton16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton16
+* NAME
+*	cl_hton16
+*
+* DESCRIPTION
+*	The cl_hton16 function converts a 16-bit value from host byte order to
+*	network byte order.
+*
+* SYNOPSIS
+*	uint16_t
+*	cl_hton16(
+*		IN	const uint16_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This function is analogous to cl_ntoh16.
+*
+* SEE ALSO
+*	Byte Swapping, cl_ntoh16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#ifndef cl_ntoh16
+#define cl_ntoh16	CL_NTOH16
+#define cl_hton16	CL_HTON16
+#endif
+/****d* Component Library: Byte Swapping/CL_NTOH32
+* NAME
+*	CL_NTOH32
+*
+* DESCRIPTION
+*	The CL_NTOH32 macro converts a 32-bit value from network byte order to
+*	host byte order.  The CL_NTOH32 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_NTOH32 is less efficient
+*	than the cl_ntoh32 function.
+*
+* SYNOPSIS
+*	CL_NTOH32( val );
+*
+* PARAMETERS
+*	val
+*		[in] 32-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*	Value of val converted to host byte order.
+*
+* NOTES
+*	This macro is analogous to CL_HTON32.
+*
+* SEE ALSO
+*	Byte Swapping, CL_HTON32, CL_NTOH16, CL_NTOH64,
+*	cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON32
+* NAME
+*	CL_HTON32
+*
+* DESCRIPTION
+*	The CL_HTON32 macro converts a 32-bit value from host byte order to
+*	network byte order.  The CL_HTON32 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_HTON32 is less efficient
+*	than the cl_hton32 function.
+*
+* SYNOPSIS
+*	CL_HTON32( val );
+*
+* PARAMETERS
+*	val
+*		[in] 32-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This macro is analogous to CL_NTOH32.
+*
+* SEE ALSO
+*	Byte Swapping, CL_NTOH32, CL_HTON16, CL_HTON64,
+*	cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+#define CL_NTOH32( x )		(uint32_t)(			\
+			(((uint32_t)(x) & 0x000000FF) << 24) |	\
+			(((uint32_t)(x) & 0x0000FF00) << 8) |	\
+			(((uint32_t)(x) & 0x00FF0000) >> 8) |	\
+			(((uint32_t)(x) & 0xFF000000) >> 24) )
+#else
+#define CL_NTOH32( x )		(x)
+#endif
+#define CL_HTON32	CL_NTOH32
+/****f* Component Library: Byte Swapping/cl_ntoh32
+* NAME
+*	cl_ntoh32
+*
+* DESCRIPTION
+*	The cl_ntoh32 function converts a 32-bit value from network byte order to
+*	host byte order.
+*
+* SYNOPSIS
+*	uint32_t
+*	cl_ntoh32(
+*		IN	const uint32_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*	Value of val converted in host byte order.
+*
+* NOTES
+*	This function is analogous to cl_hton32.
+*
+* SEE ALSO
+*	Byte Swapping, cl_hton32, cl_ntoh16, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton32
+* NAME
+*	cl_hton32
+*
+* DESCRIPTION
+*	The cl_hton32 function converts a 32-bit value from host byte order to
+*	network byte order.
+*
+* SYNOPSIS
+*	uint32_t
+*	cl_hton32(
+*		IN	const uint32_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This function is analogous to cl_ntoh32.
+*
+* SEE ALSO
+*	Byte Swapping, cl_ntoh32, cl_hton16, cl_hton64, cl_ntoh
+*********/
+#ifndef cl_ntoh32
+#define cl_ntoh32	CL_NTOH32
+#define cl_hton32	CL_HTON32
+#endif
+/****d* Component Library: Byte Swapping/CL_NTOH64
+* NAME
+*	CL_NTOH64
+*
+* DESCRIPTION
+*	The CL_NTOH64 macro converts a 64-bit value from network byte order to
+*	host byte order.  The CL_NTOH64 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_NTOH64 is less efficient
+*	than the cl_ntoh64 function.
+*
+* SYNOPSIS
+*	CL_NTOH64( val );
+*
+* PARAMETERS
+*	val
+*		[in] 64-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*	Value of val converted to host byte order.
+*
+* NOTES
+*	This macro is analogous to CL_HTON64.
+*
+* SEE ALSO
+*	Byte Swapping, CL_HTON64, CL_NTOH16, CL_NTOH32,
+*	cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON64
+* NAME
+*	CL_HTON64
+*
+* DESCRIPTION
+*	The CL_HTON64 macro converts a 64-bit value from host byte order to
+*	network byte order.  The CL_HTON64 macro will cause constant values to be
+*	swapped by the pre-processor.  For variables, CL_HTON64 is less efficient
+*	than the cl_hton64 function.
+*
+* SYNOPSIS
+*	CL_HTON64( val );
+*
+* PARAMETERS
+*	val
+*		[in] 64-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This macro is analogous to CL_NTOH64.
+*
+* SEE ALSO
+*	Byte Swapping, CL_NTOH64, CL_HTON16, CL_HTON32,
+*	cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+#define CL_NTOH64( x )		(uint64_t)(					\
+			(((uint64_t)(x) & 0x00000000000000FFULL) << 56) |	\
+			(((uint64_t)(x) & 0x000000000000FF00ULL) << 40) |	\
+			(((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) |	\
+			(((uint64_t)(x) & 0x00000000FF000000ULL) << 8 ) |	\
+			(((uint64_t)(x) & 0x000000FF00000000ULL) >> 8 ) |	\
+			(((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) |	\
+			(((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) |	\
+			(((uint64_t)(x) & 0xFF00000000000000ULL) >> 56) )
+#else
+#define CL_NTOH64( x )		(x)
+#endif
+#define CL_HTON64				CL_NTOH64
+/****f* Component Library: Byte Swapping/cl_ntoh64
+* NAME
+*	cl_ntoh64
+*
+* DESCRIPTION
+*	The cl_ntoh64 function converts a 64-bit value from network byte order to
+*	host byte order.
+*
+* SYNOPSIS
+*	uint64_t
+*	cl_ntoh64(
+*		IN	const uint64_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*	Value of val converted in host byte order.
+*
+* NOTES
+*	This function is analogous to cl_hton64.
+*
+* SEE ALSO
+*	Byte Swapping, cl_hton64, cl_ntoh16, cl_ntoh32, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton64
+* NAME
+*	cl_hton64
+*
+* DESCRIPTION
+*	The cl_hton64 function converts a 64-bit value from host byte order to
+*	network byte order.
+*
+* SYNOPSIS
+*	uint64_t
+*	cl_hton64(
+*		IN	const uint64_t	val );
+*
+* PARAMETERS
+*	val
+*		[in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*	Value of val converted to network byte order.
+*
+* NOTES
+*	This function is analogous to cl_ntoh64.
+*
+* SEE ALSO
+*	Byte Swapping, cl_ntoh64, cl_hton16, cl_hton32, cl_ntoh
+*********/
+#ifndef cl_ntoh64
+#define cl_ntoh64	CL_NTOH64
+#define cl_hton64	CL_HTON64
+#endif
+/****f* Component Library: Byte Swapping/cl_ntoh
+* NAME
+*	cl_ntoh
+*
+* DESCRIPTION
+*	The cl_ntoh function converts a value from network byte order to
+*	host byte order.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_ntoh(OUT char *const p_dest,
+	IN const char *const p_src, IN const uint8_t size)
+{
+#if CPU_LE
+	uint8_t i;
+	char temp;
+
+	if (p_src == p_dest) {
+		/* Swap in place if source and destination are the same. */
+		for (i = 0; i < size / 2; i++) {
+			temp = p_dest[i];
+			p_dest[i] = p_src[size - 1 - i];
+			p_dest[size - 1 - i] = temp;
+		}
+	} else {
+		for (i = 0; i < size; i++)
+			p_dest[i] = p_src[size - 1 - i];
+	}
+#else
+	/*
+	 * If the source and destination are not the same, copy the source to
+	 * the destination.
+	 */
+	if (p_src != p_dest)
+		memcpy(p_dest, p_src, size);
+#endif
+}
+
+/*
+* PARAMETERS
+*	p_dest
+*		[in] Pointer to a byte array to contain the converted value of p_src.
+*
+*	p_src
+*		[in] Pointer to a byte array to be converted from network byte
+*		ordering.
+*
+*	size
+*		[in] Number of bytes to swap.p_dest
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_ntoh can perform in place swapping if both p_src and p_dest point to
+*	the same buffer.
+*
+* SEE ALSO
+*	Byte Swapping, cl_ntoh16, cl_ntoh32, cl_ntoh64
+*********/
+
+END_C_DECLS
+#endif				/* _CL_BYTESWAP_H_ */
diff --git a/include/complib/cl_byteswap_osd.h b/include/complib/cl_byteswap_osd.h
new file mode 100644
index 0000000..72ff40e
--- /dev/null
+++ b/include/complib/cl_byteswap_osd.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Provides common macros for dealing with byte swapping issues.
+ */
+
+#ifndef _CL_BYTESWAP_OSD_H_
+#define _CL_BYTESWAP_OSD_H_
+
+/*
+ * This provides defines __LITTLE_ENDIAN, __BIG_ENDIAN and __BYTE_ORDER
+ */
+#include <endian.h>
+#include <byteswap.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 __BYTE_ORDER == __LITTLE_ENDIAN
+#define cl_ntoh16(x)	bswap_16(x)
+#define cl_hton16(x)	bswap_16(x)
+#define cl_ntoh32(x)	bswap_32(x)
+#define cl_hton32(x)	bswap_32(x)
+#define cl_ntoh64(x)	(uint64_t)bswap_64(x)
+#define cl_hton64(x)	(uint64_t)bswap_64(x)
+#else				/* Big Endian */
+#define cl_ntoh16(x)	(x)
+#define cl_hton16(x)	(x)
+#define cl_ntoh32(x)	(x)
+#define cl_hton32(x)	(x)
+#define cl_ntoh64(x)	(x)
+#define cl_hton64(x)	(x)
+#endif
+END_C_DECLS
+#endif				/* _CL_BYTESWAP_OSD_H_ */
diff --git a/include/complib/cl_comppool.h b/include/complib/cl_comppool.h
new file mode 100644
index 0000000..503ae18
--- /dev/null
+++ b/include/complib/cl_comppool.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of the composite pool.
+ *	The composite pool managers a pool of composite objects.  A composite object is an object
+ *	that is made of multiple sub objects.
+ *	The pool can grow to meet demand, limited only by system memory.
+ */
+
+#ifndef _CL_COMP_POOL_H_
+#define _CL_COMP_POOL_H_
+
+#include <complib/cl_qcomppool.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/Composite Pool
+* NAME
+*	Composite Pool
+*
+* DESCRIPTION
+*	The Composite Pool provides a self-contained and self-sustaining pool of
+*	user defined composite objects.
+*
+*	A composite object is an object that is composed of one or more
+*	sub-objects, each of which needs to be treated separately for
+*	initialization. Objects can be retrieved from the pool as long as there
+*	is memory in the system.
+*
+*	To aid in object oriented design, the composite pool provides the user
+*	the ability to specify callbacks that are invoked for each object for
+*	construction, initialization, and destruction. Constructor and destructor
+*	callback functions may not fail.
+*
+*	A composite pool does not return memory to the system as the user returns
+*	objects to the pool. The only method of returning memory to the system is
+*	to destroy the pool.
+*
+*	The composite pool functions operates on a cl_cpool_t structure which
+*	should be treated as opaque and should be manipulated only through the
+*	provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_cpool_t
+*
+*	Callbacks:
+*		cl_pfn_cpool_init_t, cl_pfn_cpool_dtor_t
+*
+*	Initialization/Destruction:
+*		cl_cpool_construct, cl_cpool_init, cl_cpool_destroy
+*
+*	Manipulation:
+*		cl_cpool_get, cl_cpool_put, cl_cpool_grow
+*
+*	Attributes:
+*		cl_is_cpool_inited, cl_cpool_count
+*********/
+/****d* Component Library: Composite Pool/cl_pfn_cpool_init_t
+* NAME
+*	cl_pfn_cpool_init_t
+*
+* DESCRIPTION
+*	The cl_pfn_cpool_init_t function type defines the prototype for
+*	functions used as initializers for objects being allocated by a
+*	composite pool.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_cpool_init_t) (IN void **const p_comp_array,
+			    IN const uint32_t num_components, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object to initialize.
+*
+*	context
+*		[in] Context provided in a call to cl_cpool_init.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS to indicates that initialization of the object
+*	was successful and that initialization of further objects may continue.
+*
+*	Other cl_status_t values will be returned by cl_cpool_init
+*	and cl_cpool_grow.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_cpool_init function.
+*
+*	The initializer is invoked once per allocated object, allowing the user
+*	to chain components to form a composite object and perform any necessary
+*	initialization.  Returning a status other than CL_SUCCESS aborts a grow
+*	operation, initiated either through cl_cpool_init or cl_cpool_grow, and
+*	causes the initiating function to fail.  Any non-CL_SUCCESS status will
+*	be returned by the function that initiated the grow operation.
+*
+*	All memory for the requested number of components is pre-allocated.
+*
+*	When later performing a cl_cpool_get call, the return value is a pointer
+*	to the first component.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_init, cl_cpool_grow
+*********/
+
+/****d* Component Library: Composite Pool/cl_pfn_cpool_dtor_t
+* NAME
+*	cl_pfn_cpool_dtor_t
+*
+* DESCRIPTION
+*	The cl_pfn_cpool_dtor_t function type defines the prototype for
+*	functions used as destructor for objects being deallocated by a
+*	composite pool.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_cpool_dtor_t) (IN void *const p_object, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object to destruct.
+*
+*	context
+*		[in] Context provided in the call to cl_cpool_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_cpool_init function.
+*
+*	The destructor is invoked once per allocated object, allowing the user
+*	to perform any necessary cleanup. Users should not attempt to deallocate
+*	the memory for the composite object, as the composite pool manages
+*	object allocation and deallocation.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_init
+*********/
+
+/****s* Component Library: Composite Pool/cl_cpool_t
+* NAME
+*	cl_cpool_t
+*
+* DESCRIPTION
+*	Composite pool structure.
+*
+*	The cl_cpool_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_cpool {
+	cl_qcpool_t qcpool;
+	cl_pfn_cpool_init_t pfn_init;
+	cl_pfn_cpool_dtor_t pfn_dtor;
+	const void *context;
+} cl_cpool_t;
+/*
+* FIELDS
+*	qcpool
+*		Quick composite pool that manages all objects.
+*
+*	pfn_init
+*		Pointer to the user's initializer callback, used by the pool
+*		to translate the quick composite pool's initializer callback to
+*		a composite pool initializer callback.
+*
+*	pfn_dtor
+*		Pointer to the user's destructor callback, used by the pool
+*		to translate the quick composite pool's destructor callback to
+*		a composite pool destructor callback.
+*
+*	context
+*		User's provided context for callback functions, used by the pool
+*		to when invoking callbacks.
+*
+* SEE ALSO
+*	Composite Pool
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_construct
+* NAME
+*	cl_cpool_construct
+*
+* DESCRIPTION
+*	The cl_cpool_construct function constructs a composite pool.
+*
+* SYNOPSIS
+*/
+void cl_cpool_construct(IN cl_cpool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_pool_init, cl_cpool_destroy, cl_is_cpool_inited.
+*
+*	Calling cl_cpool_construct is a prerequisite to calling any other
+*	composite pool function except cl_cpool_init.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_init, cl_cpool_destroy, cl_is_cpool_inited
+*********/
+
+/****f* Component Library: Composite Pool/cl_is_cpool_inited
+* NAME
+*	cl_is_cpool_inited
+*
+* DESCRIPTION
+*	The cl_is_cpool_inited function returns whether a composite pool was
+*	successfully initialized.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_cpool_inited(IN const cl_cpool_t * const p_pool)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_pool);
+	return (cl_is_qcpool_inited(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure whose initialization state
+*		to check.
+*
+* RETURN VALUES
+*	TRUE if the composite pool was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a composite pool to determine if invoking
+*	member functions is appropriate.
+*
+* SEE ALSO
+*	Composite Pool
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_init
+* NAME
+*	cl_cpool_init
+*
+* DESCRIPTION
+*	The cl_cpool_init function initializes a composite pool for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_cpool_init(IN cl_cpool_t * const p_pool,
+	      IN const size_t min_size,
+	      IN const size_t max_size,
+	      IN const size_t grow_size,
+	      IN size_t * const component_sizes,
+	      IN const uint32_t num_components,
+	      IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL,
+	      IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL,
+	      IN const void *const context);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure to initialize.
+*
+*	min_size
+*		[in] Minimum number of objects that the pool should support. All
+*		necessary allocations to allow storing the minimum number of items
+*		are performed at initialization time, and all necessary callbacks
+*		successfully invoked.
+*
+*	max_size
+*		[in] Maximum number of objects to which the pool is allowed to grow.
+*		A value of zero specifies no maximum.
+*
+*	grow_size
+*		[in] Number of objects to allocate when incrementally growing the pool.
+*		A value of zero disables automatic growth.
+*
+*	component_sizes
+*		[in] Pointer to the first entry in an array of sizes describing,
+*		in order, the sizes of the components that make up a composite object.
+*
+*	num_components
+*		[in] Number of components that make up a composite object.
+*
+*	pfn_initializer
+*		[in] Initialization callback to invoke for every new object when
+*		growing the pool. This parameter may be NULL only if the objects
+*		stored in the composite pool consist of only one component.
+*		See the cl_pfn_cpool_init function type declaration for details
+*		about the callback function.
+*
+*	pfn_destructor
+*		[in] Destructor callback to invoke for every object before memory for
+*		that object is freed. This parameter is optional and may be NULL.
+*		See the cl_pfn_cpool_dtor function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the composite pool was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the
+*	composite pool.
+*
+*	CL_INVALID_SETTING if a NULL constructor was provided for composite objects
+*	consisting of more than one component.  Also returns CL_INVALID_SETTING if
+*	the maximum size is non-zero and less than the minimum size.
+*
+*	Other cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter.
+*
+* NOTES
+*	cl_cpool_init initializes, and if necessary, grows the pool to
+*	the capacity desired.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_construct, cl_cpool_destroy,
+*	cl_cpool_get, cl_cpool_put, cl_cpool_grow,
+*	cl_cpool_count, cl_pfn_cpool_ctor_t, cl_pfn_cpool_init_t,
+*	cl_pfn_cpool_dtor_t
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_destroy
+* NAME
+*	cl_cpool_destroy
+*
+* DESCRIPTION
+*	The cl_cpool_destroy function destroys a composite pool.
+*
+* SYNOPSIS
+*/
+static inline void cl_cpool_destroy(IN cl_cpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+
+	cl_qcpool_destroy(&p_pool->qcpool);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	All memory allocated for composite objects is freed. The destructor
+*	callback, if any, will be invoked for every allocated object. Further
+*	operations on the composite pool should not be attempted after
+*	cl_cpool_destroy is invoked.
+*
+*	This function should only be called after a call to cl_cpool_construct.
+*
+*	In a debug build, cl_cpool_destroy asserts that all objects are in
+*	the pool.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_construct, cl_cpool_init
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_count
+* NAME
+*	cl_cpool_count
+*
+* DESCRIPTION
+*	The cl_cpool_count function returns the number of available objects
+*	in a composite pool.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_cpool_count(IN cl_cpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_count(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure for which the number of
+*		available objects is requested.
+*
+* RETURN VALUE
+*	Returns the number of objects available in the specified
+*	composite pool.
+*
+* SEE ALSO
+*	Composite Pool
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_get
+* NAME
+*	cl_cpool_get
+*
+* DESCRIPTION
+*	The cl_cpool_get function retrieves an object from a
+*	composite pool.
+*
+* SYNOPSIS
+*/
+static inline void *cl_cpool_get(IN cl_cpool_t * const p_pool)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_pool);
+
+	p_pool_obj = (cl_pool_obj_t *) cl_qcpool_get(&p_pool->qcpool);
+	if (!p_pool_obj)
+		return (NULL);
+
+	CL_ASSERT(p_pool_obj->p_object);
+	return ((void *)p_pool_obj->p_object);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure from which to retrieve
+*		an object.
+*
+* RETURN VALUES
+*	Returns a pointer to the first component of a composite object.
+*
+*	Returns NULL if the pool is empty and can not be grown automatically.
+*
+* NOTES
+*	cl_cpool_get returns the object at the head of the pool. If the pool is
+*	empty, it is automatically grown to accommodate this request unless the
+*	grow_size parameter passed to the cl_cpool_init function was zero.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_get_tail, cl_cpool_put, cl_cpool_grow,
+*	cl_cpool_count
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_put
+* NAME
+*	cl_cpool_put
+*
+* DESCRIPTION
+*	The cl_cpool_put function returns an object to a composite pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_cpool_put(IN cl_cpool_t * const p_pool, IN void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_object);
+
+	/* Calculate the offset to the list object representing this object. */
+	p_pool_obj = (cl_pool_obj_t *)
+	    (((uint8_t *) p_object) - sizeof(cl_pool_obj_t));
+
+	/* good sanity check */
+	CL_ASSERT(p_pool_obj->p_object == p_object);
+
+	cl_qcpool_put(&p_pool->qcpool, &p_pool_obj->pool_item);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure to which to return
+*		an object.
+*
+*	p_object
+*		[in] Pointer to the first component of an object to return to the pool.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_cpool_put places the returned object at the head of the pool.
+*
+*	The object specified by the p_object parameter must have been
+*	retrieved from the pool by a previous call to cl_cpool_get.
+*
+* SEE ALSO
+*	Composite Pool, cl_cpool_put_tail, cl_cpool_get
+*********/
+
+/****f* Component Library: Composite Pool/cl_cpool_grow
+* NAME
+*	cl_cpool_grow
+*
+* DESCRIPTION
+*	The cl_cpool_grow function grows a composite pool by
+*	the specified number of objects.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_cpool_grow(IN cl_cpool_t * const p_pool, IN const uint32_t obj_count)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_grow(&p_pool->qcpool, obj_count));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_cpool_t structure whose capacity to grow.
+*
+*	obj_count
+*		[in] Number of objects by which to grow the pool.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the composite pool grew successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the
+*	composite pool.
+*
+*	cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter passed to the
+*	cl_cpool_init function.
+*
+* NOTES
+*	It is not necessary to call cl_cpool_grow if the pool is
+*	configured to grow automatically.
+*
+* SEE ALSO
+*	Composite Pool
+*********/
+
+END_C_DECLS
+#endif				/* _CL_COMP_POOL_H_ */
diff --git a/include/complib/cl_debug.h b/include/complib/cl_debug.h
new file mode 100644
index 0000000..05e9769
--- /dev/null
+++ b/include/complib/cl_debug.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of functions for reporting debug output.
+ */
+
+#ifndef _CL_DEBUG_H_
+#define _CL_DEBUG_H_
+
+#include <complib/cl_debug_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Debug Output
+* NAME
+*	Debug Output
+*
+* DESCRIPTION
+*	The debug output functions and macros send debug messages to the current
+*	debug target.
+*********/
+/****f* Component Library: Debug Output/cl_break
+* NAME
+*	cl_break
+*
+* DESCRIPTION
+*	The cl_break function halts execution.
+*
+* SYNOPSIS
+*	void
+*	cl_break();
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	In a release build, cl_break has no effect.
+*********/
+/****f* Component Library: Debug Output/cl_is_debug
+* NAME
+*	cl_is_debug
+*
+* DESCRIPTION
+*	The cl_is_debug function returns TRUE if the complib was compiled
+*  in debug mode, and FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t cl_is_debug(void);
+/*
+* PARAMETERS
+*    None
+*
+* RETURN VALUE
+*	  TRUE if compiled in debug version. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+#if defined( _DEBUG_ )
+#ifndef cl_dbg_out
+/****f* Component Library: Debug Output/cl_dbg_out
+* NAME
+*	cl_dbg_out
+*
+* DESCRIPTION
+*	The cl_dbg_out function sends a debug message to the debug target in
+*	debug builds only.
+*
+* SYNOPSIS
+*/
+void cl_dbg_out(IN const char *const debug_message, IN ...);
+/*
+* PARAMETERS
+*	debug_message
+*		[in] ANSI string formatted identically as for a call to the standard C
+*		function printf.
+*
+*	...
+*		[in] Extra parameters for string formatting, as defined for the
+*		standard C function printf.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	In a release build, cl_dbg_out has no effect.
+*
+*	The formatting of the debug_message string is the same as for printf
+*
+*	cl_dbg_out sends the debug message to the current debug target.
+*
+* SEE ALSO
+*	Debug Output, cl_msg_out
+*********/
+#endif
+#else
+static inline void cl_dbg_out(IN const char *const debug_message, IN ...)
+{
+	UNUSED_PARAM(debug_message);
+}
+#endif				/* defined( _DEBUG_ ) */
+
+#ifndef cl_msg_out
+/****f* Component Library: Debug Output/cl_msg_out
+* NAME
+*	cl_msg_out
+*
+* DESCRIPTION
+*	The cl_msg_out function sends a debug message to the message log target.
+*
+* SYNOPSIS
+*/
+void cl_msg_out(IN const char *const message, IN ...);
+/*
+* PARAMETERS
+*	message
+*		[in] ANSI string formatted identically as for a call to the standard C
+*		function printf.
+*
+*	...
+*		[in] Extra parameters for string formatting, as defined for the
+*		standard C function printf.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_msg_out is available in both debug and release builds.
+*
+*	The formatting of the message string is the same as for printf
+*
+*	cl_msg_out sends the message to the current message logging target.
+*
+* SEE ALSO
+*	Debug Output, cl_dbg_out
+*********/
+#endif
+
+/****d* Component Library: Debug Output/Debug Levels
+* NAME
+*	Debug Levels
+*
+* DESCRIPTION
+*	The debug output macros reserve the upper bit of the debug level to
+*	convey an error.
+*
+* SYNOPSIS
+*/
+#define	CL_DBG_DISABLE		0
+#define	CL_DBG_ERROR		0x80000000
+#define	CL_DBG_ALL			0xFFFFFFFF
+/*
+* VALUES
+*	CL_DBG_DISABLE
+*		Disable all debug output, including errors.
+*
+*	CL_DBG_ERROR
+*		Enable error debug output.
+*
+*	CL_DBG_ALL
+*		Enbale all debug output.
+*
+* NOTES
+*	Users can define custom debug levels using the lower 31 bits of their
+*	debug level to control non-error debug output.  Error messages are
+*	always displayed, regardless of the lower bit definition.
+*
+*	When specifying the debug output desired for non-error messages
+*	(the CHK_LVL parameter in the debug output macros), users must define
+*	all bits whose output they are interested in.
+*
+* SEE ALSO
+*	Debug Output, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE, CL_TRACE_EXIT
+*********/
+
+#if defined(_DEBUG_)
+
+/****d* Component Library: Debug Output/CL_PRINT
+* NAME
+*	CL_PRINT
+*
+* DESCRIPTION
+*	The CL_PRINT macro sends a string to the current debug target if
+*	the requested debug level matches the current debug level.
+*
+* SYNOPSIS
+*	CL_PRINT( DBG_LVL, CHK_LVL, STRING );
+*
+* PARAMETERS
+*	DBG_LVL
+*		[in] Debug level for the string to output
+*
+*	CHK_LVL
+*		[in] Current debug level against which to check DBG_LVL
+*
+*	STRING
+*		[in] String to send to the current debug target.  The string includes
+*		parentheses in order to allow additional parameters.
+*
+* RETURN VALUE
+*	This macro does not return a value.
+*
+* EXAMPLE
+*	#define	MY_FUNC_DBG_LVL	1
+*
+*	uint32_t	my_dbg_lvl = CL_DBG_ALL;
+*
+*	void
+*	my_func()
+*	{
+*		CL_PRINT( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") );
+*	}
+*
+* RESULT
+*	Hello world!
+*
+* NOTES
+*	The requested string is printed only if all bits set in DBG_LVL are also
+*	set in CHK_LVL unless the most significant bit is set (indicating an
+*	error), in which case the lower bits are ignored.  CHK_LVL may have
+*	additional bits set.
+*
+*	In multi-processor environments where the current processor can be
+*	determined, the zero-based number of the processor on which the output
+*	is generated is prepended to the output.
+*
+* SEE ALSO
+*	Debug Output, Debug Levels, CL_ENTER, CL_EXIT, CL_TRACE, CL_TRACE_EXIT
+*********/
+#define	CL_PRINT( DBG_LVL, CHK_LVL, STRING )								\
+	{																		\
+	if( DBG_LVL & CL_DBG_ERROR )											\
+		cl_dbg_out STRING;													\
+	else if( (DBG_LVL & CHK_LVL) == DBG_LVL )								\
+		cl_dbg_out STRING;													\
+	}
+
+/****d* Component Library: Debug Output/CL_ENTER
+* NAME
+*	CL_ENTER
+*
+* DESCRIPTION
+*	The CL_ENTER macro marks the entrance into a function by sending a
+*	string to the current debug target if the requested debug level matches
+*	the current debug level.
+*
+* SYNOPSIS
+*	CL_ENTER( DBG_LVL, CHK_LVL );
+*
+* PARAMETERS
+*	DBG_LVL
+*		[in] Debug level for the string to output
+*
+*	CHK_LVL
+*		[in] Current debug level against which to check DBG_LVL
+*
+* RETURN VALUE
+*	This macro does not return a value.
+*
+* EXAMPLE
+*	#define __MODULE__	"my_module"
+*	#define	MY_FUNC_DBG_LVL	1
+*
+*	uint32_t	my_dbg_lvl = CL_DBG_ALL;
+*
+*	void
+*	my_func()
+*	{
+*		CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*		CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*	}
+*
+* RESULT
+*	my_module:my_func() [
+*	my_module:my_func() ]
+*
+* NOTES
+*	The function entrance notification is printed only if all bits set
+*	in DBG_LVL are also set in CHK_LVL.  CHK_LVL may have additional bits set.
+*
+*	If the __MODULE__ preprocessor keyword is defined, that keyword will be
+*	prepended to the function name, separated with a colon.
+*
+*	In multi-processor environments where the current processor can be
+*	determined, the zero-based number of the processor on which the output
+*	is generated is prepended to the output.
+*
+* SEE ALSO
+*	Debug Output, Debug Levels, CL_PRINT, CL_EXIT, CL_TRACE, CL_TRACE_EXIT
+*********/
+#define CL_ENTER( DBG_LVL, CHK_LVL )										\
+	CL_CHK_STK;																\
+	CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_ENTER );
+
+/****d* Component Library: Debug Output/CL_EXIT
+* NAME
+*	CL_EXIT
+*
+* DESCRIPTION
+*	The CL_EXIT macro marks the exit from a function by sending a string
+*	to the current debug target if the requested debug level matches the
+*	current debug level.
+*
+* SYNOPSIS
+*	CL_EXIT( DBG_LVL, CHK_LVL );
+*
+* PARAMETERS
+*	DBG_LVL
+*		[in] Debug level for the string to output
+*
+*	CHK_LVL
+*		[in] Current debug level against which to check DBG_LVL
+*
+* RETURN VALUE
+*	This macro does not return a value.
+*
+* EXAMPLE
+*	#define __MODULE__	"my_module"
+*	#define	MY_FUNC_DBG_LVL	1
+*
+*	uint32_t	my_dbg_lvl = CL_DBG_ALL;
+*
+*	void
+*	my_func()
+*	{
+*		CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*		CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*	}
+*
+* RESULT
+*	my_module:my_func() [
+*	my_module:my_func() ]
+*
+* NOTES
+*	The exit notification is printed only if all bits set in DBG_LVL are also
+*	set in CHK_LVL.  CHK_LVL may have additional bits set.
+*
+*	The CL_EXIT macro must only be used after the CL_ENTRY macro as it
+*	depends on that macro's implementation.
+*
+*	If the __MODULE__ preprocessor keyword is defined, that keyword will be
+*	prepended to the function name, separated with a colon.
+*
+*	In multi-processor environments where the current processor can be
+*	determined, the zero-based number of the processor on which the output
+*	is generated is prepended to the output.
+*
+* SEE ALSO
+*	Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_TRACE, CL_TRACE_EXIT
+*********/
+#define CL_EXIT( DBG_LVL, CHK_LVL )											\
+	CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_EXIT );
+
+/****d* Component Library: Debug Output/CL_TRACE
+* NAME
+*	CL_TRACE
+*
+* DESCRIPTION
+*	The CL_TRACE macro sends a string to the current debug target if
+*	the requested debug level matches the current debug level.  The
+*	output is prepended with the function name and, depending on the
+*	debug level requested, an indication of the severity of the message.
+*
+* SYNOPSIS
+*	CL_TRACE( DBG_LVL, CHK_LVL, STRING );
+*
+* PARAMETERS
+*	DBG_LVL
+*		[in] Debug level for the string to output
+*
+*	CHK_LVL
+*		[in] Current debug level against which to check DBG_LVL
+*
+*	STRING
+*		[in] String to send to the current debug target.  The string includes
+*		parentheses in order to allow additional parameters.
+*
+* RETURN VALUE
+*	This macro does not return a value.
+*
+* EXAMPLE
+*	#define __MODULE__	"my_module"
+*	#define	MY_FUNC_DBG_LVL	1
+*
+*	uint32_t	my_dbg_lvl = CL_DBG_ALL;
+*
+*	void
+*	my_func()
+*	{
+*		CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*		CL_TRACE( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") );
+*		CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*	}
+*
+* RESULT
+*	my_module:my_func() [
+*	my_module:my_func(): Hello world!
+*	my_module:my_func() ]
+*
+* NOTES
+*	The requested string is printed only if all bits set in DBG_LVL are also
+*	set in CHK_LVL.  CHK_LVL may have additional bits set.
+*
+*	The CL_TRACE macro must only be used after the CL_ENTRY macro as it
+*	depends on that macro's implementation.
+*
+*	If the DBG_LVL has the upper bit set, the output will contain
+*	an "!ERROR!" statement between the function name and STRING.
+*
+*	If the __MODULE__ preprocessor keyword is defined, that keyword will be
+*	prepended to the function name, separated with a colon.
+*
+*	In multi-processor environments where the current processor can be
+*	determined, the zero-based number of the processor on which the output
+*	is generated is prepended to the output.
+*
+* SEE ALSO
+*	Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE_EXIT
+*********/
+#define CL_TRACE( DBG_LVL, CHK_LVL, STRING )								\
+{																			\
+switch( DBG_LVL & CL_DBG_ERROR )											\
+{																			\
+	case CL_DBG_ERROR:														\
+		CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_ERROR );						\
+		break;																\
+	default:																\
+		CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_INFO );							\
+		break;																\
+}																			\
+CL_PRINT( DBG_LVL, CHK_LVL, STRING );										\
+}
+
+/****d* Component Library: Debug Output/CL_TRACE_EXIT
+* NAME
+*	CL_TRACE_EXIT
+*
+* DESCRIPTION
+*	The CL_TRACE_EXIT macro combines the functionality of the CL_TRACE and
+*	CL_EXIT macros, in that order.
+*
+* SYNOPSIS
+*	CL_TRACE_EXIT(  DBG_LVL, CHK_LVL, STRING );
+*
+* PARAMETERS
+*	DBG_LVL
+*		[in] Debug level for the string to output
+*
+*	CHK_LVL
+*		[in] Current debug level against which to check DBG_LVL
+*
+*	STRING
+*		[in] String to send to the current debug target.  The string includes
+*		parentheses in order to allow additional parameters.
+*
+* RETURN VALUE
+*	This macro does not return a value.
+*
+* EXAMPLE
+*	#define __MODULE__	"my_module"
+*	#define	MY_FUNC_DBG_LVL	1
+*
+*	uint32_t	my_dbg_lvl = CL_DBG_ALL;
+*
+*	void
+*	my_func()
+*	{
+*		CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl );
+*		CL_TRACE_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") );
+*	}
+*
+* RESULT
+*	my_module:my_func() [
+*	my_module:my_func(): Hello world!
+*	my_module:my_func() ]
+*
+* NOTES
+*	The requested string is printed only if all bits set in DBG_LVL are also
+*	set in CHK_LVL.  CHK_LVL may have additional bits set.
+*
+*	The CL_TRACE_EXIT macro must only be used after the CL_ENTRY macro as it
+*	depends on that macro's implementation.
+*
+*	If the DBG_LVL has the upper bit set, the output will contain
+*	an "!ERROR!" statement between the function name and STRING.
+*
+*	If the __MODULE__ preprocessor keyword is defined, that keyword will be
+*	prepended to the function name, separated with a colon.
+*
+*	In multi-processor environments where the current processor can be
+*	determined, the zero-based number of the processor on which the output
+*	is generated is prepended to the output.
+*
+* SEE ALSO
+*	Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE
+*********/
+#define CL_TRACE_EXIT( DBG_LVL, CHK_LVL, STRING )							\
+	CL_TRACE( DBG_LVL, CHK_LVL, STRING );									\
+	CL_EXIT( DBG_LVL, CHK_LVL );
+
+#else				/* defined(_DEBUG_) */
+
+/* Define as NULL macros in a free build. */
+#define CL_PRINT( DBG_LVL, CHK_LVL, STRING );
+#define CL_ENTER( DBG_LVL, CHK_LVL );
+#define CL_EXIT( DBG_LVL, CHK_LVL );
+#define CL_TRACE( DBG_LVL, CHK_LVL, STRING );
+#define CL_TRACE_EXIT( DBG_LVL, CHK_LVL, STRING );
+
+#endif				/* defined(_DEBUG_) */
+
+/****d* Component Library: Debug Output/64-bit Print Format
+* NAME
+*	64-bit Print Format
+*
+* DESCRIPTION
+*	The 64-bit print keywords allow users to use 64-bit values in debug or
+*	console output.
+*
+*	Different platforms define 64-bit print formats differently. The 64-bit
+*	print formats exposed by the component library are supported in all
+*	platforms.
+*
+* VALUES
+*	PRId64
+*		Print a 64-bit integer in signed decimal format.
+*	PRIx64
+*		Print a 64-bit integer in hexadecimal format.
+*	PRIo64
+*		Print a 64-bit integer in octal format.
+*	PRIu64
+*		Print a 64-bit integer in unsigned decimal format.
+*
+* EXAMPLE
+*	uint64 MyVal = 2;
+*	// Print a 64-bit integer in hexadecimal format.
+*	cl_dbg_out( "MyVal: 0x%" PRIx64 "\n", MyVal );
+*
+* NOTES
+*	Standard print flags to specify padding and precision can still be used
+*	following the '%' sign in the string preceding the 64-bit print keyword.
+*
+*	The above keywords are strings and make use of compilers' string
+*	concatenation ability.
+*********/
+void complib_init(void);
+
+void complib_exit(void);
+
+END_C_DECLS
+#endif				/* _CL_DEBUG_H_ */
diff --git a/include/complib/cl_debug_osd.h b/include/complib/cl_debug_osd.h
new file mode 100644
index 0000000..31d6972
--- /dev/null
+++ b/include/complib/cl_debug_osd.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Debug Macros.
+ */
+
+#ifndef _CL_DEBUG_OSD_H_
+#define _CL_DEBUG_OSD_H_
+
+#include <complib/cl_types.h>
+#include <bits/wordsize.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#if !defined(__MODULE__)
+#define __MODULE__			""
+#define __MOD_DELIMITER__	""
+#else				/* !defined(__MODULE__) */
+#define __MOD_DELIMITER__	":"
+#endif				/* !defined(__MODULE__) */
+/*
+ * Define specifiers for print functions based on the platform
+ */
+#ifdef __IA64__
+#define PRIdSIZE_T	"ld"
+#else
+#define PRIdSIZE_T	"d"
+#endif
+#include <inttypes.h>
+#include <stdio.h>
+#define cl_msg_out	printf
+#if defined( _DEBUG_ )
+#define cl_dbg_out	printf
+#else
+#define cl_dbg_out	foo
+#endif				/* _DEBUG_ */
+/*
+ * The following macros are used internally by the CL_ENTER, CL_TRACE,
+ * CL_TRACE_EXIT, and CL_EXIT macros.
+ */
+#define _CL_DBG_ENTER	\
+	("%s%s%s() [\n", __MODULE__, __MOD_DELIMITER__, __func__)
+#define _CL_DBG_EXIT	\
+	("%s%s%s() ]\n", __MODULE__, __MOD_DELIMITER__, __func__)
+#define _CL_DBG_INFO	\
+	("%s%s%s(): ", __MODULE__, __MOD_DELIMITER__, __func__)
+#define _CL_DBG_ERROR	\
+	("%s%s%s() !ERROR!: ", __MODULE__, __MOD_DELIMITER__, __func__)
+#define CL_CHK_STK
+END_C_DECLS
+#endif				/* _CL_DEBUG_OSD_H_ */
diff --git a/include/complib/cl_dispatcher.h b/include/complib/cl_dispatcher.h
new file mode 100644
index 0000000..a5b4a28
--- /dev/null
+++ b/include/complib/cl_dispatcher.h
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of dispatcher abstraction.
+ */
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+#include <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_) */
diff --git a/include/complib/cl_event.h b/include/complib/cl_event.h
new file mode 100644
index 0000000..10805fb
--- /dev/null
+++ b/include/complib/cl_event.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of event abstraction.
+ */
+
+#ifndef _CL_EVENT_H_
+#define _CL_EVENT_H_
+
+/* Indicates that waiting on an event should never timeout */
+#define EVENT_NO_TIMEOUT	0xFFFFFFFF
+
+#include <complib/cl_event_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Event
+* NAME
+*	Event
+*
+* DESCRIPTION
+*	The Event provides the ability to suspend and wakeup a thread.
+*
+*	The event functions operates on a cl_event_t structure which should be
+*	treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_event_t
+*
+*	Initialization/Destruction:
+*		cl_event_construct, cl_event_init, cl_event_destroy
+*
+*	Manipulation:
+*		cl_event_signal, cl_event_reset, cl_event_wait_on
+*********/
+/****f* Component Library: Event/cl_event_construct
+* NAME
+*	cl_event_construct
+*
+* DESCRIPTION
+*	The cl_event_construct function constructs an event.
+*
+* SYNOPSIS
+*/
+void cl_event_construct(IN cl_event_t * const p_event);
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure to construct.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_event_destroy without first calling cl_event_init.
+*
+*	Calling cl_event_construct is a prerequisite to calling any other event
+*	function except cl_event_init.
+*
+* SEE ALSO
+*	Event, cl_event_init, cl_event_destroy
+*********/
+
+/****f* Component Library: Event/cl_event_init
+* NAME
+*	cl_event_init
+*
+* DESCRIPTION
+*	The cl_event_init function initializes an event for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_init(IN cl_event_t * const p_event, IN const boolean_t manual_reset);
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure to initialize.
+*
+*	manual_reset
+*		[in] If FALSE, indicates that the event resets itself after releasing
+*		a single waiter.  If TRUE, the event remains in the signalled state
+*		until explicitly reset by a call to cl_event_reset.
+*
+* RETURN VALUES
+*	CL_SUCCESS if event initialization succeeded.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	Allows calling event manipulation functions, such as cl_event_signal,
+*	cl_event_reset, and cl_event_wait_on.
+*
+*	The event is initially in a reset state.
+*
+* SEE ALSO
+*	Event, cl_event_construct, cl_event_destroy, cl_event_signal,
+*	cl_event_reset, cl_event_wait_on
+*********/
+
+/****f* Component Library: Event/cl_event_destroy
+* NAME
+*	cl_event_destroy
+*
+* DESCRIPTION
+*	The cl_event_destroy function performs any necessary cleanup of an event.
+*
+* SYNOPSIS
+*/
+void cl_event_destroy(IN cl_event_t * const p_event);
+
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function should only be called after a call to cl_event_construct
+*	or cl_event_init.
+*
+* SEE ALSO
+*	Event, cl_event_construct, cl_event_init
+*********/
+
+/****f* Component Library: Event/cl_event_signal
+* NAME
+*	cl_event_signal
+*
+* DESCRIPTION
+*	The cl_event_signal function sets an event to the signalled state and
+*	releases at most one waiting thread.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_event_signal(IN cl_event_t * const p_event);
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure to set.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the event was successfully signalled.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	For auto-reset events, the event is reset automatically once a wait
+*	operation is satisfied.
+*
+*	Triggering the event multiple times does not guarantee that the same
+*	number of wait operations are satisfied. This is because events are
+*	either in a signalled on non-signalled state, and triggering an event
+*	that is already in the signalled state has no effect.
+*
+* SEE ALSO
+*	Event, cl_event_reset, cl_event_wait_on
+*********/
+
+/****f* Component Library: Event/cl_event_reset
+* NAME
+*	cl_event_reset
+*
+* DESCRIPTION
+*	The cl_event_reset function sets an event to the non-signalled state.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_event_reset(IN cl_event_t * const p_event);
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure to reset.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the event was successfully reset.
+*
+*	CL_ERROR otherwise.
+*
+* SEE ALSO
+*	Event, cl_event_signal, cl_event_wait_on
+*********/
+
+/****f* Component Library: Event/cl_event_wait_on
+* NAME
+*	cl_event_wait_on
+*
+* DESCRIPTION
+*	The cl_event_wait_on function waits for the specified event to be
+*	triggered for a minimum amount of time.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wait_on(IN cl_event_t * const p_event,
+		 IN const uint32_t wait_us, IN const boolean_t interruptible);
+/*
+* PARAMETERS
+*	p_event
+*		[in] Pointer to an cl_event_t structure on which to wait.
+*
+*	wait_us
+*		[in] Number of microseconds to wait.
+*
+*	interruptible
+*		[in] Indicates whether the wait operation can be interrupted
+*		by external signals.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the wait operation succeeded in response to the event
+*	being set.
+*
+*	CL_TIMEOUT if the specified time period elapses.
+*
+*	CL_NOT_DONE if the wait was interrupted by an external signal.
+*
+*	CL_ERROR if the wait operation failed.
+*
+* NOTES
+*	If wait_us is set to EVENT_NO_TIMEOUT, the function will wait until the
+*	event is triggered and never timeout.
+*
+*	If the timeout value is zero, this function simply tests the state of
+*	the event.
+*
+*	If the event is already on the signalled state at the time of the call
+*	to cl_event_wait_on, the call completes immediately with CL_SUCCESS.
+*
+* SEE ALSO
+*	Event, cl_event_signal, cl_event_reset
+*********/
+
+END_C_DECLS
+#endif				/* _CL_EVENT_H_ */
diff --git a/include/complib/cl_event_osd.h b/include/complib/cl_event_osd.h
new file mode 100644
index 0000000..541ced0
--- /dev/null
+++ b/include/complib/cl_event_osd.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of event object.
+ */
+
+#ifndef _CL_EVENT_OSD_H_
+#define _CL_EVENT_OSD_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#include <pthread.h>		/* usr/include */
+/*
+ * Linux user mode specific data structure for the event object.
+ * Users should not access these variables directly.
+ */
+typedef struct _cl_event_t {
+	pthread_cond_t condvar;
+	pthread_mutex_t mutex;
+	boolean_t signaled;
+	boolean_t manual_reset;
+	cl_state_t state;
+} cl_event_t;
+
+END_C_DECLS
+#endif				/* _CL_EVENT_OSD_H_ */
diff --git a/include/complib/cl_event_wheel.h b/include/complib/cl_event_wheel.h
new file mode 100644
index 0000000..ac02242
--- /dev/null
+++ b/include/complib/cl_event_wheel.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of event wheel abstraction.
+ */
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.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;
+} cl_event_wheel_t;
+/*
+* FIELDS
+*	lock
+*		Spinlock to guard internal structures.
+*
+*       p_external_lock
+*               Reference to external spinlock to guard internal structures
+*               if the event wheel is part of a larger object protected by its own lock
+*
+*	events_map
+*		A Map holding all registered event items by their key.
+*
+*  closing
+*     A flag indicating the event wheel is closing. This means that
+*     callbacks that are called when closing == TRUE should just be ignored.
+*
+*	events_wheel
+*		A list of the events sorted by expiration time.
+*
+*	timer
+*		The timer scheduling event time propagation.
+*
+* SEE ALSO
+*	Event_Wheel
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t
+* NAME
+*	cl_event_wheel_reg_info_t
+*
+* DESCRIPTION
+*	Defines the event_wheel registration object structure.
+*
+*	The cl_event_wheel_reg_info_t structure is for internal use by the
+*	Event_Wheel only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel_reg_info {
+	cl_map_item_t map_item;
+	cl_list_item_t list_item;
+	uint64_t key;
+	cl_pfn_event_aged_cb_t pfn_aged_callback;
+	uint64_t aging_time;
+	uint32_t num_regs;
+	void *context;
+	cl_event_wheel_t *p_event_wheel;
+} cl_event_wheel_reg_info_t;
+/*
+* FIELDS
+*  map_item
+*     The map item of this event
+*
+*  list_item
+*     The sorted by aging time list item
+*
+*  key
+*     The key by which one can find the event
+*
+*	pfn_aged_callback
+*		The clients Event-Aged callback
+*
+*  aging_time
+*     The delta time [msec] for which the event should age.
+*
+*  num_regs
+*     The number of times the same event (key) was registered
+*
+*	context
+*		Client's context for event-aged callback.
+*
+*	p_event_wheel
+*		Pointer to this event wheel object
+*
+* SEE ALSO
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_construct
+* NAME
+*	cl_event_wheel_construct
+*
+* DESCRIPTION
+*	This function constructs a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void cl_event_wheel_construct(IN cl_event_wheel_t * const p_event_wheel);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_event_wheel_init and cl_event_wheel_destroy.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*	cl_event_wheel_init
+*
+* DESCRIPTION
+*	This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init(IN cl_event_wheel_t * const p_event_wheel);
+
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*	CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*	cl_event_wheel_init
+*
+* DESCRIPTION
+*	This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init_ex(IN cl_event_wheel_t * const p_event_wheel,
+		       IN cl_spinlock_t * p_external_lock);
+
+/*
+* PARAMETERS
+*  p_event_wheel
+*     [in] Pointer to a Event_Wheel.
+*
+*  p_external_lock
+*     [in] Reference to external spinlock to guard internal structures
+*          if the event wheel is part of a larger object protected by its own lock
+*
+* RETURN VALUE
+*	CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_destroy
+* NAME
+*	cl_event_wheel_destroy
+*
+* DESCRIPTION
+*	This function destroys a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void cl_event_wheel_destroy(IN cl_event_wheel_t * const p_event_wheel);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function does not returns until all client callback functions
+*  been successfully finished.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_dump
+* NAME
+*	cl_event_wheel_dump
+*
+* DESCRIPTION
+*	This function dumps the details of an Event_Whell object.
+*
+* SYNOPSIS
+*/
+void cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Note that this function should be called inside a lock of the event wheel!
+*  It doesn't aquire the lock by itself.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_reg
+* NAME
+*	cl_event_wheel_reg
+*
+* DESCRIPTION
+*	This function registers a client with a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel,
+		   IN const uint64_t key,
+		   IN const uint64_t aging_time_usec,
+		   IN cl_pfn_event_aged_cb_t pfn_callback,
+		   IN void *const context);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+*	key
+*		[in] The specifc Key by which events are registered.
+*
+*  aging_time_usec
+*     [in] The absolute time this event should age in usec
+*
+*	pfn_callback
+*		[in] Event Aging callback.  The Event_Wheel calls this
+*		function after the time the event has registed for has come.
+*
+*	context
+*		[in] Client context value passed to the cl_pfn_event_aged_cb_t
+*		function.
+*
+* RETURN VALUE
+*	On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_unreg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_unreg
+* NAME
+*	cl_event_wheel_unreg
+*
+* DESCRIPTION
+*	This function unregisters a client event from a Event_Wheel.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel,
+		     IN uint64_t key);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+*	key
+*		[in] The key used for registering the event
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*  After the event has aged it is automatically removed from
+*  the event wheel. So it should only be invoked when the need arises
+*  to remove existing events before they age.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs
+* NAME
+*	cl_event_wheel_num_regs
+*
+* DESCRIPTION
+*	This function returns the number of times an event was registered.
+*
+* SYNOPSIS
+*/
+uint32_t
+cl_event_wheel_num_regs(IN cl_event_wheel_t * const p_event_wheel,
+			IN uint64_t key);
+/*
+* PARAMETERS
+*	p_event_wheel
+*		[in] Pointer to a Event_Wheel.
+*
+*	key
+*		[in] The key used for registering the event
+*
+* RETURN VALUE
+*	The number of times the event was registered.
+*  0 if never registered or eventually aged.
+*
+* SEE ALSO
+*	Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg
+*********/
+
+END_C_DECLS
+#endif				/* !defined(_CL_EVENT_WHEEL_H_) */
diff --git a/include/complib/cl_fleximap.h b/include/complib/cl_fleximap.h
new file mode 100644
index 0000000..0af8766
--- /dev/null
+++ b/include/complib/cl_fleximap.h
@@ -0,0 +1,907 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of flexi map, a binary tree where the caller always provides
+ *	all necessary storage.
+ */
+
+#ifndef _CL_FLEXIMAP_H_
+#define _CL_FLEXIMAP_H_
+
+#include <complib/cl_qmap.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/Flexi Map
+* NAME
+*	Flexi Map
+*
+* DESCRIPTION
+*	Flexi map implements a binary tree that stores user provided cl_fmap_item_t
+*	structures.  Each item stored in a flexi map has a unique user defined
+*	key (duplicates are not allowed).  Flexi map provides the ability to
+*	efficiently search for an item given a key.  Flexi map allows user
+*	defined keys of any size.  Storage for keys and a comparison function
+*	are provided by users to allow flexi map to store items with arbitrary
+*	key values.
+*
+*	Flexi map does not allocate any memory, and can therefore not fail
+*	any operations due to insufficient memory.  Flexi map can thus be useful
+*	in minimizing the error paths in code.
+*
+*	Flexi map is not thread safe, and users must provide serialization when
+*	adding and removing items from the map.
+*
+*	The flexi map functions operate on a cl_fmap_t structure which should
+*	be treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_fmap_t, cl_fmap_item_t
+*
+*	Callbacks:
+*		cl_pfn_fmap_apply_t
+*
+*	Item Manipulation:
+*		cl_fmap_key
+*
+*	Initialization:
+*		cl_fmap_init
+*
+*	Iteration:
+*		cl_fmap_end, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_prev
+*
+*	Manipulation:
+*		cl_fmap_insert, cl_fmap_get, cl_fmap_remove_item, cl_fmap_remove,
+*		cl_fmap_remove_all, cl_fmap_merge, cl_fmap_delta, cl_fmap_get_next
+*
+*	Search:
+*		cl_fmap_apply_func
+*
+*	Attributes:
+*		cl_fmap_count, cl_is_fmap_empty,
+*********/
+/****s* Component Library: Flexi Map/cl_fmap_item_t
+* NAME
+*	cl_fmap_item_t
+*
+* DESCRIPTION
+*	The cl_fmap_item_t structure is used by maps to store objects.
+*
+*	The cl_fmap_item_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_fmap_item {
+	/* Must be first to allow casting. */
+	cl_pool_item_t pool_item;
+	struct _cl_fmap_item *p_left;
+	struct _cl_fmap_item *p_right;
+	struct _cl_fmap_item *p_up;
+	cl_map_color_t color;
+	const void *p_key;
+#ifdef _DEBUG_
+	struct _cl_fmap *p_map;
+#endif
+} cl_fmap_item_t;
+/*
+* FIELDS
+*	pool_item
+*		Used to store the item in a doubly linked list, allowing more
+*		efficient map traversal.
+*
+*	p_left
+*		Pointer to the map item that is a child to the left of the node.
+*
+*	p_right
+*		Pointer to the map item that is a child to the right of the node.
+*
+*	p_up
+*		Pointer to the map item that is the parent of the node.
+*
+*	p_nil
+*		Pointer to the map's NIL item, used as a terminator for leaves.
+*		The NIL sentinel is in the cl_fmap_t structure.
+*
+*	color
+*		Indicates whether a node is red or black in the map.
+*
+*	p_key
+*		Pointer to the value that uniquely represents a node in a map.  This
+*		pointer is set by calling cl_fmap_insert and can be retrieved by
+*		calling cl_fmap_key.
+*
+* NOTES
+*	None of the fields of this structure should be manipulated by users, as
+*	they are crititcal to the proper operation of the map in which they
+*	are stored.
+*
+*	To allow storing items in either a quick list, a quick pool, or a flexi
+*	map, the map implementation guarantees that the map item can be safely
+*	cast to a pool item used for storing an object in a quick pool, or cast
+*	to a list item used for storing an object in a quick list.  This removes
+*	the need to embed a flexi map item, a list item, and a pool item in
+*	objects that need to be stored in a quick list, a quick pool, and a
+*	flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_insert, cl_fmap_key, cl_pool_item_t, cl_list_item_t
+*********/
+
+/****d* Component Library: Flexi Map/cl_pfn_fmap_cmp_t
+* NAME
+*	cl_pfn_fmap_cmp_t
+*
+* DESCRIPTION
+*	The cl_pfn_fmap_cmp_t function type defines the prototype for functions
+*	used to compare item keys in a flexi map.
+*
+* SYNOPSIS
+*/
+typedef intn_t
+    (*cl_pfn_fmap_cmp_t) (IN const void *const p_key1,
+			  IN const void *const p_key2);
+/*
+* PARAMETERS
+*	p_key1
+*		[in] Pointer to the first of two keys to compare.
+*
+*	p_key2
+*		[in] Pointer to the second of two keys to compare.
+*
+* RETURN VALUE
+*	Returns 0 if the keys match.
+*	Returns less than 0 if *p_key1 is less than *p_key2.
+*	Returns greater than 0 if *p_key1 is greater than *p_key2.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_fmap_init function.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_init
+*********/
+
+/****s* Component Library: Flexi Map/cl_fmap_t
+* NAME
+*	cl_fmap_t
+*
+* DESCRIPTION
+*	Flexi map structure.
+*
+*	The cl_fmap_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_fmap {
+	cl_fmap_item_t root;
+	cl_fmap_item_t nil;
+	cl_state_t state;
+	size_t count;
+	cl_pfn_fmap_cmp_t pfn_compare;
+} cl_fmap_t;
+/*
+* PARAMETERS
+*	root
+*		Map item that serves as root of the map.  The root is set up to
+*		always have itself as parent.  The left pointer is set to point
+*		to the item at the root.
+*
+*	nil
+*		Map item that serves as terminator for all leaves, as well as
+*		providing the list item used as quick list for storing map items
+*		in a list for faster traversal.
+*
+*	state
+*		State of the map, used to verify that operations are permitted.
+*
+*	count
+*		Number of items in the map.
+*
+*	pfn_compare
+*		Pointer to a compare function to invoke to compare the keys of
+*		items in the map.
+*
+* SEE ALSO
+*	Flexi Map, cl_pfn_fmap_cmp_t
+*********/
+
+/****d* Component Library: Flexi Map/cl_pfn_fmap_apply_t
+* NAME
+*	cl_pfn_fmap_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_fmap_apply_t function type defines the prototype for
+*	functions used to iterate items in a flexi map.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_fmap_apply_t) (IN cl_fmap_item_t * const p_map_item,
+			 IN void *context);
+/*
+* PARAMETERS
+*	p_map_item
+*		[in] Pointer to a cl_fmap_item_t structure.
+*
+*	context
+*		[in] Value passed to the callback function.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_fmap_apply_func
+*	function.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_apply_func
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_count
+* NAME
+*	cl_fmap_count
+*
+* DESCRIPTION
+*	The cl_fmap_count function returns the number of items stored
+*	in a flexi map.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_fmap_count(IN const cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return (p_map->count);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure whose item count to return.
+*
+* RETURN VALUE
+*	Returns the number of items stored in the map.
+*
+* SEE ALSO
+*	Flexi Map, cl_is_fmap_empty
+*********/
+
+/****f* Component Library: Flexi Map/cl_is_fmap_empty
+* NAME
+*	cl_is_fmap_empty
+*
+* DESCRIPTION
+*	The cl_is_fmap_empty function returns whether a flexi map is empty.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_fmap_empty(IN const cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	return (p_map->count == 0);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure to test for emptiness.
+*
+* RETURN VALUES
+*	TRUE if the flexi map is empty.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_count, cl_fmap_remove_all
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_key
+* NAME
+*	cl_fmap_key
+*
+* DESCRIPTION
+*	The cl_fmap_key function retrieves the key value of a map item.
+*
+* SYNOPSIS
+*/
+static inline const void *cl_fmap_key(IN const cl_fmap_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	return (p_item->p_key);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose key value to return.
+*
+* RETURN VALUE
+*	Returns the a pointer to the key value for the specified map item.
+*	The key value should not be modified to insure proper flexi map operation.
+*
+* NOTES
+*	The key value is set in a call to cl_fmap_insert.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_insert
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_init
+* NAME
+*	cl_fmap_init
+*
+* DESCRIPTION
+*	The cl_fmap_init function initialized a flexi map for use.
+*
+* SYNOPSIS
+*/
+void cl_fmap_init(IN cl_fmap_t * const p_map, IN cl_pfn_fmap_cmp_t pfn_compare);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure to initialize.
+*
+*	pfn_compare
+*		[in] Pointer to the compare function used to compare keys.
+*		See the cl_pfn_fmap_cmp_t function type declaration for details
+*		about the callback function.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling flexi map manipulation functions.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_insert, cl_fmap_remove
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_end
+* NAME
+*	cl_fmap_end
+*
+* DESCRIPTION
+*	The cl_fmap_end function returns the end of a flexi map.
+*
+* SYNOPSIS
+*/
+static inline const cl_fmap_item_t *cl_fmap_end(IN const cl_fmap_t *
+						const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	/* Nil is the end of the map. */
+	return (&p_map->nil);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure whose end to return.
+*
+* RETURN VALUE
+*	Pointer to the end of the map.
+*
+* NOTES
+*	cl_fmap_end is useful for determining the validity of map items returned
+*	by cl_fmap_head, cl_fmap_tail, cl_fmap_next, or cl_fmap_prev.  If the
+*	map item pointer returned by any of these functions compares to the end,
+*	the end of the map was encoutered.
+*	When using cl_fmap_head or cl_fmap_tail, this condition indicates that
+*	the map is empty.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_prev
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_head
+* NAME
+*	cl_fmap_head
+*
+* DESCRIPTION
+*	The cl_fmap_head function returns the map item with the lowest key
+*	value stored in a flexi map.
+*
+* SYNOPSIS
+*/
+static inline cl_fmap_item_t *cl_fmap_head(IN const cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return ((cl_fmap_item_t *) p_map->nil.pool_item.list_item.p_next);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure whose item with the lowest key
+*		is returned.
+*
+* RETURN VALUES
+*	Pointer to the map item with the lowest key in the flexi map.
+*
+*	Pointer to the map end if the flexi map was empty.
+*
+* NOTES
+*	cl_fmap_head does not remove the item from the map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_tail, cl_fmap_next, cl_fmap_prev, cl_fmap_end,
+*	cl_fmap_item_t
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_tail
+* NAME
+*	cl_fmap_tail
+*
+* DESCRIPTION
+*	The cl_fmap_tail function returns the map item with the highest key
+*	value stored in a flexi map.
+*
+* SYNOPSIS
+*/
+static inline cl_fmap_item_t *cl_fmap_tail(IN const cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return ((cl_fmap_item_t *) p_map->nil.pool_item.list_item.p_prev);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure whose item with the highest key
+*		is returned.
+*
+* RETURN VALUES
+*	Pointer to the map item with the highest key in the flexi map.
+*
+*	Pointer to the map end if the flexi map was empty.
+*
+* NOTES
+*	cl_fmap_end does not remove the item from the map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_head, cl_fmap_next, cl_fmap_prev, cl_fmap_end,
+*	cl_fmap_item_t
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_next
+* NAME
+*	cl_fmap_next
+*
+* DESCRIPTION
+*	The cl_fmap_next function returns the map item with the next higher
+*	key value than a specified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_fmap_item_t *cl_fmap_next(IN const cl_fmap_item_t *
+					   const p_item)
+{
+	CL_ASSERT(p_item);
+	return ((cl_fmap_item_t *) p_item->pool_item.list_item.p_next);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose successor to return.
+*
+* RETURN VALUES
+*	Pointer to the map item with the next higher key value in a flexi map.
+*
+*	Pointer to the map end if the specified item was the last item in
+*	the flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_prev, cl_fmap_end,
+*	cl_fmap_item_t
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_prev
+* NAME
+*	cl_fmap_prev
+*
+* DESCRIPTION
+*	The cl_fmap_prev function returns the map item with the next lower
+*	key value than a precified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_fmap_item_t *cl_fmap_prev(IN const cl_fmap_item_t *
+					   const p_item)
+{
+	CL_ASSERT(p_item);
+	return ((cl_fmap_item_t *) p_item->pool_item.list_item.p_prev);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose predecessor to return.
+*
+* RETURN VALUES
+*	Pointer to the map item with the next lower key value in a flexi map.
+*
+*	Pointer to the map end if the specifid item was the first item in
+*	the flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_end,
+*	cl_fmap_item_t
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_insert
+* NAME
+*	cl_fmap_insert
+*
+* DESCRIPTION
+*	The cl_fmap_insert function inserts a map item into a flexi map.
+*
+* SYNOPSIS
+*/
+cl_fmap_item_t *cl_fmap_insert(IN cl_fmap_t * const p_map,
+			       IN const void *const p_key,
+			       IN cl_fmap_item_t * const p_item);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure into which to add the item.
+*
+*	p_key
+*		[in] Pointer to the key value to assign to the item.  Storage
+*		for the key must be persistant, as only the pointer is stored.
+*		Users are responsible for maintaining the validity of key
+*		 pointers while they are in use.
+*
+*	p_item
+*		[in] Pointer to a cl_fmap_item_t stucture to insert into the flexi map.
+*
+* RETURN VALUE
+*	Pointer to the item in the map with the specified key.  If insertion
+*	was successful, this is the pointer to the item.  If an item with the
+*	specified key already exists in the map, the pointer to that item is
+*	returned.
+*
+* NOTES
+*	Insertion operations may cause the flexi map to rebalance.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove, cl_fmap_item_t
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_get
+* NAME
+*	cl_fmap_get
+*
+* DESCRIPTION
+*	The cl_fmap_get function returns the map item associated with a key.
+*
+* SYNOPSIS
+*/
+cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map,
+			    IN const void *const p_key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure from which to retrieve the
+*		item with the specified key.
+*
+*	p_key
+*		[in] Pointer to a key value used to search for the desired map item.
+*
+* RETURN VALUES
+*	Pointer to the map item with the desired key value.
+*
+*	Pointer to the map end if there was no item with the desired key value
+*	stored in the flexi map.
+*
+* NOTES
+*	cl_fmap_get does not remove the item from the flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove, cl_fmap_get_next
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_get_next
+* NAME
+*	cl_fmap_get_next
+*
+* DESCRIPTION
+*	The cl_fmap_get_next function returns the first map item associated with a
+*	key > the key specified.
+*
+* SYNOPSIS
+*/
+cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map,
+				 IN const void *const p_key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure from which to retrieve the
+*		item with the specified key.
+*
+*	p_key
+*		[in] Pointer to a key value used to search for the desired map item.
+*
+* RETURN VALUES
+*	Pointer to the first map item with a key > the  desired key value.
+*
+*	Pointer to the map end if there was no item with a key > the desired key
+*	value stored in the flexi map.
+*
+* NOTES
+*	cl_fmap_get_next does not remove the item from the flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove, cl_fmap_get
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_remove_item
+* NAME
+*	cl_fmap_remove_item
+*
+* DESCRIPTION
+*	The cl_fmap_remove_item function removes the specified map item
+*	from a flexi map.
+*
+* SYNOPSIS
+*/
+void
+cl_fmap_remove_item(IN cl_fmap_t * const p_map,
+		    IN cl_fmap_item_t * const p_item);
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item to remove from its flexi map.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+*	In a debug build, cl_fmap_remove_item asserts that the item being
+*	removed es in the specified map.
+*
+* NOTES
+*	Removes the map item pointed to by p_item from its flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove, cl_fmap_remove_all, cl_fmap_insert
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_remove
+* NAME
+*	cl_fmap_remove
+*
+* DESCRIPTION
+*	The cl_fmap_remove function removes the map item with the specified key
+*	from a flexi map.
+*
+* SYNOPSIS
+*/
+cl_fmap_item_t *cl_fmap_remove(IN cl_fmap_t * const p_map,
+			       IN const void *const p_key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure from which to remove the
+*		item with the specified key.
+*
+*	p_key
+*		[in] Pointer to the key value used to search for the map item
+*		to remove.
+*
+* RETURN VALUES
+*	Pointer to the removed map item if it was found.
+*
+*	Pointer to the map end if no item with the specified key exists in the
+*	flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove_item, cl_fmap_remove_all, cl_fmap_insert
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_remove_all
+* NAME
+*	cl_fmap_remove_all
+*
+* DESCRIPTION
+*	The cl_fmap_remove_all function removes all items in a flexi map,
+*	leaving it empty.
+*
+* SYNOPSIS
+*/
+static inline void cl_fmap_remove_all(IN cl_fmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_map->root.p_left = &p_map->nil;
+	p_map->nil.pool_item.list_item.p_next = &p_map->nil.pool_item.list_item;
+	p_map->nil.pool_item.list_item.p_prev = &p_map->nil.pool_item.list_item;
+	p_map->count = 0;
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure to empty.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_remove, cl_fmap_remove_item
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_merge
+* NAME
+*	cl_fmap_merge
+*
+* DESCRIPTION
+*	The cl_fmap_merge function moves all items from one map to another,
+*	excluding duplicates.
+*
+* SYNOPSIS
+*/
+void
+cl_fmap_merge(OUT cl_fmap_t * const p_dest_map,
+	      IN OUT cl_fmap_t * const p_src_map);
+/*
+* PARAMETERS
+*	p_dest_map
+*		[out] Pointer to a cl_fmap_t structure to which items should be added.
+*
+*	p_src_map
+*		[in/out] Pointer to a cl_fmap_t structure whose items to add
+*		to p_dest_map.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Items are evaluated based on their keys only.
+*
+*	Upon return from cl_fmap_merge, the flexi map referenced by p_src_map
+*	contains all duplicate items.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_delta
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_delta
+* NAME
+*	cl_fmap_delta
+*
+* DESCRIPTION
+*	The cl_fmap_delta function computes the differences between two maps.
+*
+* SYNOPSIS
+*/
+void
+cl_fmap_delta(IN OUT cl_fmap_t * const p_map1,
+	      IN OUT cl_fmap_t * const p_map2,
+	      OUT cl_fmap_t * const p_new, OUT cl_fmap_t * const p_old);
+/*
+* PARAMETERS
+*	p_map1
+*		[in/out] Pointer to the first of two cl_fmap_t structures whose
+*		differences to compute.
+*
+*	p_map2
+*		[in/out] Pointer to the second of two cl_fmap_t structures whose
+*		differences to compute.
+*
+*	p_new
+*		[out] Pointer to an empty cl_fmap_t structure that contains the
+*		items unique to p_map2 upon return from the function.
+*
+*	p_old
+*		[out] Pointer to an empty cl_fmap_t structure that contains the
+*		items unique to p_map1 upon return from the function.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Items are evaluated based on their keys.  Items that exist in both
+*	p_map1 and p_map2 remain in their respective maps.  Items that
+*	exist only p_map1 are moved to p_old.  Likewise, items that exist only
+*	in p_map2 are moved to p_new.  This function can be useful in evaluating
+*	changes between two maps.
+*
+*	Both maps pointed to by p_new and p_old must be empty on input.  This
+*	requirement removes the possibility of failures.
+*
+* SEE ALSO
+*	Flexi Map, cl_fmap_merge
+*********/
+
+/****f* Component Library: Flexi Map/cl_fmap_apply_func
+* NAME
+*	cl_fmap_apply_func
+*
+* DESCRIPTION
+*	The cl_fmap_apply_func function executes a specified function
+*	for every item stored in a flexi map.
+*
+* SYNOPSIS
+*/
+void
+cl_fmap_apply_func(IN const cl_fmap_t * const p_map,
+		   IN cl_pfn_fmap_apply_t pfn_func,
+		   IN const void *const context);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_fmap_t structure.
+*
+*	pfn_func
+*		[in] Function invoked for every item in the flexi map.
+*		See the cl_pfn_fmap_apply_t function type declaration for
+*		details about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	The function provided must not perform any map operations, as these
+*	would corrupt the flexi map.
+*
+* SEE ALSO
+*	Flexi Map, cl_pfn_fmap_apply_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_FLEXIMAP_H_ */
diff --git a/include/complib/cl_list.h b/include/complib/cl_list.h
new file mode 100644
index 0000000..5d40b19
--- /dev/null
+++ b/include/complib/cl_list.h
@@ -0,0 +1,1292 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of list.
+ */
+
+#ifndef _CL_LIST_H_
+#define _CL_LIST_H_
+
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.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/List
+* NAME
+*	List
+*
+* DESCRIPTION
+*	List stores objects in a doubly linked list.
+*
+*	Unlike quick list, users pass pointers to the object being stored, rather
+*	than to a cl_list_item_t structure.  Insertion operations on a list can
+*	fail, and callers should trap for such failures.
+*
+*	Use quick list in situations where insertion failures cannot be tolerated.
+*
+*	List is not thread safe, and users must provide serialization.
+*
+*	The list functions operates on a cl_list_t structure which should be
+*	treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Types:
+*		cl_list_iterator_t
+*
+*	Structures:
+*		cl_list_t
+*
+*	Callbacks:
+*		cl_pfn_list_apply_t, cl_pfn_list_find_t
+*
+*	Initialization/Destruction:
+*		cl_list_construct, cl_list_init, cl_list_destroy
+*
+*	Iteration:
+*		cl_list_next, cl_list_prev, cl_list_head, cl_list_tail,
+*		cl_list_end
+*
+*	Manipulation:
+*		cl_list_insert_head, cl_list_insert_tail,
+*		cl_list_insert_array_head, cl_list_insert_array_tail,
+*		cl_list_insert_prev, cl_list_insert_next,
+*		cl_list_remove_head, cl_list_remove_tail,
+*		cl_list_remove_object, cl_list_remove_item, cl_list_remove_all
+*
+*	Search:
+*		cl_is_object_in_list, cl_list_find_from_head, cl_list_find_from_tail,
+*		cl_list_apply_func
+*
+*	Attributes:
+*		cl_list_count, cl_is_list_empty, cl_is_list_inited
+*********/
+/****s* Component Library: List/cl_list_t
+* NAME
+*	cl_list_t
+*
+* DESCRIPTION
+*	List structure.
+*
+*	The cl_list_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_list {
+	cl_qlist_t list;
+	cl_qpool_t list_item_pool;
+} cl_list_t;
+/*
+* FIELDS
+*	list
+*		Quick list of items stored in the list.
+*
+*	list_item_pool
+*		Quick pool of list objects for storing objects in the quick list.
+*
+* SEE ALSO
+*	List
+*********/
+
+/****d* Component Library: List/cl_list_iterator_t
+* NAME
+*	cl_list_iterator_t
+*
+* DESCRIPTION
+*	Iterator type used to walk a list.
+*
+* SYNOPSIS
+*/
+typedef const cl_list_item_t *cl_list_iterator_t;
+/*
+* NOTES
+*	The iterator should be treated as opaque to prevent corrupting the list.
+*
+* SEE ALSO
+*	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev,
+*	cl_list_obj
+*********/
+
+/****d* Component Library: List/cl_pfn_list_apply_t
+* NAME
+*	cl_pfn_list_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_list_apply_t function type defines the prototype for functions
+*	used to iterate objects in a list.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_list_apply_t) (IN void *const p_object, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object stored in a list.
+*
+*	context
+*		[in] Context provided in a call to cl_list_apply_func.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_list_apply_func
+*	function.
+*
+* SEE ALSO
+*	List, cl_list_apply_func
+*********/
+
+/****d* Component Library: List/cl_pfn_list_find_t
+* NAME
+*	cl_pfn_list_find_t
+*
+* DESCRIPTION
+*	The cl_pfn_list_find_t function type defines the prototype for functions
+*	used to find objects in a list.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_list_find_t) (IN const void *const p_object, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object stored in a list.
+*
+*	context
+*		[in] Context provided in a call to ListFindFromHead or ListFindFromTail.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS if the desired item was found.  This stops list iteration.
+*
+*	Return CL_NOT_FOUND to continue the list iteration.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_list_find_from_head
+*	and cl_list_find_from_tail functions.
+*
+* SEE ALSO
+*	List, cl_list_find_from_head, cl_list_find_from_tail
+*********/
+
+/****f* Component Library: List/cl_list_construct
+* NAME
+*	cl_list_construct
+*
+* DESCRIPTION
+*	The cl_list_construct function constructs a list.
+*
+* SYNOPSIS
+*/
+void cl_list_construct(IN cl_list_t * const p_list);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to cl_list_t object whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_list_init, cl_list_destroy and cl_is_list_inited.
+*
+*	Calling cl_list_construct is a prerequisite to calling any other
+*	list function except cl_list_init.
+*
+* SEE ALSO
+*	List, cl_list_init, cl_list_destroy, cl_is_list_inited
+*********/
+
+/****f* Component Library: List/cl_is_list_inited
+* NAME
+*	cl_is_list_inited
+*
+* DESCRIPTION
+*	The cl_is_list_inited function returns whether a list was
+*	initialized successfully.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_list_inited(IN const cl_list_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/*
+	 * The pool is the last thing initialized.  If it is initialized, the
+	 * list is initialized too.
+	 */
+	return (cl_is_qpool_inited(&p_list->list_item_pool));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure whose initilization state
+*		to check.
+*
+* RETURN VALUES
+*	TRUE if the list was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a list to determine if invoking
+*	member functions is appropriate.
+*
+* SEE ALSO
+*	List
+*********/
+
+/****f* Component Library: List/cl_list_init
+* NAME
+*	cl_list_init
+*
+* DESCRIPTION
+*	The cl_list_init function initializes a list for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to cl_list_t structure to initialize.
+*
+*	min_items
+*		[in] Minimum number of items that can be stored.  All necessary
+*		allocations to allow storing the minimum number of items is performed
+*		at initialization time.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the list was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for initialization.
+*
+* NOTES
+*	The list will always be able to store at least as many items as specified
+*	by the min_items parameter.
+*
+* SEE ALSO
+*	List, cl_list_construct, cl_list_destroy, cl_list_insert_head,
+*	cl_list_insert_tail, cl_list_remove_head, cl_list_remove_tail
+*********/
+
+/****f* Component Library: List/cl_list_destroy
+* NAME
+*	cl_list_destroy
+*
+* DESCRIPTION
+*	The cl_list_destroy function destroys a list.
+*
+* SYNOPSIS
+*/
+void cl_list_destroy(IN cl_list_t * const p_list);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to cl_list_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_list_destroy does not affect any of the objects stored in the list,
+*	but does release all memory allocated internally.  Further operations
+*	should not be attempted on the list after cl_list_destroy is invoked.
+*
+*	This function should only be called after a call to cl_list_construct
+*	or cl_list_init.
+*
+*	In debug builds, cl_list_destroy asserts if the list is not empty.
+*
+* SEE ALSO
+*	List, cl_list_construct, cl_list_init
+*********/
+
+/****f* Component Library: List/cl_is_list_empty
+* NAME
+*	cl_is_list_empty
+*
+* DESCRIPTION
+*	The cl_is_list_empty function returns whether a list is empty.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_list_empty(IN const cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+	return (cl_is_qlist_empty(&p_list->list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure.
+*
+* RETURN VALUES
+*	TRUE if the specified list is empty.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	List, cl_list_count, cl_list_remove_all
+*********/
+
+/****f* Component Library: List/cl_list_insert_head
+* NAME
+*	cl_list_insert_head
+*
+* DESCRIPTION
+*	The cl_list_insert_head function inserts an object at the head of a list.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_list_insert_head(IN cl_list_t * const p_list, IN const void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* Get a list item to add to the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
+	if (!p_pool_obj)
+		return (CL_INSUFFICIENT_MEMORY);
+
+	p_pool_obj->p_object = p_object;
+	cl_qlist_insert_head(&p_list->list, &p_pool_obj->pool_item.list_item);
+	return (CL_SUCCESS);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the object.
+*
+*	p_object
+*		[in] Pointer to an object to insert into the list.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* NOTES
+*	Inserts the specified object at the head of the list.  List insertion
+*	operations are guaranteed to work for the minimum number of items as
+*	specified in cl_list_init by the min_items parameter.
+*
+* SEE ALSO
+*	List, cl_list_insert_tail, cl_list_insert_array_head,
+*	cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next,
+*	cl_list_remove_head
+*********/
+
+/****f* Component Library: List/cl_list_insert_tail
+* NAME
+*	cl_list_insert_tail
+*
+* DESCRIPTION
+*	The cl_list_insert_tail function inserts an object at the tail of a list.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_list_insert_tail(IN cl_list_t * const p_list, IN const void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* Get a list item to add to the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
+	if (!p_pool_obj)
+		return (CL_INSUFFICIENT_MEMORY);
+
+	p_pool_obj->p_object = p_object;
+	cl_qlist_insert_tail(&p_list->list, &p_pool_obj->pool_item.list_item);
+	return (CL_SUCCESS);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the object.
+*
+*	p_object
+*		[in] Pointer to an object to insert into the list.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* NOTES
+*	Inserts the specified object at the tail of the list.  List insertion
+*	operations are guaranteed to work for the minimum number of items as
+*	specified in cl_list_init by the min_items parameter.
+*
+* SEE ALSO
+*	List, cl_list_insert_head, cl_list_insert_array_head,
+*	cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next,
+*	cl_list_remove_tail
+*********/
+
+/****f* Component Library: List/cl_list_insert_array_head
+* NAME
+*	cl_list_insert_array_head
+*
+* DESCRIPTION:
+*	The cl_list_insert_array_head function inserts an array of objects
+*	at the head of a list.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_list_insert_array_head(IN cl_list_t * const p_list,
+			  IN const void *const p_array,
+			  IN uint32_t item_count, IN const uint32_t item_size);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the objects.
+*
+*	p_array
+*		[in] Pointer to the first object in an array.
+*
+*	item_count
+*		[in] Number of objects in the array.
+*
+*	item_size
+*		[in] Size of the objects added to the list.  This is the stride in the
+*		array from one object to the next.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* NOTES
+*	Inserts all objects in the array to the head of the list, preserving the
+*	ordering of the objects.  If not successful, no items are added.
+*	List insertion operations are guaranteed to work for the minimum number
+*	of items as specified in cl_list_init by the min_items parameter.
+*
+* SEE ALSO
+*	List, cl_list_insert_array_tail, cl_list_insert_head, cl_list_insert_tail,
+*	cl_list_insert_prev, cl_list_insert_next
+*********/
+
+/****f* Component Library: List/cl_list_insert_array_tail
+* NAME
+*	cl_list_insert_array_tail
+*
+* DESCRIPTION
+*	The cl_list_insert_array_tail function inserts an array of objects
+*	at the tail of a list.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_list_insert_array_tail(IN cl_list_t * const p_list,
+			  IN const void *const p_array,
+			  IN uint32_t item_count, IN const uint32_t item_size);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the objects.
+*
+*	p_array
+*		[in] Pointer to the first object in an array.
+*
+*	item_count
+*		[in] Number of objects in the array.
+*
+*	item_size
+*		[in] Size of the objects added to the list.  This is the stride in the
+*		array from one object to the next.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* NOTES
+*	Inserts all objects in the array to the tail of the list, preserving the
+*	ordering of the objects.  If not successful, no items are added.
+*	List insertion operations are guaranteed to work for the minimum number
+*	of items as specified in cl_list_init by the min_items parameter.
+*
+* SEE ALSO
+*	List, cl_list_insert_array_head, cl_list_insert_head, cl_list_insert_tail,
+*	cl_list_insert_prev, cl_list_insert_next
+*********/
+
+/****f* Component Library: List/cl_list_insert_next
+* NAME
+*	cl_list_insert_next
+*
+* DESCRIPTION
+*	The cl_list_insert_next function inserts an object in a list after
+*	the object associated with a given iterator.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_list_insert_next(IN cl_list_t * const p_list,
+		    IN cl_list_iterator_t iterator,
+		    IN const void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* Get a list item to add to the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
+	if (!p_pool_obj)
+		return (CL_INSUFFICIENT_MEMORY);
+
+	p_pool_obj->p_object = p_object;
+	cl_qlist_insert_next(&p_list->list, (cl_list_item_t *) iterator,
+			     &p_pool_obj->pool_item.list_item);
+	return (CL_SUCCESS);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the object.
+*
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev.
+*
+*	p_object
+*		[in] Pointer to an object to insert into the list.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* SEE ALSO
+*	List, cl_list_insert_prev, cl_list_insert_head, cl_list_insert_tail,
+*	cl_list_insert_array_head, cl_list_insert_array_tail
+*********/
+
+/****f* Component Library: List/cl_list_insert_prev
+* NAME
+*	cl_list_insert_prev
+*
+* DESCRIPTION
+*	The cl_list_insert_prev function inserts an object in a list before
+*	the object associated with a given iterator.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_list_insert_prev(IN cl_list_t * const p_list,
+		    IN cl_list_iterator_t iterator,
+		    IN const void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* Get a list item to add to the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
+	if (!p_pool_obj)
+		return (CL_INSUFFICIENT_MEMORY);
+
+	p_pool_obj->p_object = p_object;
+	cl_qlist_insert_prev(&p_list->list, (cl_list_item_t *) iterator,
+			     &p_pool_obj->pool_item.list_item);
+	return (CL_SUCCESS);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure into which to insert the object.
+*
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev.
+*
+*	p_object
+*		[in] Pointer to an object to insert into the list.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the insertion was successful.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
+*
+* SEE ALSO
+*	List, cl_list_insert_next, cl_list_insert_head, cl_list_insert_tail,
+*	cl_list_insert_array_head, cl_list_insert_array_tail
+*********/
+
+/****f* Component Library: List/cl_list_remove_head
+* NAME
+*	cl_list_remove_head
+*
+* DESCRIPTION
+*	The cl_list_remove_head function removes an object from the head of a list.
+*
+* SYNOPSIS
+*/
+static inline void *cl_list_remove_head(IN cl_list_t * const p_list)
+{
+	cl_pool_obj_t *p_pool_obj;
+	void *p_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* See if the list is empty. */
+	if (cl_is_qlist_empty(&p_list->list))
+		return (NULL);
+
+	/* Get the item at the head of the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_head(&p_list->list);
+
+	p_obj = (void *)p_pool_obj->p_object;
+	/* Place the pool item back into the pool. */
+	cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item);
+
+	return (p_obj);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure from which to remove an object.
+*
+* RETURN VALUES
+*	Returns the pointer to the object formerly at the head of the list.
+*
+*	NULL if the list was empty.
+*
+* SEE ALSO
+*	List, cl_list_remove_tail, cl_list_remove_all, cl_list_remove_object,
+*	cl_list_remove_item, cl_list_insert_head
+*********/
+
+/****f* Component Library: List/cl_list_remove_tail
+* NAME
+*	cl_list_remove_tail
+*
+* DESCRIPTION
+*	The cl_list_remove_tail function removes an object from the tail of a list.
+*
+* SYNOPSIS
+*/
+static inline void *cl_list_remove_tail(IN cl_list_t * const p_list)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* See if the list is empty. */
+	if (cl_is_qlist_empty(&p_list->list))
+		return (NULL);
+
+	/* Get the item at the head of the list. */
+	p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_tail(&p_list->list);
+
+	/* Place the list item back into the pool. */
+	cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item);
+
+	return ((void *)p_pool_obj->p_object);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure from which to remove an object.
+*
+* RETURN VALUES
+*	Returns the pointer to the object formerly at the tail of the list.
+*
+*	NULL if the list was empty.
+*
+* SEE ALSO
+*	List, cl_list_remove_head, cl_list_remove_all, cl_list_remove_object,
+*	cl_list_remove_item, cl_list_insert_head
+*********/
+
+/****f* Component Library: List/cl_list_remove_all
+* NAME
+*	cl_list_remove_all
+*
+* DESCRIPTION
+*	The cl_list_remove_all function removes all objects from a list,
+*	leaving it empty.
+*
+* SYNOPSIS
+*/
+static inline void cl_list_remove_all(IN cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	/* Return all the list items to the pool. */
+	cl_qpool_put_list(&p_list->list_item_pool, &p_list->list);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure from which to remove all objects.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	List, cl_list_remove_head, cl_list_remove_tail, cl_list_remove_object,
+*	cl_list_remove_item
+*********/
+
+/****f* Component Library: List/cl_list_remove_object
+* NAME
+*	cl_list_remove_object
+*
+* DESCRIPTION
+*	The cl_list_remove_object function removes a specific object from a list.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_list_remove_object(IN cl_list_t * const p_list,
+		      IN const void *const p_object);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure from which to remove the object.
+*
+*	p_object
+*		[in] Pointer to an object to remove from the list.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the object was removed.
+*
+*	CL_NOT_FOUND if the object was not found in the list.
+*
+* NOTES
+*	Removes the first occurrence of an object from a list.
+*
+* SEE ALSO
+*	List, cl_list_remove_item, cl_list_remove_head, cl_list_remove_tail,
+*	cl_list_remove_all
+*********/
+
+/****f* Component Library: List/cl_list_remove_item
+* NAME
+*	cl_list_remove_item
+*
+* DESCRIPTION
+*	The cl_list_remove_item function removes an object from the head of a list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_list_remove_item(IN cl_list_t * const p_list, IN cl_list_iterator_t iterator)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	cl_qlist_remove_item(&p_list->list, (cl_list_item_t *) iterator);
+
+	/* Place the list item back into the pool. */
+	cl_qpool_put(&p_list->list_item_pool, (cl_pool_item_t *) iterator);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure from which to remove the item.
+*
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	List, cl_list_remove_object, cl_list_remove_head, cl_list_remove_tail,
+*	cl_list_remove_all
+*********/
+
+/****f* Component Library: List/cl_is_object_in_list
+* NAME
+*	cl_is_object_in_list
+*
+* DESCRIPTION
+*	The cl_is_object_in_list function returns whether an object
+*	is stored in a list.
+*
+* SYNOPSIS
+*/
+boolean_t
+cl_is_object_in_list(IN const cl_list_t * const p_list,
+		     IN const void *const p_object);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure in which to look for the object.
+*
+*	p_object
+*		[in] Pointer to an object stored in a list.
+*
+* RETURN VALUES
+*	TRUE if p_object was found in the list.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	List
+*********/
+
+/****f* Component Library: List/cl_list_end
+* NAME
+*	cl_list_end
+*
+* DESCRIPTION
+*	The cl_list_end function returns returns the list iterator for
+*	the end of a list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_iterator_t cl_list_end(IN const cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	return (cl_qlist_end(&p_list->list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure for which the iterator for the
+*		object at the head is to be returned.
+*
+* RETURN VALUE
+*	cl_list_iterator_t for the end of the list.
+*
+* NOTES
+*	Use cl_list_obj to retrieve the object associated with the
+*	returned cl_list_iterator_t.
+*
+* SEE ALSO
+*	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev,
+*	cl_list_obj
+*********/
+
+/****f* Component Library: List/cl_list_head
+* NAME
+*	cl_list_head
+*
+* DESCRIPTION
+*	The cl_list_head function returns returns a list iterator for
+*	the head of a list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_iterator_t cl_list_head(IN const cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	return (cl_qlist_head(&p_list->list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure for which the iterator for the
+*		object at the head is to be returned.
+*
+* RETURN VALUES
+*	cl_list_iterator_t for the head of the list.
+*
+*	cl_list_iterator_t for the end of the list if the list is empty.
+*
+* NOTES
+*	Use cl_list_obj to retrieve the object associated with the
+*	returned cl_list_iterator_t.
+*
+* SEE ALSO
+*	List, cl_list_tail, cl_list_next, cl_list_prev, cl_list_end,
+*	cl_list_obj
+*********/
+
+/****f* Component Library: List/cl_list_tail
+* NAME
+*	cl_list_tail
+*
+* DESCRIPTION
+*	The cl_list_tail function returns returns a list iterator for
+*	the tail of a list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_iterator_t cl_list_tail(IN const cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	return (cl_qlist_tail(&p_list->list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure for which the iterator for the
+*		object at the tail is to be returned.
+*
+* RETURN VALUES
+*	cl_list_iterator_t for the tail of the list.
+*
+*	cl_list_iterator_t for the end of the list if the list is empty.
+*
+* NOTES
+*	Use cl_list_obj to retrieve the object associated with the
+*
+*	returned cl_list_iterator_t.
+*
+* SEE ALSO
+*	List, cl_list_head, cl_list_next, cl_list_prev, cl_list_end,
+*	cl_list_obj
+*********/
+
+/****f* Component Library: List/cl_list_next
+* NAME
+*	cl_list_next
+*
+* DESCRIPTION
+*	The cl_list_next function returns a list iterator for the object stored
+*	in a list after the object associated with a given list iterator.
+*
+* SYNOPSIS
+*/
+static inline cl_list_iterator_t cl_list_next(IN cl_list_iterator_t iterator)
+{
+	CL_ASSERT(iterator);
+
+	return (cl_qlist_next(iterator));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure for which the iterator for the
+*		next object is to be returned.
+*
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev.
+*
+* RETURN VALUES
+*	cl_list_iterator_t for the object following the object associated with
+*	the list iterator specified by the iterator parameter.
+*
+*	cl_list_iterator_t for the end of the list if the list is empty.
+*
+* NOTES
+*	Use cl_list_obj to retrieve the object associated with the
+*	returned cl_list_iterator_t.
+*
+* SEE ALSO
+*	List, cl_list_prev, cl_list_head, cl_list_tail, cl_list_end,
+*	cl_list_obj
+*********/
+
+/****f* Component Library: List/cl_list_prev
+* NAME
+*	cl_list_prev
+*
+* DESCRIPTION
+*	The cl_list_prev function returns a list iterator for the object stored
+*	in a list before the object associated with a given list iterator.
+*
+* SYNOPSIS
+*/
+static inline cl_list_iterator_t cl_list_prev(IN cl_list_iterator_t iterator)
+{
+	CL_ASSERT(iterator);
+
+	return (cl_qlist_prev(iterator));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure for which the iterator for the
+*		next object is to be returned.
+*
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev.
+*
+* RETURN VALUES
+*	cl_list_iterator_t for the object preceding the object associated with
+*	the list iterator specified by the iterator parameter.
+*
+*	cl_list_iterator_t for the end of the list if the list is empty.
+*
+* NOTES
+*	Use cl_list_obj to retrieve the object associated with the
+*	returned cl_list_iterator_t.
+*
+* SEE ALSO
+*	List, cl_list_next, cl_list_head, cl_list_tail, cl_list_end,
+*	cl_list_obj
+*********/
+
+/****f* Component Library: List/cl_list_obj
+* NAME
+*	cl_list_obj
+*
+* DESCRIPTION
+*	The cl_list_obj function returns the object associated
+*	with a list iterator.
+*
+* SYNOPSIS
+*/
+static inline void *cl_list_obj(IN cl_list_iterator_t iterator)
+{
+	CL_ASSERT(iterator);
+
+	return ((void *)((cl_pool_obj_t *) iterator)->p_object);
+}
+
+/*
+* PARAMETERS
+*	iterator
+*		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
+*		cl_list_tail, cl_list_next, or cl_list_prev whose object is requested.
+*
+* RETURN VALUE
+*	Pointer to the object associated with the list iterator specified
+*	by the iterator parameter.
+*
+* SEE ALSO
+*	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev
+*********/
+
+/****f* Component Library: List/cl_list_find_from_head
+* NAME
+*	cl_list_find_from_head
+*
+* DESCRIPTION
+*	The cl_list_find_from_head function uses a specified function
+*	to search for an object starting from the head of a list.
+*
+* SYNOPSIS
+*/
+cl_list_iterator_t
+cl_list_find_from_head(IN const cl_list_t * const p_list,
+		       IN cl_pfn_list_find_t pfn_func,
+		       IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure to search.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_list_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	Returns the iterator for the object if found.
+*
+*	Returns the iterator for the list end otherwise.
+*
+* NOTES
+*	cl_list_find_from_head does not remove the found object from
+*	the list.  The iterator for the object is returned when the function
+*	provided by the pfn_func parameter returns CL_SUCCESS.  The function
+*	specified by the pfn_func parameter must not perform any list
+*	operations as these would corrupt the list.
+*
+* SEE ALSO
+*	List, cl_list_find_from_tail, cl_list_apply_func_t,
+*	cl_pfn_list_find_t
+*********/
+
+/****f* Component Library: List/cl_list_find_from_tail
+* NAME
+*	cl_list_find_from_tail
+*
+* DESCRIPTION
+*	The cl_list_find_from_tail function uses a specified function
+*	to search for an object starting from the tail of a list.
+*
+* SYNOPSIS
+*/
+cl_list_iterator_t
+cl_list_find_from_tail(IN const cl_list_t * const p_list,
+		       IN cl_pfn_list_find_t pfn_func,
+		       IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure to search.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_list_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	Returns the iterator for the object if found.
+*
+*	Returns the iterator for the list end otherwise.
+*
+* NOTES
+*	cl_list_find_from_tail does not remove the found object from
+*	the list.  The iterator for the object is returned when the function
+*	provided by the pfn_func parameter returns CL_SUCCESS.  The function
+*	specified by the pfn_func parameter must not perform any list
+*	operations as these would corrupt the list.
+*
+* SEE ALSO
+*	List, cl_list_find_from_head, cl_list_apply_func_t,
+*	cl_pfn_list_find_t
+*********/
+
+/****f* Component Library: List/cl_list_apply_func
+* NAME
+*	cl_list_apply_func
+*
+* DESCRIPTION
+*	The cl_list_apply_func function executes a specified function for every
+*	object stored in a list.
+*
+* SYNOPSIS
+*/
+void
+cl_list_apply_func(IN const cl_list_t * const p_list,
+		   IN cl_pfn_list_apply_t pfn_func,
+		   IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure to iterate.
+*
+*	pfn_func
+*		[in] Function invoked for every item in a list.
+*		See the cl_pfn_list_apply_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_list_apply_func invokes the specified callback function for every
+*	object stored in the list, starting from the head.  The function specified
+*	by the pfn_func parameter must not perform any list operations as these
+*	would corrupt the list.
+*
+* SEE ALSO
+*	List, cl_list_find_from_head, cl_list_find_from_tail,
+*	cl_pfn_list_apply_t
+*********/
+
+/****f* Component Library: List/cl_list_count
+* NAME
+*	cl_list_count
+*
+* DESCRIPTION
+*	The cl_list_count function returns the number of objects stored in a list.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_list_count(IN const cl_list_t * const p_list)
+{
+	CL_ASSERT(p_list);
+	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
+
+	return (cl_qlist_count(&p_list->list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_list_t structure whose object to count.
+*
+* RETURN VALUES
+*	Number of objects stored in the specified list.
+*
+* SEE ALSO
+*	List
+*********/
+
+END_C_DECLS
+#endif				/* _CL_LIST_H_ */
diff --git a/include/complib/cl_log.h b/include/complib/cl_log.h
new file mode 100644
index 0000000..45c7ec3
--- /dev/null
+++ b/include/complib/cl_log.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of logging mechanisms.
+ */
+
+#ifndef _CL_LOG_H_
+#define _CL_LOG_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Log Provider
+* NAME
+*	Log Provider
+*
+* DESCRIPTION
+*	The log provider allows users to log information in a system log instead of
+*	the console or debugger target.
+**********/
+/****d* Component Library: Log Provider/cl_log_type_t
+* NAME
+*	cl_log_type_t
+*
+* DESCRIPTION
+*	The cl_log_type_t enumerated type is used to differentiate between
+*	different types of log entries.
+*
+* SYNOPSIS
+*/
+typedef enum _cl_log_type {
+	CL_LOG_INFO,
+	CL_LOG_WARN,
+	CL_LOG_ERROR
+} cl_log_type_t;
+/*
+* VALUES
+*	CL_LOG_INFO
+*		Indicates a log entry is purely informational.
+*
+*	CL_LOG_WARN
+*		Indicates a log entry is a warning but non-fatal.
+*
+*	CL_LOG_ERROR
+*		Indicates a log entry is a fatal error.
+*
+* SEE ALSO
+*	Log Provider, cl_log_event
+*********/
+
+/****f* Component Library: Log Provider/cl_log_event
+* NAME
+*	cl_log_event
+*
+* DESCRIPTION
+*	The cl_log_event function adds a new entry to the system log.
+*
+* SYNOPSIS
+*/
+void
+cl_log_event(IN const char *const name,
+	     IN const cl_log_type_t type,
+	     IN const char *const message,
+	     IN const void *const p_data OPTIONAL, IN const uint32_t data_len);
+/*
+* PARAMETERS
+*	name
+*		[in] Pointer to an ANSI string containing the name of the source for
+*		the log entry.
+*
+*	type
+*		[in] Defines the type of log entry to add to the system log.
+*		See the definition of cl_log_type_t for acceptable values.
+*
+*	message
+*		[in] Pointer to an ANSI string containing the text for the log entry.
+*		The message should not be terminated with a new line, as the log
+*		provider appends a new line to all log entries.
+*
+*	p_data
+*		[in] Optional pointer to data providing context for the log entry.
+*		At most 256 bytes of data can be successfully logged.
+*
+*	data_len
+*		[in] Length of the buffer pointed to by the p_data parameter.  Ignored
+*		if p_data is NULL.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	If the data length exceeds the maximum supported, the event is logged
+*	without its accompanying data.
+*
+* SEE ALSO
+*	Log Provider, cl_log_type_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_LOG_H_ */
diff --git a/include/complib/cl_map.h b/include/complib/cl_map.h
new file mode 100644
index 0000000..5bf779c
--- /dev/null
+++ b/include/complib/cl_map.h
@@ -0,0 +1,846 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of map, a binary tree.
+ */
+
+#ifndef _CL_MAP_H_
+#define _CL_MAP_H_
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_qpool.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/Map
+* NAME
+*	Map
+*
+* DESCRIPTION
+*	Map implements a binary tree that stores user objects.  Each item stored
+*	in a map has a unique 64-bit key (duplicates are not allowed).  Map
+*	provides the ability to efficiently search for an item given a key.
+*
+*	Map may allocate memory when inserting objects, and can therefore fail
+*	operations due to insufficient memory.  Use quick map in situations
+*	where such insertion failures cannot be tolerated.
+*
+*	Map is not thread safe, and users must provide serialization when adding
+*	and removing items from the map.
+*
+*	The map functions operates on a cl_map_t structure which should be treated
+*	as opaque and should be manipulated only through the provided functions.
+*
+* SEE ALSO
+*	Types:
+*		cl_map_iterator_t
+*
+*	Structures:
+*		cl_map_t, cl_map_item_t, cl_map_obj_t
+*
+*	Item Manipulation:
+*		cl_map_obj, cl_map_key
+*
+*	Initialization:
+*		cl_map_construct, cl_map_init, cl_map_destroy
+*
+*	Iteration:
+*		cl_map_end, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev
+*
+*	Manipulation
+*		cl_map_insert, cl_map_get, cl_map_remove_item, cl_map_remove,
+*		cl_map_remove_all, cl_map_merge, cl_map_delta, cl_map_get_next
+*
+*	Attributes:
+*		cl_map_count, cl_is_map_empty, cl_is_map_inited
+*********/
+/****s* Component Library: Map/cl_map_t
+* NAME
+*	cl_map_t
+*
+* DESCRIPTION
+*	Quick map structure.
+*
+*	The cl_map_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_map {
+	cl_qmap_t qmap;
+	cl_qpool_t pool;
+} cl_map_t;
+/*
+* FIELDS
+*	qmap
+*		Quick map object that maintains the map.
+*
+*	pool
+*		Pool of cl_map_obj_t structures used to store user objects
+*		in the map.
+*
+* SEE ALSO
+*	Map, cl_map_obj_t
+*********/
+
+/****d* Component Library: Map/cl_map_iterator_t
+* NAME
+*	cl_map_iterator_t
+*
+* DESCRIPTION
+*	Iterator type used to walk a map.
+*
+* SYNOPSIS
+*/
+typedef const cl_map_item_t *cl_map_iterator_t;
+/*
+* NOTES
+*	The iterator should be treated as opaque to prevent corrupting the map.
+*
+* SEE ALSO
+*	Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev, cl_map_key
+*********/
+
+/****f* Component Library: Map/cl_map_count
+* NAME
+*	cl_map_count
+*
+* DESCRIPTION
+*	The cl_map_count function returns the number of items stored
+*	in a map.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_map_count(IN const cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (cl_qmap_count(&p_map->qmap));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map whose item count to return.
+*
+* RETURN VALUE
+*	Returns the number of items stored in the map.
+*
+* SEE ALSO
+*	Map, cl_is_map_empty
+*********/
+
+/****f* Component Library: Map/cl_is_map_empty
+* NAME
+*	cl_is_map_empty
+*
+* DESCRIPTION
+*	The cl_is_map_empty function returns whether a map is empty.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_map_empty(IN const cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (cl_is_qmap_empty(&p_map->qmap));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map to test for emptiness.
+*
+* RETURN VALUES
+*	TRUE if the map is empty.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Map, cl_map_count, cl_map_remove_all
+*********/
+
+/****f* Component Library: Map/cl_map_key
+* NAME
+*	cl_map_key
+*
+* DESCRIPTION
+*	The cl_map_key function retrieves the key value of a map item.
+*
+* SYNOPSIS
+*/
+static inline uint64_t cl_map_key(IN const cl_map_iterator_t itor)
+{
+	return (cl_qmap_key(itor));
+}
+
+/*
+* PARAMETERS
+*	itor
+*		[in] Iterator for the item whose key to return.
+*
+* RETURN VALUE
+*	Returns the 64-bit key value for the specified iterator.
+*
+* NOTES
+*	The iterator specified by the itor parameter must have been retrived by
+*	a previous call to cl_map_head, cl_map_tail, cl_map_next, or cl_map_prev.
+*
+*	The key value is set in a call to cl_map_insert.
+*
+* SEE ALSO
+*	Map, cl_map_insert, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev
+*********/
+
+/****f* Component Library: Map/cl_map_construct
+* NAME
+*	cl_map_construct
+*
+* DESCRIPTION
+*	The cl_map_construct function constructs a map.
+*
+* SYNOPSIS
+*/
+void cl_map_construct(IN cl_map_t * const p_map);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_map_t structure to construct.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_map_init, cl_map_destroy, and cl_is_map_inited.
+*
+*	Calling cl_map_construct is a prerequisite to calling any other
+*	map function except cl_map_init.
+*
+* SEE ALSO
+*	Map, cl_map_init, cl_map_destroy, cl_is_map_inited
+*********/
+
+/****f* Component Library: Event/cl_is_map_inited
+* NAME
+*	cl_is_map_inited
+*
+* DESCRIPTION
+*	The cl_is_map_inited function returns whether a map was
+*	successfully initialized.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_map_inited(IN const cl_map_t * const p_map)
+{
+	/*
+	 * The map's pool of map items is the last thing initialized.
+	 * We can therefore use it to test for initialization.
+	 */
+	return (cl_is_qpool_inited(&p_map->pool));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_map_t structure whose initialization state
+*		to check.
+*
+* RETURN VALUES
+*	TRUE if the map was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a map to determine if invoking
+*	member functions is appropriate.
+*
+* SEE ALSO
+*	Map
+*********/
+
+/****f* Component Library: Map/cl_map_init
+* NAME
+*	cl_map_init
+*
+* DESCRIPTION
+*	The cl_map_init function initialized a map for use.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_map_t structure to initialize.
+*
+*	min_items
+*		[in] Minimum number of items that can be stored.  All necessary
+*		allocations to allow storing the minimum number of items is
+*		performed at initialization time.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the map was initialized successfully.
+*
+* NOTES
+*	Allows calling map manipulation functions.
+*
+* SEE ALSO
+*	Map, cl_map_destroy, cl_map_insert, cl_map_remove
+*********/
+
+/****f* Component Library: Map/cl_map_destroy
+* NAME
+*	cl_map_destroy
+*
+* DESCRIPTION
+*	The cl_map_destroy function destroys a map.
+*
+* SYNOPSIS
+*/
+void cl_map_destroy(IN cl_map_t * const p_map);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Performs any necessary cleanup of the specified map. Further
+*	operations should not be attempted on the map. cl_map_destroy does
+*	not affect any of the objects stored in the map.
+*	This function should only be called after a call to cl_map_construct.
+*
+*	In debug builds, cl_map_destroy asserts that the map is empty.
+*
+* SEE ALSO
+*	Map, cl_map_construct, cl_map_init
+*********/
+
+/****f* Component Library: Map/cl_map_end
+* NAME
+*	cl_map_end
+*
+* DESCRIPTION
+*	The cl_map_end function returns the iterator for the end of a map.
+*
+* SYNOPSIS
+*/
+static inline cl_map_iterator_t cl_map_end(IN const cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (cl_qmap_end(&p_map->qmap));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_map_t structure whose end to return.
+*
+* RETURN VALUE
+*	Iterator for the end of the map.
+*
+* NOTES
+*	cl_map_end is useful for determining the validity of map items returned
+*	by cl_map_head, cl_map_tail, cl_map_next, cl_map_prev.  If the iterator
+*	by any of these functions compares to the end, the end of the map was
+*	encoutered.
+*	When using cl_map_head or cl_map_tail, this condition indicates that
+*	the map is empty.
+*
+* SEE ALSO
+*	Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev
+*********/
+
+/****f* Component Library: Map/cl_map_head
+* NAME
+*	cl_map_head
+*
+* DESCRIPTION
+*	The cl_map_head function returns the map item with the lowest key
+*	value stored in a map.
+*
+* SYNOPSIS
+*/
+static inline cl_map_iterator_t cl_map_head(IN const cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (cl_qmap_head(&p_map->qmap));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map whose item with the lowest key is returned.
+*
+* RETURN VALUES
+*	Iterator for the object with the lowest key in the map.
+*
+*	Iterator for the map end if the map was empty.
+*
+* NOTES
+*	cl_map_head does not remove the object from the map.
+*
+* SEE ALSO
+*	Map, cl_map_tail, cl_map_next, cl_map_prev, cl_map_end
+*********/
+
+/****f* Component Library: Map/cl_map_tail
+* NAME
+*	cl_map_tail
+*
+* DESCRIPTION
+*	The cl_map_tail function returns the map item with the highest key
+*	value stored in a map.
+*
+* SYNOPSIS
+*/
+static inline cl_map_iterator_t cl_map_tail(IN const cl_map_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	return (cl_qmap_tail(&p_map->qmap));
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map whose item with the highest key
+*		is returned.
+*
+* RETURN VALUES
+*	Iterator for the object with the highest key in the map.
+*
+*	Iterator for the map end if the map was empty.
+*
+* NOTES
+*	cl_map_end does no remove the object from the map.
+*
+* SEE ALSO
+*	Map, cl_map_head, cl_map_next, cl_map_prev, cl_map_end
+*********/
+
+/****f* Component Library: Map/cl_map_next
+* NAME
+*	cl_map_next
+*
+* DESCRIPTION
+*	The cl_map_next function returns the map item with the next higher
+*	key value than a specified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_map_iterator_t cl_map_next(IN const cl_map_iterator_t itor)
+{
+	CL_ASSERT(itor);
+	return (cl_qmap_next(itor));
+}
+
+/*
+* PARAMETERS
+*	itor
+*		[in] Iterator for an object in a map whose successor to return.
+*
+* RETURN VALUES
+*	Iterator for the object with the next higher key value in a map.
+*
+*	Iterator for the map end if the specified object was the last item in
+*	the map.
+*
+* NOTES
+*	The iterator must have been retrieved by a previous call to cl_map_head,
+*	cl_map_tail, cl_map_next, or cl_map_prev.
+*
+* SEE ALSO
+*	Map, cl_map_head, cl_map_tail, cl_map_prev, cl_map_end
+*********/
+
+/****f* Component Library: Map/cl_map_prev
+* NAME
+*	cl_map_prev
+*
+* DESCRIPTION
+*	The cl_map_prev function returns the map item with the next lower
+*	key value than a precified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_map_iterator_t cl_map_prev(IN const cl_map_iterator_t itor)
+{
+	CL_ASSERT(itor);
+	return (cl_qmap_prev(itor));
+}
+
+/*
+* PARAMETERS
+*	itor
+*		[in] Iterator for an object in a map whose predecessor to return.
+*
+* RETURN VALUES
+*	Iterator for the object with the next lower key value in a map.
+*
+*	Iterator for the map end if the specified object was the first item in
+*	the map.
+*
+* NOTES
+*	The iterator must have been retrieved by a previous call to cl_map_head,
+*	cl_map_tail, cl_map_next, or cl_map_prev.
+*
+* SEE ALSO
+*	Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_end
+*********/
+
+/****f* Component Library: Map/cl_map_insert
+* NAME
+*	cl_map_insert
+*
+* DESCRIPTION
+*	The cl_map_insert function inserts a map item into a map.
+*
+* SYNOPSIS
+*/
+void *cl_map_insert(IN cl_map_t * const p_map,
+		    IN const uint64_t key, IN const void *const p_object);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map into which to add the item.
+*
+*	key
+*		[in] Value to associate with the object.
+*
+*	p_object
+*		[in] Pointer to an object to insert into the map.
+*
+* RETURN VALUES
+*	Pointer to the object in the map with the specified key after the call
+*	completes.
+*
+*	NULL if there was not enough memory to insert the desired item.
+*
+* NOTES
+*	Insertion operations may cause the map to rebalance.
+*
+*	If the map already contains an object already with the specified key,
+*	that object will not be replaced and the pointer to that object is
+*	returned.
+*
+* SEE ALSO
+*	Map, cl_map_remove, cl_map_item_t
+*********/
+
+/****f* Component Library: Map/cl_map_get
+* NAME
+*	cl_map_get
+*
+* DESCRIPTION
+*	The cl_map_get function returns the object associated with a key.
+*
+* SYNOPSIS
+*/
+void *cl_map_get(IN const cl_map_t * const p_map, IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map from which to retrieve the object with
+*		the specified key.
+*
+*	key
+*		[in] Key value used to search for the desired object.
+*
+* RETURN VALUES
+*	Pointer to the object with the desired key value.
+*
+*	NULL if there was no item with the desired key value stored in
+*	the map.
+*
+* NOTES
+*	cl_map_get does not remove the item from the map.
+*
+* SEE ALSO
+*	Map, cl_map_remove, cl_map_get_next
+*********/
+
+/****f* Component Library: Map/cl_map_get_next
+* NAME
+*	cl_map_get_next
+*
+* DESCRIPTION
+*	The cl_qmap_get_next function returns the first object associated with a
+*	key > the key specified.
+*
+* SYNOPSIS
+*/
+void *cl_map_get_next(IN const cl_map_t * const p_map, IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map from which to retrieve the object with
+*		the specified key.
+*
+*	key
+*		[in] Key value used to search for the desired object.
+*
+* RETURN VALUES
+*	Pointer to the first object with a key > the desired key value.
+*
+*	NULL if there was no item with a key > the desired key
+*	value stored in the map.
+*
+* NOTES
+*	cl_map_get does not remove the item from the map.
+*
+* SEE ALSO
+*	Map, cl_map_remove, cl_map_get
+*********/
+
+/****f* Component Library: Map/cl_map_remove_item
+* NAME
+*	cl_map_remove_item
+*
+* DESCRIPTION
+*	The cl_map_remove_item function removes the specified map item
+*	from a map.
+*
+* SYNOPSIS
+*/
+void
+cl_map_remove_item(IN cl_map_t * const p_map, IN const cl_map_iterator_t itor);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map from which to remove the object associated
+*		with the specified iterator.
+*
+*	itor
+*		[in] Iterator for an object to remove from its map.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Removes the object associated with the specifid iterator from its map.
+*
+*	The specified iterator is no longer valid after the call completes.
+*
+*	The iterator must have been retrieved by a previous call to cl_map_head,
+*	cl_map_tail, cl_map_next, or cl_map_prev.
+*
+* SEE ALSO
+*	Map, cl_map_remove, cl_map_remove_all, cl_map_insert, cl_map_head,
+*	cl_map_tail, cl_map_next, cl_map_prev
+*********/
+
+/****f* Component Library: Map/cl_map_remove
+* NAME
+*	cl_map_remove
+*
+* DESCRIPTION
+*	The cl_map_remove function removes the map item with the specified key
+*	from a map.
+*
+* SYNOPSIS
+*/
+void *cl_map_remove(IN cl_map_t * const p_map, IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_map_t structure from which to remove the
+*		item with the specified key.
+*
+*	key
+*		[in] Key value used to search for the object to remove.
+*
+* RETURN VALUES
+*	Pointer to the object associated with the specified key if
+*	it was found and removed.
+*
+*	NULL if no object with the specified key exists in the map.
+*
+* SEE ALSO
+*	Map, cl_map_remove_item, cl_map_remove_all, cl_map_insert
+*********/
+
+/****f* Component Library: Map/cl_map_remove_all
+* NAME
+*	cl_map_remove_all
+*
+* DESCRIPTION
+*	The cl_map_remove_all function removes all objects from a map,
+*	leaving it empty.
+*
+* SYNOPSIS
+*/
+void cl_map_remove_all(IN cl_map_t * const p_map);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a map to empty.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Map, cl_map_remove, cl_map_remove_item
+*********/
+
+/****f* Component Library: Map/cl_map_obj
+* NAME
+*	cl_map_obj
+*
+* DESCRIPTION
+*	The cl_map_obj function returns the object associated with an iterator.
+*
+* SYNOPSIS
+*/
+static inline void *cl_map_obj(IN const cl_map_iterator_t itor)
+{
+	return (cl_qmap_obj(PARENT_STRUCT(itor, cl_map_obj_t, item)));
+}
+
+/*
+* PARAMETERS
+*	itor
+*		[in] Iterator whose object to return.
+*
+* RETURN VALUES
+*	Returns the value of the object pointer associated with the iterator.
+*
+*	The iterator must have been retrieved by a previous call to cl_map_head,
+*	cl_map_tail, cl_map_next, or cl_map_prev.
+*
+* SEE ALSO
+*	Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev
+*********/
+
+/****f* Component Library: Map/cl_map_merge
+* NAME
+*	cl_map_merge
+*
+* DESCRIPTION
+*	The cl_map_merge function moves all items from one map to another,
+*	excluding duplicates.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_map_merge(OUT cl_map_t * const p_dest_map,
+	     IN OUT cl_map_t * const p_src_map);
+/*
+* PARAMETERS
+*	p_dest_map
+*		[out] Pointer to a cl_map_t structure to which items should be added.
+*
+*	p_src_map
+*		[in/out] Pointer to a cl_map_t structure whose items to add
+*		to p_dest_map.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the operation succeeded.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the operation
+*	to succeed.
+*
+* NOTES
+*	Items are evaluated based on their keys only.
+*
+*	Upon return from cl_map_merge, the map referenced by p_src_map contains
+*	all duplicate items.
+*
+* SEE ALSO
+*	Map, cl_map_delta
+*********/
+
+/****f* Component Library: Map/cl_map_delta
+* NAME
+*	cl_map_delta
+*
+* DESCRIPTION
+*	The cl_map_delta function computes the differences between two maps.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_map_delta(IN OUT cl_map_t * const p_map1,
+	     IN OUT cl_map_t * const p_map2,
+	     OUT cl_map_t * const p_new, OUT cl_map_t * const p_old);
+/*
+* PARAMETERS
+*	p_map1
+*		[in/out] Pointer to the first of two cl_map_t structures whose
+*		differences to compute.
+*
+*	p_map2
+*		[in/out] Pointer to the second of two cl_map_t structures whose
+*		differences to compute.
+*
+*	p_new
+*		[out] Pointer to an empty cl_map_t structure that contains the
+*		items unique to p_map2 upon return from the function.
+*
+*	p_old
+*		[out] Pointer to an empty cl_map_t structure that contains the
+*		items unique to p_map1 upon return from the function.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the operation succeeded.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory for the operation
+*	to succeed.
+*
+* NOTES
+*	Items are evaluated based on their keys.  Items that exist in both
+*	p_map1 and p_map2 remain in their respective maps.  Items that
+*	exist only p_map1 are moved to p_old.  Likewise, items that exist only
+*	in p_map2 are moved to p_new.  This function can be useful in evaluating
+*	changes between two maps.
+*
+*	Both maps pointed to by p_new and p_old must be empty on input.
+*
+*	Upon failure, all input maps are restored to their original state.
+*
+* SEE ALSO
+*	Map, cl_map_merge
+*********/
+
+END_C_DECLS
+#endif				/* _CL_MAP_H_ */
diff --git a/include/complib/cl_math.h b/include/complib/cl_math.h
new file mode 100644
index 0000000..47489bd
--- /dev/null
+++ b/include/complib/cl_math.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Defines standard math related macros and functions.
+ */
+
+#ifndef _CL_MATH_H_
+#define _CL_MATH_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****d* Component Library: Math/MAX
+* NAME
+*	MAX
+*
+* DESCRIPTION
+*	The MAX macro returns the greater of two values.
+*
+* SYNOPSIS
+*	MAX( x, y );
+*
+* PARAMETERS
+*	x
+*		[in] First of two values to compare.
+*
+*	y
+*		[in] Second of two values to compare.
+*
+* RETURN VALUE
+*	Returns the greater of the x and y parameters.
+*
+* SEE ALSO
+*	MIN, ROUNDUP
+*********/
+#ifndef MAX
+#define MAX(x,y)	((x) > (y) ? (x) : (y))
+#endif
+/****d* Component Library: Math/MIN
+* NAME
+*	MIN
+*
+* DESCRIPTION
+*	The MIN macro returns the greater of two values.
+*
+* SYNOPSIS
+*	MIN( x, y );
+*
+* PARAMETERS
+*	x
+*		[in] First of two values to compare.
+*
+*	y
+*		[in] Second of two values to compare.
+*
+* RETURN VALUE
+*	Returns the lesser of the x and y parameters.
+*
+* SEE ALSO
+*	MAX, ROUNDUP
+*********/
+#ifndef MIN
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#endif
+/****d* Component Library: Math/ROUNDUP
+* NAME
+*	ROUNDUP
+*
+* DESCRIPTION
+*	The ROUNDUP macro rounds a value up to a given multiple.
+*
+* SYNOPSIS
+*	ROUNDUP( val, align );
+*
+* PARAMETERS
+*	val
+*		[in] Value that is to be rounded up. The type of the value is
+*		indeterminate, but must be at most the size of a natural integer
+*		for the platform.
+*
+*	align
+*		[in] Multiple to which the val parameter must be rounded up.
+*
+* RETURN VALUE
+*	Returns a value that is the input value specified by val rounded up to
+*	the nearest multiple of align.
+*
+* NOTES
+*	The value provided must be of a type at most the size of a natural integer.
+*********/
+#ifndef ROUNDUP
+#define ROUNDUP(val, align)	\
+	((((val) / (align))*(align)) + (((val) % (align)) ? (align) : 0))
+#endif
+END_C_DECLS
+#endif				/* _CL_MATH_H_ */
diff --git a/include/complib/cl_nodenamemap.h b/include/complib/cl_nodenamemap.h
new file mode 100644
index 0000000..9b2ada4
--- /dev/null
+++ b/include/complib/cl_nodenamemap.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 Lawrence Livermore National Lab
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _CL_NODE_NAME_MAP_H_
+#define _CL_NODE_NAME_MAP_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <complib/cl_qmap.h>
+
+/* NOTE: this may modify the parameter "nodedesc". */
+char *clean_nodedesc(char *nodedesc);
+
+typedef struct _name_map_item {
+	cl_map_item_t item;
+	uint64_t guid;
+	char *name;
+} name_map_item_t;
+
+typedef cl_qmap_t nn_map_t;
+
+/**
+ * Node name map interface.
+ * It is OK to pass NULL for the node_name_map[_fp] parameters.
+ */
+nn_map_t *open_node_name_map(char *node_name_map);
+void  close_node_name_map(nn_map_t *map);
+char *remap_node_name(nn_map_t *map, uint64_t target_guid,
+			char *nodedesc);
+	/* NOTE: parameter "nodedesc" may be modified here. */
+int parse_node_map(const char *file_name,
+		   int (*create)(void *, uint64_t, char *), void *cxt);
+
+#endif				/* _CL_NODE_NAME_MAP_H_ */
diff --git a/include/complib/cl_packoff.h b/include/complib/cl_packoff.h
new file mode 100644
index 0000000..52ee381
--- /dev/null
+++ b/include/complib/cl_packoff.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *  Turns off byte packing, which is necessary for passing information from
+ *	system to system over a network to ensure no padding by the compiler has
+ *	taken place.
+ */
+
+#ifdef PACK_SUFFIX
+#undef PACK_SUFFIX
+#endif
+
+#ifdef _MSC_VER
+#pragma pack (pop)
+#endif
diff --git a/include/complib/cl_packon.h b/include/complib/cl_packon.h
new file mode 100644
index 0000000..ffc8e11
--- /dev/null
+++ b/include/complib/cl_packon.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *  Turns on byte packing, which is necessary for passing information from
+ *	system to system over a network to ensure no padding by the compiler has
+ *	taken place.
+ */
+
+/****h* Component Library/Structure Packing
+* NAME
+*	Structure Packing
+*
+* DESCRIPTION
+*	The structure packing header files allow packing structures on byte
+*	boundaries.
+*
+*	Structure packing should be used whenever a structure is transmitted
+*	between systems, as different platforms pad structures differently if
+*	they are not packed.  Packing a structure that is not transmitted between
+*	systems can be detrimental to performance, as fields in the structure may
+*	not align properly for some platforms. Care must be taken when creating
+*	packed structures that the alignment rules for all platforms are followed.
+*
+*	To pack a structure, include ipackon.h before defining the structure, and
+*	include ipackoff.h after the structure definition.  Multiple structures
+*	can be packed between the two include statements if desired.
+*
+*	The structure definition itself must use the PACK_SUFFIX keyword.
+*
+* EXAMPLE
+*	#include <complib/ipackon.h>
+*
+*	typedef _my_struct_t
+*	{
+*	    uint64 large;
+*	    uint32 medium;
+*	    uint16 small;
+*
+*	} PACK_SUFFIX my_struct_t;
+*	#include <complib/ipackoff.h>
+*********/
+
+#ifndef PACK_SUFFIX
+#define PACK_SUFFIX __attribute__((packed))
+#endif
+
+#ifdef _MSC_VER
+#pragma pack (push, 1)
+#endif
diff --git a/include/complib/cl_passivelock.h b/include/complib/cl_passivelock.h
new file mode 100644
index 0000000..bafd339
--- /dev/null
+++ b/include/complib/cl_passivelock.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	This file contains the passive lock, which synchronizes passive threads.
+ *	The passive lock allows multiple readers to access a resource
+ *	simultaneously, exclusive from a single thread allowed writing.
+ * Several writer threads are allowed - but only one can write at a given time
+ */
+
+#ifndef _CL_PASSIVE_LOCK_H_
+#define _CL_PASSIVE_LOCK_H_
+#include <complib/cl_types.h>
+#include <pthread.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/Passive Lock
+* NAME
+*	Passive Lock
+*
+* DESCRIPTION
+*	The Passive Lock provides synchronization between multiple threads that
+*	are sharing the lock with a single thread holding the lock exclusively.
+*
+*	Passive lock works exclusively between threads and cannot be used in
+*	situations where the caller cannot be put into a waiting state.
+*
+*	The passive lock functions operate a cl_plock_t structure which should
+*	be treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_plock_t
+*
+*	Initialization:
+*		cl_plock_construct, cl_plock_init, cl_plock_destroy
+*
+*	Manipulation
+*		cl_plock_acquire, cl_plock_excl_acquire, cl_plock_release
+*********/
+/****s* Component Library: Passive Lock/cl_plock_t
+* NAME
+*	cl_plock_t
+*
+* DESCRIPTION
+*	Passive Lock structure.
+*
+*	The cl_plock_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_plock {
+	pthread_rwlock_t lock;
+	cl_state_t state;
+} cl_plock_t;
+/*
+* FIELDS
+*	lock
+*		Pthread RWLOCK object
+*
+*	state
+*		Records the current state of the lock, such as initialized,
+*		destroying, etc.
+*
+* SEE ALSO
+*	Passive Lock
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_construct
+* NAME
+*	cl_plock_construct
+*
+* DESCRIPTION
+*	The cl_plock_construct function initializes the state of a
+*	passive lock.
+*
+* SYNOPSIS
+*/
+static inline void cl_plock_construct(IN cl_plock_t * const p_lock)
+{
+	CL_ASSERT(p_lock);
+
+	p_lock->state = CL_UNINITIALIZED;
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_plock_destroy without first calling cl_plock_init.
+*
+*	Calling cl_plock_construct is a prerequisite to calling any other
+*	passive lock function except cl_plock_init.
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_init, cl_plock_destroy
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_destroy
+* NAME
+*	cl_plock_destroy
+*
+* DESCRIPTION
+*	The cl_plock_destroy function performs any necessary cleanup
+*	of a passive lock.
+*
+* SYNOPSIS
+*/
+static inline void cl_plock_destroy(IN cl_plock_t * const p_lock)
+{
+	CL_ASSERT(p_lock);
+	p_lock->state = CL_DESTROYING;
+	pthread_rwlock_destroy(&p_lock->lock);
+	p_lock->state = CL_DESTROYED;
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_plock_destroy performs any necessary cleanup of the specified
+*	passive lock.
+*
+*	This function must only be called if cl_plock_construct or
+*	cl_plock_init has been called. The passive lock must not be held
+*	when calling this function.
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_construct, cl_plock_init
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_init
+* NAME
+*	cl_plock_init
+*
+* DESCRIPTION
+*	The cl_plock_init function initializes a passive lock.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t cl_plock_init(IN cl_plock_t * const p_lock)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_lock);
+	status = (cl_status_t) pthread_rwlock_init(&p_lock->lock, NULL);
+	if (status)
+		return CL_ERROR;
+	p_lock->state = CL_INITIALIZED;
+	return (CL_SUCCESS);
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure to initialize.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the passive lock was initialized successfully.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	Allows calling cl_plock_acquire, cl_plock_release,
+*	cl_plock_excl_acquire
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_construct, cl_plock_destroy,
+*	cl_plock_excl_acquire, cl_plock_acquire, cl_plock_release
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_acquire
+* NAME
+*	cl_plock_acquire
+*
+* DESCRIPTION
+*	The cl_plock_acquire function acquires a passive lock for
+*	shared access.
+*
+* SYNOPSIS
+*/
+static inline void cl_plock_acquire(IN cl_plock_t * const p_lock)
+{
+	cl_status_t status;
+	CL_ASSERT(p_lock);
+	CL_ASSERT(p_lock->state == CL_INITIALIZED);
+
+	status = (cl_status_t) pthread_rwlock_rdlock(&p_lock->lock);
+	CL_ASSERT(status == 0);
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure to acquire.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_release, cl_plock_excl_acquire
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_excl_acquire
+* NAME
+*	cl_plock_excl_acquire
+*
+* DESCRIPTION
+*	The cl_plock_excl_acquire function acquires exclusive access
+*	to a passive lock.
+*
+* SYNOPSIS
+*/
+static inline void cl_plock_excl_acquire(IN cl_plock_t * const p_lock)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_lock);
+	CL_ASSERT(p_lock->state == CL_INITIALIZED);
+
+	status = (cl_status_t) pthread_rwlock_wrlock(&p_lock->lock);
+	CL_ASSERT(status == 0);
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure to acquire exclusively.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_release, cl_plock_acquire
+*********/
+
+/****f* Component Library: Passive Lock/cl_plock_release
+* NAME
+*	cl_plock_release
+*
+* DESCRIPTION
+*	The cl_plock_release function releases a passive lock from
+*	shared or exclusive access.
+*
+* SYNOPSIS
+*/
+static inline void cl_plock_release(IN cl_plock_t * const p_lock)
+{
+	cl_status_t status;
+	CL_ASSERT(p_lock);
+	CL_ASSERT(p_lock->state == CL_INITIALIZED);
+
+	status = (cl_status_t) pthread_rwlock_unlock(&p_lock->lock);
+	CL_ASSERT(status == 0);
+}
+
+/*
+* PARAMETERS
+*	p_lock
+*		[in] Pointer to a cl_plock_t structure to release.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Passive Lock, cl_plock_acquire, cl_plock_excl_acquire
+*********/
+
+END_C_DECLS
+#endif				/* _CL_PASSIVE_LOCK_H_ */
diff --git a/include/complib/cl_pool.h b/include/complib/cl_pool.h
new file mode 100644
index 0000000..f01de96
--- /dev/null
+++ b/include/complib/cl_pool.h
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of the pool.
+ *	The pool manages a pool of objects.
+ *	The pool can grow to meet demand, limited only by system memory.
+ */
+
+#ifndef _CL_POOL_H_
+#define _CL_POOL_H_
+
+#include <complib/cl_qcomppool.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/Pool
+* NAME
+*	Pool
+*
+* DESCRIPTION
+*	The pool provides a self-contained and self-sustaining pool
+*	of user defined objects.
+*
+*	To aid in object oriented design, the pool provides the user
+*	the ability to specify callbacks that are invoked for each object for
+*	construction, initialization, and destruction. Constructor and destructor
+*	callback functions may not fail.
+*
+*	A pool does not return memory to the system as the user returns
+*	objects to the pool. The only method of returning memory to the system is
+*	to destroy the pool.
+*
+*	The Pool functions operate on a cl_pool_t structure which should be treated
+*	as opaque and should be manipulated only through the provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_pool_t
+*
+*	Callbacks:
+*		cl_pfn_pool_init_t, cl_pfn_pool_dtor_t
+*
+*	Initialization/Destruction:
+*		cl_pool_construct, cl_pool_init, cl_pool_destroy
+*
+*	Manipulation:
+*		cl_pool_get, cl_pool_put, cl_pool_grow
+*
+*	Attributes:
+*		cl_is_pool_inited, cl_pool_count
+*********/
+/****d* Component Library: Pool/cl_pfn_pool_init_t
+* NAME
+*	cl_pfn_pool_init_t
+*
+* DESCRIPTION
+*	The cl_pfn_pool_init_t function type defines the prototype for
+*	functions used as initializers for objects being allocated by a
+*	pool.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_pool_init_t) (IN void *const p_object, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object to initialize.
+*
+*	context
+*		[in] Context provided in a call to cl_pool_init.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS to indicates that initialization of the object
+*	was successful and initialization of further objects may continue.
+*
+*	Other cl_status_t values will be returned by cl_pool_init
+*	and cl_pool_grow.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_pool_init function.
+*
+*	The initializer is invoked once per allocated object, allowing the user
+*	to trap initialization failures. Returning a status other than CL_SUCCESS
+*	aborts a grow operation, initiated either through cl_pool_init or
+*	cl_pool_grow, and causes the initiating function to fail.
+*	Any non-CL_SUCCESS status will be returned by the function that initiated
+*	the grow operation.
+*
+* SEE ALSO
+*	Pool, cl_pool_init, cl_pool_grow
+*********/
+
+/****d* Component Library: Pool/cl_pfn_pool_dtor_t
+* NAME
+*	cl_pfn_pool_dtor_t
+*
+* DESCRIPTION
+*	The cl_pfn_pool_dtor_t function type defines the prototype for
+*	functions used as destructor for objects being deallocated by a
+*	pool.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_pool_dtor_t) (IN void *const p_object, IN void *context);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object to destruct.
+*
+*	context
+*		[in] Context provided in the call to cl_pool_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_pool_init function.
+*
+*	The destructor is invoked once per allocated object, allowing the user
+*	to perform any necessary cleanup. Users should not attempt to deallocate
+*	the memory for the object, as the pool manages object
+*	allocation and deallocation.
+*
+* SEE ALSO
+*	Pool, cl_pool_init
+*********/
+
+/****s* Component Library: Pool/cl_pool_t
+* NAME
+*	cl_pool_t
+*
+* DESCRIPTION
+*	pool structure.
+*
+*	The cl_pool_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_pool {
+	cl_qcpool_t qcpool;
+	cl_pfn_pool_init_t pfn_init;
+	cl_pfn_pool_dtor_t pfn_dtor;
+	const void *context;
+} cl_pool_t;
+/*
+* FIELDS
+*	qcpool
+*		Quick composite pool that manages all objects.
+*
+*	pfn_init
+*		Pointer to the user's initializer callback, used by the pool
+*		to translate the quick composite pool's initializer callback to
+*		a pool initializer callback.
+*
+*	pfn_dtor
+*		Pointer to the user's destructor callback, used by the pool
+*		to translate the quick composite pool's destructor callback to
+*		a pool destructor callback.
+*
+*	context
+*		User's provided context for callback functions, used by the pool
+*		to when invoking callbacks.
+*
+* SEE ALSO
+*	Pool
+*********/
+
+/****f* Component Library: Pool/cl_pool_construct
+* NAME
+*	cl_pool_construct
+*
+* DESCRIPTION
+*	The cl_pool_construct function constructs a pool.
+*
+* SYNOPSIS
+*/
+void cl_pool_construct(IN cl_pool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_pool_init, cl_pool_destroy, and cl_is_pool_inited.
+*
+*	Calling cl_pool_construct is a prerequisite to calling any other
+*	pool function except cl_pool_init.
+*
+* SEE ALSO
+*	Pool, cl_pool_init, cl_pool_destroy, cl_is_pool_inited
+*********/
+
+/****f* Component Library: Pool/cl_is_pool_inited
+* NAME
+*	cl_is_pool_inited
+*
+* DESCRIPTION
+*	The cl_is_pool_inited function returns whether a pool was successfully
+*	initialized.
+*
+* SYNOPSIS
+*/
+static inline uint32_t cl_is_pool_inited(IN const cl_pool_t * const p_pool)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_pool);
+	return (cl_is_qcpool_inited(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure whose initialization state
+*		to check.
+*
+* RETURN VALUES
+*	TRUE if the pool was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a pool to determine if invoking member
+*	functions is appropriate.
+*
+* SEE ALSO
+*	Pool
+*********/
+
+/****f* Component Library: Pool/cl_pool_init
+* NAME
+*	cl_pool_init
+*
+* DESCRIPTION
+*	The cl_pool_init function initializes a pool for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_pool_init(IN cl_pool_t * const p_pool,
+	     IN const size_t min_count,
+	     IN const size_t max_count,
+	     IN const size_t grow_size,
+	     IN const size_t object_size,
+	     IN cl_pfn_pool_init_t pfn_initializer OPTIONAL,
+	     IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL,
+	     IN const void *const context);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure to initialize.
+*
+*	min_count
+*		[in] Minimum number of objects that the pool should support. All
+*		necessary allocations to allow storing the minimum number of items
+*		are performed at initialization time, and all necessary callbacks
+*		invoked.
+*
+*	max_count
+*		[in] Maximum number of objects to which the pool is allowed to grow.
+*		A value of zero specifies no maximum.
+*
+*	grow_size
+*		[in] Number of objects to allocate when incrementally growing the pool.
+*		A value of zero disables automatic growth.
+*
+*	object_size
+*		[in] Size, in bytes, of each object.
+*
+*	pfn_initializer
+*		[in] Initialization callback to invoke for every new object when
+*		growing the pool. This parameter is optional and may be NULL.
+*		See the cl_pfn_pool_init_t function type declaration for details
+*		about the callback function.
+*
+*	pfn_destructor
+*		[in] Destructor callback to invoke for every object before memory for
+*		that object is freed. This parameter is optional and may be NULL.
+*		See the cl_pfn_pool_dtor_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the pool was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the
+*	pool.
+*
+*	CL_INVALID_SETTING if a the maximum size is non-zero and less than the
+*	minimum size.
+*
+*	Other cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter.
+*
+* NOTES
+*	cl_pool_init initializes, and if necessary, grows the pool to
+*	the capacity desired.
+*
+* SEE ALSO
+*	Pool, cl_pool_construct, cl_pool_destroy,
+*	cl_pool_get, cl_pool_put, cl_pool_grow,
+*	cl_pool_count, cl_pfn_pool_init_t, cl_pfn_pool_dtor_t
+*********/
+
+/****f* Component Library: Pool/cl_pool_destroy
+* NAME
+*	cl_pool_destroy
+*
+* DESCRIPTION
+*	The cl_pool_destroy function destroys a pool.
+*
+* SYNOPSIS
+*/
+static inline void cl_pool_destroy(IN cl_pool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	cl_qcpool_destroy(&p_pool->qcpool);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	All memory allocated for objects is freed. The destructor callback,
+*	if any, will be invoked for every allocated object. Further operations
+*	on the pool should not be attempted after cl_pool_destroy
+*	is invoked.
+*
+*	This function should only be called after a call to
+*	cl_pool_construct or cl_pool_init.
+*
+*	In a debug build, cl_pool_destroy asserts that all objects are in
+*	the pool.
+*
+* SEE ALSO
+*	Pool, cl_pool_construct, cl_pool_init
+*********/
+
+/****f* Component Library: Pool/cl_pool_count
+* NAME
+*	cl_pool_count
+*
+* DESCRIPTION
+*	The cl_pool_count function returns the number of available objects
+*	in a pool.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_pool_count(IN cl_pool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_count(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure for which the number of
+*		available objects is requested.
+*
+* RETURN VALUE
+*	Returns the number of objects available in the specified pool.
+*
+* SEE ALSO
+*	Pool
+*********/
+
+/****f* Component Library: Pool/cl_pool_get
+* NAME
+*	cl_pool_get
+*
+* DESCRIPTION
+*	The cl_pool_get function retrieves an object from a pool.
+*
+* SYNOPSIS
+*/
+static inline void *cl_pool_get(IN cl_pool_t * const p_pool)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_pool);
+
+	p_pool_obj = (cl_pool_obj_t *) cl_qcpool_get(&p_pool->qcpool);
+	if (!p_pool_obj)
+		return (NULL);
+
+	CL_ASSERT(p_pool_obj->p_object);
+	return ((void *)p_pool_obj->p_object);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure from which to retrieve
+*		an object.
+*
+* RETURN VALUES
+*	Returns a pointer to an object.
+*
+*	Returns NULL if the pool is empty and can not be grown automatically.
+*
+* NOTES
+*	cl_pool_get returns the object at the head of the pool. If the pool is
+*	empty, it is automatically grown to accommodate this request unless the
+*	grow_size parameter passed to the cl_pool_init function was zero.
+*
+* SEE ALSO
+*	Pool, cl_pool_get_tail, cl_pool_put, cl_pool_grow, cl_pool_count
+*********/
+
+/****f* Component Library: Pool/cl_pool_put
+* NAME
+*	cl_pool_put
+*
+* DESCRIPTION
+*	The cl_pool_put function returns an object to a pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_pool_put(IN cl_pool_t * const p_pool, IN void *const p_object)
+{
+	cl_pool_obj_t *p_pool_obj;
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_object);
+
+	/* Calculate the offset to the list object representing this object. */
+	p_pool_obj = (cl_pool_obj_t *)
+	    (((uint8_t *) p_object) - sizeof(cl_pool_obj_t));
+
+	/* good sanity check */
+	CL_ASSERT(p_pool_obj->p_object == p_object);
+
+	cl_qcpool_put(&p_pool->qcpool, &p_pool_obj->pool_item);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure to which to return
+*		an object.
+*
+*	p_object
+*		[in] Pointer to an object to return to the pool.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_pool_put places the returned object at the head of the pool.
+*
+*	The object specified by the p_object parameter must have been
+*	retrieved from the pool by a previous call to cl_pool_get.
+*
+* SEE ALSO
+*	Pool, cl_pool_put_tail, cl_pool_get
+*********/
+
+/****f* Component Library: Pool/cl_pool_grow
+* NAME
+*	cl_pool_grow
+*
+* DESCRIPTION
+*	The cl_pool_grow function grows a pool by
+*	the specified number of objects.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_pool_grow(IN cl_pool_t * const p_pool, IN const size_t obj_count)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_grow(&p_pool->qcpool, obj_count));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_pool_t structure whose capacity to grow.
+*
+*	obj_count
+*		[in] Number of objects by which to grow the pool.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the pool grew successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the
+*	pool.
+*
+*	cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter passed to the
+*	cl_pool_init function.
+*
+* NOTES
+*	It is not necessary to call cl_pool_grow if the pool is
+*	configured to grow automatically.
+*
+* SEE ALSO
+*	Pool
+*********/
+
+END_C_DECLS
+#endif				/* _CL_POOL_H_ */
diff --git a/include/complib/cl_ptr_vector.h b/include/complib/cl_ptr_vector.h
new file mode 100644
index 0000000..d4af0fe
--- /dev/null
+++ b/include/complib/cl_ptr_vector.h
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	This file contains pointer vector definitions.  Pointer Vector provides
+ *  dynmically resizable array functionality.
+ */
+
+#ifndef _CL_PTR_VECTOR_H_
+#define _CL_PTR_VECTOR_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Pointer Vector
+* NAME
+*	Pointer Vector
+*
+* DESCRIPTION
+*	The Pointer Vector is a self-sizing array of pointers. Like a traditonal
+*	array, a pointer vector allows efficient constant time access to elements
+*	with a specified index.  A pointer vector grows transparently as the
+*	user adds elements to the array.
+*
+*	The cl_pointer vector_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_ptr_vector_t
+*
+*	Callbacks:
+*		cl_pfn_ptr_vec_apply_t, cl_pfn_ptr_vec_find_t
+*
+*	Item Manipulation:
+*		cl_ptr_vector_set, cl_ptr_vector_obj
+*
+*	Initialization:
+*		cl_ptr_vector_construct, cl_ptr_vector_init, cl_ptr_vector_destroy
+*
+*	Manipulation:
+*		cl_ptr_vector_get_capacity, cl_ptr_vector_set_capacity,
+*		cl_ptr_vector_get_size, cl_ptr_vector_set_size, cl_ptr_vector_set_min_size
+*		cl_ptr_vector_get_ptr, cl_ptr_vector_get, cl_ptr_vector_at, cl_ptr_vector_set
+*
+*	Search:
+*		cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end
+*		cl_ptr_vector_apply_func
+*********/
+/****d* Component Library: Pointer Vector/cl_pfn_ptr_vec_apply_t
+* NAME
+*	cl_pfn_ptr_vec_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_ptr_vec_apply_t function type defines the prototype for
+*	functions used to iterate elements in a pointer vector.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_ptr_vec_apply_t) (IN const size_t index,
+			    IN void *const element, IN void *context);
+/*
+* PARAMETERS
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[in] Pointer to an element at the specified index in the pointer vector.
+*
+*	context
+*		[in] Context provided in a call to cl_ptr_vector_apply_func.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function passed by users as a parameter to the cl_ptr_vector_apply_func
+*	function.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_apply_func
+*********/
+
+/****d* Component Library: Pointer Vector/cl_pfn_ptr_vec_find_t
+* NAME
+*	cl_pfn_ptr_vec_find_t
+*
+* DESCRIPTION
+*	The cl_pfn_ptr_vec_find_t function type defines the prototype for
+*	functions used to find elements in a pointer vector.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_ptr_vec_find_t) (IN const size_t index,
+			      IN const void *const element, IN void *context);
+/*
+* PARAMETERS
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[in] Pointer to an element at the specified index in the
+*		pointer vector.
+*
+*	context
+*		[in] Context provided in a call to cl_ptr_vector_find_from_start or
+*		cl_ptr_vector_find_from_end.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS if the element was found. This stops pointer vector
+*	iteration.
+*
+*	CL_NOT_FOUND to continue the pointer vector iteration.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the
+*	cl_ptr_vector_find_from_start and cl_ptr_vector_find_from_end functions.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end
+*********/
+
+/****s* Component Library: Pointer Vector/cl_ptr_vector_t
+* NAME
+*	cl_ptr_vector_t
+*
+* DESCRIPTION
+*	Pointer Vector structure.
+*
+*	The cl_ptr_vector_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_ptr_vector {
+	size_t size;
+	size_t grow_size;
+	size_t capacity;
+	const void **p_ptr_array;
+	cl_state_t state;
+} cl_ptr_vector_t;
+/*
+* FIELDS
+*	size
+*		 Number of elements successfully initialized in the pointer vector.
+*
+*	grow_size
+*		 Number of elements to allocate when growing.
+*
+*	capacity
+*		 total # of elements allocated.
+*
+*	alloc_list
+*		 List of allocations.
+*
+*	p_ptr_array
+*		 Internal array of pointers to elements.
+*
+*	state
+*		State of the pointer vector.
+*
+* SEE ALSO
+*	Pointer Vector
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_construct
+* NAME
+*	cl_ptr_vector_construct
+*
+* DESCRIPTION
+*	The cl_ptr_vector_construct function constructs a pointer vector.
+*
+* SYNOPSIS
+*/
+void cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure to construct.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_ptr_vector_destroy without first calling
+*	cl_ptr_vector_init.
+*
+*	Calling cl_ptr_vector_construct is a prerequisite to calling any other
+*	pointer vector function except cl_ptr_vector_init.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_init, cl_ptr_vector_destroy
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_init
+* NAME
+*	cl_ptr_vector_init
+*
+* DESCRIPTION
+*	The cl_ptr_vector_init function initializes a pointer vector for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector,
+		   IN const size_t min_size, IN const size_t grow_size);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure to inititalize.
+*
+*	initial_size
+*		[in] Initial number of elements.
+*
+*	grow_size
+*		[in] Number of elements to allocate when incrementally growing
+*		the pointer vector.  A value of zero disables automatic growth.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the pointer vector was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if the initialization failed.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_construct, cl_ptr_vector_destroy,
+*	cl_ptr_vector_set, cl_ptr_vector_get, cl_ptr_vector_at
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_destroy
+* NAME
+*	cl_ptr_vector_destroy
+*
+* DESCRIPTION
+*	The cl_ptr_vector_destroy function destroys a pointer vector.
+*
+* SYNOPSIS
+*/
+void cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_ptr_vector_destroy frees all memory allocated for the pointer vector.
+*
+*	This function should only be called after a call to cl_ptr_vector_construct
+*	or cl_ptr_vector_init.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_construct, cl_ptr_vector_init
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_get_capacity
+* NAME
+*	cl_ptr_vector_get_capacity
+*
+* DESCRIPTION
+*	The cl_ptr_vector_get_capacity function returns the capacity of
+*	a pointer vector.
+*
+* SYNOPSIS
+*/
+static inline size_t
+cl_ptr_vector_get_capacity(IN const cl_ptr_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	return (p_vector->capacity);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose capacity to return.
+*
+* RETURN VALUE
+*	Capacity, in elements, of the pointer vector.
+*
+* NOTES
+*	The capacity is the number of elements that the pointer vector can store,
+*	and can be greater than the number of elements stored. To get the number
+*	of elements stored in the pointer vector, use cl_ptr_vector_get_size.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_set_capacity, cl_ptr_vector_get_size
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_get_size
+* NAME
+*	cl_ptr_vector_get_size
+*
+* DESCRIPTION
+*	The cl_ptr_vector_get_size function returns the size of a pointer vector.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+cl_ptr_vector_get_size(IN const cl_ptr_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	return ((uint32_t) p_vector->size);
+
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose size to return.
+*
+* RETURN VALUE
+*	Size, in elements, of the pointer vector.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_set_size, cl_ptr_vector_get_capacity
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_get
+* NAME
+*	cl_ptr_vector_get
+*
+* DESCRIPTION
+*	The cl_ptr_vector_get function returns the pointer stored in a
+*	pointer vector at a specified index.
+*
+* SYNOPSIS
+*/
+static inline void *cl_ptr_vector_get(IN const cl_ptr_vector_t * const p_vector,
+				      IN const size_t index)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(p_vector->size > index);
+
+	return ((void *)p_vector->p_ptr_array[index]);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure from which to get an
+*		element.
+*
+*	index
+*		[in] Index of the element.
+*
+* RETURN VALUE
+*	Value of the pointer stored at the specified index.
+*
+* NOTES
+*	cl_ptr_vector_get provides constant access times regardless of the index.
+*
+*	cl_ptr_vector_get does not perform boundary checking. Callers are
+*	responsible for providing an index that is within the range of the pointer
+*	vector.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_at, cl_ptr_vector_set, cl_ptr_vector_get_size
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_at
+* NAME
+*	cl_ptr_vector_at
+*
+* DESCRIPTION
+*	The cl_ptr_vector_at function copies an element stored in a pointer
+*	vector at a specified index, performing boundary checks.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector,
+		 IN const size_t index, OUT void **const p_element);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure from which to get a copy of
+*		an element.
+*
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[out] Pointer to storage for the pointer element. Contains a copy of
+*		the desired pointer upon successful completion of the call.
+*
+* RETURN VALUES
+*	CL_SUCCESS if an element was found at the specified index.
+*
+*	CL_INVALID_SETTING if the index was out of range.
+*
+* NOTES
+*	cl_ptr_vector_at provides constant time access regardless of
+*	the index, and performs boundary checking on the pointer vector.
+*
+*	Upon success, the p_element parameter contains a copy of the
+*	desired element.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_get
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_set
+* NAME
+*	cl_ptr_vector_set
+*
+* DESCRIPTION
+*	The cl_ptr_vector_set function sets the element at the specified index.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector,
+		  IN const size_t index, IN const void *const element);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure into which to store
+*		an element.
+*
+*	index
+*		[in] Index of the element.
+*
+*	element
+*		[in] Pointer to store in the pointer vector.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the element was successfully set.
+*
+*	CL_INSUFFICIENT_MEMORY if the pointer vector could not be resized to
+*	accommodate the new element.
+*
+* NOTES
+*	cl_ptr_vector_set grows the pointer vector as needed to accommodate
+*	the new element, unless the grow_size parameter passed into the
+*	cl_ptr_vector_init function was zero.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_get
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_insert
+* NAME
+*	cl_ptr_vector_insert
+*
+* DESCRIPTION
+*	The cl_ptr_vector_insert function inserts an element into a pointer vector.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_ptr_vector_insert(IN cl_ptr_vector_t * const p_vector,
+		     IN const void *const element,
+		     OUT size_t * const p_index OPTIONAL)
+{
+	cl_status_t status;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	status = cl_ptr_vector_set(p_vector, p_vector->size, element);
+	if (status == CL_SUCCESS && p_index)
+		*p_index = p_vector->size - 1;
+
+	return (status);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure into which to store
+*		an element.
+*
+*	element
+*		[in] Pointer to store in the pointer vector.
+*
+*	p_index
+*		[out] Pointer to the index of the element.  Valid only if
+*		insertion was successful.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the element was successfully inserted.
+*
+*	CL_INSUFFICIENT_MEMORY if the pointer vector could not be resized to
+*	accommodate the new element.
+*
+* NOTES
+*	cl_ptr_vector_insert places the new element at the end of
+*	the pointer vector.
+*
+*	cl_ptr_vector_insert grows the pointer vector as needed to accommodate
+*	the new element, unless the grow_size parameter passed into the
+*	cl_ptr_vector_init function was zero.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_remove, cl_ptr_vector_set
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_remove
+* NAME
+*	cl_ptr_vector_remove
+*
+* DESCRIPTION
+*	The cl_ptr_vector_remove function removes and returns the pointer stored
+*	in a pointer vector at a specified index.  Items beyond the removed item
+*	are shifted down and the size of the pointer vector is decremented.
+*
+* SYNOPSIS
+*/
+void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t index);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure from which to get an
+*		element.
+*
+*	index
+*		[in] Index of the element.
+*
+* RETURN VALUE
+*	Value of the pointer stored at the specified index.
+*
+* NOTES
+*	cl_ptr_vector_get does not perform boundary checking. Callers are
+*	responsible for providing an index that is within the range of the pointer
+*	vector.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_insert, cl_ptr_vector_get_size
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_set_capacity
+* NAME
+*	cl_ptr_vector_set_capacity
+*
+* DESCRIPTION
+*	The cl_ptr_vector_set_capacity function reserves memory in a
+*	pointer vector for a specified number of pointers.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t new_capacity);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose capacity to set.
+*
+*	new_capacity
+*		[in] Total number of elements for which the pointer vector should
+*		allocate memory.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the capacity was successfully set.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to satisfy the
+*	operation. The pointer vector is left unchanged.
+*
+* NOTES
+*	cl_ptr_vector_set_capacity increases the capacity of the pointer vector.
+*	It does not change the size of the pointer vector. If the requested
+*	capacity is less than the current capacity, the pointer vector is left
+*	unchanged.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_get_capacity, cl_ptr_vector_set_size,
+*	cl_ptr_vector_set_min_size
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_set_size
+* NAME
+*	cl_ptr_vector_set_size
+*
+* DESCRIPTION
+*	The cl_ptr_vector_set_size function resizes a pointer vector, either
+*	increasing or decreasing its size.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector,
+		       IN const size_t size);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose size to set.
+*
+*	size
+*		[in] Number of elements desired in the pointer vector.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the size of the pointer vector was set successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to complete the
+*	operation. The pointer vector is left unchanged.
+*
+* NOTES
+*	cl_ptr_vector_set_size sets the pointer vector to the specified size.
+*	If size is smaller than the current size of the pointer vector, the size
+*	is reduced.
+*
+*	This function can only fail if size is larger than the current capacity.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_get_size, cl_ptr_vector_set_min_size,
+*	cl_ptr_vector_set_capacity
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_set_min_size
+* NAME
+*	cl_ptr_vector_set_min_size
+*
+* DESCRIPTION
+*	The cl_ptr_vector_set_min_size function resizes a pointer vector to a
+*	specified size if the pointer vector is smaller than the specified size.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector,
+			   IN const size_t min_size);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose minimum size to set.
+*
+*	min_size
+*		[in] Minimum number of elements that the pointer vector should contain.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the pointer vector size is greater than or equal to min_size.
+*	This could indicate that the pointer vector's capacity was increased to
+*	min_size or that the pointer vector was already of sufficient size.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to resize the
+*	pointer vector.  The pointer vector is left unchanged.
+*
+* NOTES
+*	If min_size is smaller than the current size of the pointer vector,
+*	the pointer vector is unchanged. The pointer vector is unchanged if the
+*	size could not be changed due to insufficient memory being available to
+*	perform the operation.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_get_size, cl_ptr_vector_set_size,
+*	cl_ptr_vector_set_capacity
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_apply_func
+* NAME
+*	cl_ptr_vector_apply_func
+*
+* DESCRIPTION
+*	The cl_ptr_vector_apply_func function invokes a specified function for
+*	every element in a pointer vector.
+*
+* SYNOPSIS
+*/
+void
+cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector,
+			 IN cl_pfn_ptr_vec_apply_t pfn_callback,
+			 IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure whose elements to iterate.
+*
+*	pfn_callback
+*		[in] Function invoked for every element in the array.
+*		See the cl_pfn_ptr_vec_apply_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_ptr_vector_apply_func invokes the specified function for every element
+*	in the pointer vector, starting from the beginning of the pointer vector.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end,
+*	cl_pfn_ptr_vec_apply_t
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_find_from_start
+* NAME
+*	cl_ptr_vector_find_from_start
+*
+* DESCRIPTION
+*	The cl_ptr_vector_find_from_start function uses a specified function to
+*	search for elements in a pointer vector starting from the lowest index.
+*
+* SYNOPSIS
+*/
+size_t
+cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector,
+			      IN cl_pfn_ptr_vec_find_t pfn_callback,
+			      IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure to inititalize.
+*
+*	pfn_callback
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_ptr_vec_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUES
+*	Index of the element, if found.
+*
+*	Size of the pointer vector if the element was not found.
+*
+* NOTES
+*	cl_ptr_vector_find_from_start does not remove the found element from
+*	the pointer vector. The index of the element is returned when the function
+*	provided by the pfn_callback parameter returns CL_SUCCESS.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_find_from_end, cl_ptr_vector_apply_func,
+*	cl_pfn_ptr_vec_find_t
+*********/
+
+/****f* Component Library: Pointer Vector/cl_ptr_vector_find_from_end
+* NAME
+*	cl_ptr_vector_find_from_end
+*
+* DESCRIPTION
+*	The cl_ptr_vector_find_from_end function uses a specified function to
+*	search for elements in a pointer vector starting from the highest index.
+*
+* SYNOPSIS
+*/
+size_t
+cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector,
+			    IN cl_pfn_ptr_vec_find_t pfn_callback,
+			    IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_ptr_vector_t structure to inititalize.
+*
+*	pfn_callback
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_ptr_vec_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUES
+*	Index of the element, if found.
+*
+*	Size of the pointer vector if the element was not found.
+*
+* NOTES
+*	cl_ptr_vector_find_from_end does not remove the found element from
+*	the pointer vector. The index of the element is returned when the function
+*	provided by the pfn_callback parameter returns CL_SUCCESS.
+*
+* SEE ALSO
+*	Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_apply_func,
+*	cl_pfn_ptr_vec_find_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_PTR_VECTOR_H_ */
diff --git a/include/complib/cl_qcomppool.h b/include/complib/cl_qcomppool.h
new file mode 100644
index 0000000..58862e3
--- /dev/null
+++ b/include/complib/cl_qcomppool.h
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of the quick composite pool.  The quick composite pool
+ *	manages a pool of composite objects.  A composite object is an object
+ *	that is made of multiple sub objects.
+ *	It can grow to meet demand, limited only by system memory.
+ */
+
+#ifndef _CL_QUICK_COMPOSITE_POOL_H_
+#define _CL_QUICK_COMPOSITE_POOL_H_
+
+#include <complib/cl_types.h>
+#include <complib/cl_qlist.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/Quick Composite Pool
+* NAME
+*	Quick Composite Pool
+*
+* DESCRIPTION
+*	The Quick Composite Pool provides a self-contained and self-sustaining
+*	pool of user defined composite objects.
+*
+*	A composite object is an object that is composed of one or more
+*	sub-objects, each of which needs to be treated separately for
+*	initialization. Objects can be retrieved from the pool as long as there
+*	is memory in the system.
+*
+*	To aid in object oriented design, the Quick Composite Pool provides users
+*	the ability to specify callbacks that are invoked for each object for
+*	construction, initialization, and destruction. Constructor and destructor
+*	callback functions may not fail.
+*
+*	A Quick Composite Pool does not return memory to the system as the user
+*	returns objects to the pool. The only method of returning memory to the
+*	system is to destroy the pool.
+*
+*	The Quick Composite Pool operates on cl_pool_item_t structures that
+*	describe composite objects. This provides for more efficient memory use.
+*	If using a cl_pool_item_t is not desired, the Composite Pool provides
+*	similar functionality but operates on opaque objects.
+*
+*	The Quick Composit Pool functions operate on a cl_qcpool_t structure
+*	which should be treated as opaque and should be manipulated only through
+*	the provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_qcpool_t, cl_pool_item_t
+*
+*	Callbacks:
+*		cl_pfn_qcpool_init_t, cl_pfn_qcpool_dtor_t
+*
+*	Initialization/Destruction:
+*		cl_qcpool_construct, cl_qcpool_init, cl_qcpool_destroy
+*
+*	Manipulation:
+*		cl_qcpool_get, cl_qcpool_put, cl_qcpool_put_list, cl_qcpool_grow
+*
+*	Attributes:
+*		cl_is_qcpool_inited, cl_qcpool_count
+*********/
+/****s* Component Library: Quick Composite Pool/cl_pool_item_t
+* NAME
+*	cl_pool_item_t
+*
+* DESCRIPTION
+*	The cl_pool_item_t structure is used by pools to store objects.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_pool_item {
+	cl_list_item_t list_item;
+#ifdef _DEBUG_
+	/* Pointer to the owner pool used for sanity checks. */
+	struct _cl_qcpool *p_pool;
+#endif
+} cl_pool_item_t;
+/*
+* FIELDS
+*	list_item
+*		Used internally by the pool. Users should not use this field.
+*
+*	p_pool
+*		Used internally by the pool in debug builds to check for consistency.
+*
+* NOTES
+*	The pool item structure is defined in such a way as to safely allow
+*	users to cast from a pool item to a list item for storing items
+*	retrieved from a quick pool in a quick list.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_list_item_t
+*********/
+
+/****i* Component Library: Quick List/cl_pool_obj_t
+* NAME
+*	cl_pool_obj_t
+*
+* DESCRIPTION
+*	The cl_pool_obj_t structure is used by pools to store objects.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_pool_obj {
+	/* The pool item must be the first item to allow casting. */
+	cl_pool_item_t pool_item;
+	const void *p_object;
+} cl_pool_obj_t;
+/*
+* FIELDS
+*	pool_item
+*		Used internally by the pool. Users should not use this field.
+*
+*	p_object
+*		Pointer to the user's object being stored in the pool.
+*
+* NOTES
+*	The pool object structure is used by non-quick pools to store object.
+*
+* SEE ALSO
+*	cl_pool_item_t
+*********/
+
+/****d* Component Library: Quick Composite Pool/cl_pfn_qcpool_init_t
+* NAME
+*	cl_pfn_qcpool_init_t
+*
+* DESCRIPTION
+*	The cl_pfn_qcpool_init_t function type defines the prototype for
+*	functions used as initializer for objects being allocated by a
+*	quick composite pool.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_qcpool_init_t) (IN void **const p_comp_array,
+			     IN const uint32_t num_components,
+			     IN void *context,
+			     OUT cl_pool_item_t ** const pp_pool_item);
+/*
+* PARAMETERS
+*	p_comp_array
+*		[in] Pointer to the first entry in an array of pointers, each of
+*		which points to a component that makes up a composite object.
+*
+*	num_components
+*		[in] Number of components that in the component array.
+*
+*	context
+*		[in] Context provided in a call to cl_qcpool_init.
+*
+*	pp_pool_item
+*		[out] Users should set this pointer to reference the cl_pool_item_t
+*		structure that represents the composite object.  This pointer must
+*		not be NULL if the function returns CL_SUCCESS.
+*
+* RETURN VALUE
+*	Return CL_SUCCESS to indicate that initialization of the object
+*	was successful and that initialization of further objects may continue.
+*
+*	Other cl_status_t values will be returned by cl_qcpool_init
+*	and cl_qcpool_grow.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as a parameter to the
+*	cl_qcpool_init function.
+*
+*	The initializer is invoked once per allocated object, allowing the user
+*	to chain components to form a composite object and perform any necessary
+*	initialization.  Returning a status other than CL_SUCCESS aborts a grow
+*	operation, initiated either through cl_qcpool_init or cl_qcpool_grow,
+*	and causes the initiating function to fail.  Any non-CL_SUCCESS status
+*	will be returned by the function that initiated the grow operation.
+*
+*	All memory for the requested number of components is pre-allocated.  Users
+*	should include space in one of their components for the cl_pool_item_t
+*	structure that will represent the composite object to avoid having to
+*	allocate that structure in the initialization callback.  Alternatively,
+*	users may specify an additional component for the cl_pool_item_t structure.
+*
+*	When later performing a cl_qcpool_get call, the return value is a pointer
+*	to the cl_pool_item_t returned by this function in the pp_pool_item
+*	parameter. Users must set pp_pool_item to a valid pointer to the
+*	cl_pool_item_t representing the object if they return CL_SUCCESS.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_init
+*********/
+
+/****d* Component Library: Quick Composite Pool/cl_pfn_qcpool_dtor_t
+* NAME
+*	cl_pfn_qcpool_dtor_t
+*
+* DESCRIPTION
+*	The cl_pfn_qcpool_dtor_t function type defines the prototype for
+*	functions used as destructor for objects being deallocated by a
+*	quick composite pool.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_qcpool_dtor_t) (IN const cl_pool_item_t * const p_pool_item,
+			  IN void *context);
+/*
+* PARAMETERS
+*	p_pool_item
+*		[in] Pointer to a cl_pool_item_t structure representing an object.
+*
+*	context
+*		[in] Context provided in a call to cl_qcpool_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_qcpool_init function.
+*
+*	The destructor is invoked once per allocated object, allowing the user
+*	to perform any necessary cleanup. Users should not attempt to deallocate
+*	the memory for the composite object, as the quick composite pool manages
+*	object allocation and deallocation.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_init
+*********/
+
+/****s* Component Library: Quick Composite Pool/cl_qcpool_t
+* NAME
+*	cl_qcpool_t
+*
+* DESCRIPTION
+*	Quick composite pool structure.
+*
+*	The cl_qcpool_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_qcpool {
+	uint32_t num_components;
+	size_t *component_sizes;
+	void **p_components;
+	size_t num_objects;
+	size_t max_objects;
+	size_t grow_size;
+	cl_pfn_qcpool_init_t pfn_init;
+	cl_pfn_qcpool_dtor_t pfn_dtor;
+	const void *context;
+	cl_qlist_t free_list;
+	cl_qlist_t alloc_list;
+	cl_state_t state;
+} cl_qcpool_t;
+/*
+* FIELDS
+*	num_components
+*		Number of components per object.
+*
+*	component_sizes
+*		Array of sizes, one for each component.
+*
+*	p_components
+*		Array of pointers to components, used for the constructor callback.
+*
+*	num_objects
+*		Number of objects managed by the pool
+*
+*	grow_size
+*		Number of objects to add when automatically growing the pool.
+*
+*	pfn_init
+*		Pointer to the user's initializer callback to invoke when initializing
+*		new objects.
+*
+*	pfn_dtor
+*		Pointer to the user's destructor callback to invoke before deallocating
+*		memory allocated for objects.
+*
+*	context
+*		User's provided context for callback functions, used by the pool
+*		when invoking callbacks.
+*
+*	free_list
+*		Quick list of objects available.
+*
+*	alloc_list
+*		Quick list used to store information about allocations.
+*
+*	state
+*		State of the pool.
+*
+* SEE ALSO
+*	Quick Composite Pool
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_construct
+* NAME
+*	cl_qcpool_construct
+*
+* DESCRIPTION
+*	The cl_qcpool_construct function constructs a quick composite pool.
+*
+* SYNOPSIS
+*/
+void cl_qcpool_construct(IN cl_qcpool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_qcpool_init, cl_qcpool_destroy, cl_is_qcpool_inited.
+*
+*	Calling cl_qcpool_construct is a prerequisite to calling any other
+*	quick composite pool function except cl_qcpool_init.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_init, cl_qcpool_destroy,
+*	cl_is_qcpool_inited
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_is_qcpool_inited
+* NAME
+*	cl_is_qcpool_inited
+*
+* DESCRIPTION
+*	The cl_is_qcpool_inited function returns whether a quick composite pool was
+*	successfully initialized.
+*
+* SYNOPSIS
+*/
+static inline uint32_t cl_is_qcpool_inited(IN const cl_qcpool_t * const p_pool)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_pool);
+	/* CL_ASSERT that the pool is not in some invalid state. */
+	CL_ASSERT(cl_is_state_valid(p_pool->state));
+
+	return (p_pool->state == CL_INITIALIZED);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure to check.
+*
+* RETURN VALUES
+*	TRUE if the quick composite pool was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a quick composite pool to determine if
+*	invoking member functions is appropriate.
+*
+* SEE ALSO
+*	Quick Composite Pool
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_init
+* NAME
+*	cl_qcpool_init
+*
+* DESCRIPTION
+*	The cl_qcpool_init function initializes a quick composite pool for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_qcpool_init(IN cl_qcpool_t * const p_pool,
+	       IN const size_t min_size,
+	       IN const size_t max_size,
+	       IN const size_t grow_size,
+	       IN const size_t * const component_sizes,
+	       IN const uint32_t num_components,
+	       IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL,
+	       IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL,
+	       IN const void *const context);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure to initialize.
+*
+*	min_size
+*		[in] Minimum number of objects that the pool should support. All
+*		necessary allocations to allow storing the minimum number of items
+*		are performed at initialization time, and all necessary callbacks
+*		successfully invoked.
+*
+*	max_size
+*		[in] Maximum number of objects to which the pool is allowed to grow.
+*		A value of zero specifies no maximum.
+*
+*	grow_size
+*		[in] Number of objects to allocate when incrementally growing the pool.
+*		A value of zero disables automatic growth.
+*
+*	component_sizes
+*		[in] Pointer to the first entry in an array of sizes describing,
+*		in order, the sizes of the components that make up a composite object.
+*
+*	num_components
+*		[in] Number of components that make up a composite object.
+*
+*	pfn_initializer
+*		[in] Initializer callback to invoke for every new object when growing
+*		the pool. This parameter may be NULL only if the objects stored in
+*		the quick composite pool consist of only one component. If NULL, the
+*		pool assumes the cl_pool_item_t structure describing objects is
+*		located at the head of each object. See the cl_pfn_qcpool_init_t
+*		function type declaration for details about the callback function.
+*
+*	pfn_destructor
+*		[in] Destructor callback to invoke for every object before memory for
+*		that object is freed. This parameter is optional and may be NULL.
+*		See the cl_pfn_qcpool_dtor_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the quick composite pool was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the
+*	quick composite pool.
+*
+*	CL_INVALID_SETTING if a NULL constructor was provided for composite objects
+*	consisting of more than one component.  Also returns CL_INVALID_SETTING if
+*	the maximum size is non-zero and less than the minimum size.
+*
+*	Other cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter.
+*
+*	If initialization fails, the pool is left in a destroyed state.  Callers
+*	may still safely call cl_qcpool_destroy.
+*
+* NOTES
+*	cl_qcpool_init initializes, and if necessary, grows the pool to
+*	the capacity desired.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_construct, cl_qcpool_destroy,
+*	cl_qcpool_get, cl_qcpool_put, cl_qcpool_grow,
+*	cl_qcpool_count, cl_pfn_qcpool_init_t, cl_pfn_qcpool_dtor_t
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_destroy
+* NAME
+*	cl_qcpool_destroy
+*
+* DESCRIPTION
+*	The cl_qcpool_destroy function destroys a quick composite pool.
+*
+* SYNOPSIS
+*/
+void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	All memory allocated for composite objects is freed. The destructor
+*	callback, if any, will be invoked for every allocated object. Further
+*	operations on the composite pool should not be attempted after
+*	cl_qcpool_destroy is invoked.
+*
+*	This function should only be called after a call to
+*	cl_qcpool_construct or cl_qcpool_init.
+*
+*	In a debug build, cl_qcpool_destroy asserts that all objects are in
+*	the pool.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_construct, cl_qcpool_init
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_count
+* NAME
+*	cl_qcpool_count
+*
+* DESCRIPTION
+*	The cl_qcpool_count function returns the number of available objects
+*	in a quick composite pool.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_qcpool_count(IN cl_qcpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+
+	return (cl_qlist_count(&p_pool->free_list));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure for which the number of
+*		available objects is requested.
+*
+* RETURN VALUE
+*	Returns the number of objects available in the specified
+*	quick composite pool.
+*
+* SEE ALSO
+*	Quick Composite Pool
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_get
+* NAME
+*	cl_qcpool_get
+*
+* DESCRIPTION
+*	The cl_qcpool_get function retrieves an object from a
+*	quick composite pool.
+*
+* SYNOPSIS
+*/
+cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure from which to retrieve
+*		an object.
+*
+* RETURN VALUES
+*	Returns a pointer to a cl_pool_item_t for a composite object.
+*
+*	Returns NULL if the pool is empty and can not be grown automatically.
+*
+* NOTES
+*	cl_qcpool_get returns the object at the head of the pool. If the pool is
+*	empty, it is automatically grown to accommodate this request unless the
+*	grow_size parameter passed to the cl_qcpool_init function was zero.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_get_tail, cl_qcpool_put,
+*	cl_qcpool_grow, cl_qcpool_count
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_put
+* NAME
+*	cl_qcpool_put
+*
+* DESCRIPTION
+*	The cl_qcpool_put function returns an object to a quick composite pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qcpool_put(IN cl_qcpool_t * const p_pool,
+	      IN cl_pool_item_t * const p_pool_item)
+{
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+	CL_ASSERT(p_pool_item);
+	/* Make sure items being returned came from the specified pool. */
+	CL_ASSERT(p_pool_item->p_pool == p_pool);
+
+	/* return this lil' doggy to the pool */
+	cl_qlist_insert_head(&p_pool->free_list, &p_pool_item->list_item);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure to which to return
+*		an object.
+*
+*	p_pool_item
+*		[in] Pointer to a cl_pool_item_t structure for the object
+*		being returned.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_qcpool_put places the returned object at the head of the pool.
+*
+*	The object specified by the p_pool_item parameter must have been
+*	retrieved from the pool by a previous call to cl_qcpool_get.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_put_tail, cl_qcpool_get
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_put_list
+* NAME
+*	cl_qcpool_put_list
+*
+* DESCRIPTION
+*	The cl_qcpool_put_list function returns a list of objects to the head of
+*	a quick composite pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qcpool_put_list(IN cl_qcpool_t * const p_pool, IN cl_qlist_t * const p_list)
+{
+#ifdef _DEBUG_
+	cl_list_item_t *p_item;
+#endif
+
+	CL_ASSERT(p_pool);
+	CL_ASSERT(p_pool->state == CL_INITIALIZED);
+	CL_ASSERT(p_list);
+
+#ifdef _DEBUG_
+	/* Chech that all items in the list came from this pool. */
+	p_item = cl_qlist_head(p_list);
+	while (p_item != cl_qlist_end(p_list)) {
+		CL_ASSERT(((cl_pool_item_t *) p_item)->p_pool == p_pool);
+		p_item = cl_qlist_next(p_item);
+	}
+#endif
+
+	/* return these lil' doggies to the pool */
+	cl_qlist_insert_list_head(&p_pool->free_list, p_list);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure to which to return
+*		a list of objects.
+*
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure for the list of objects
+*		being returned.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_qcpool_put_list places the returned objects at the head of the pool.
+*
+*	The objects in the list specified by the p_list parameter must have been
+*	retrieved from the pool by a previous call to cl_qcpool_get.
+*
+* SEE ALSO
+*	Quick Composite Pool, cl_qcpool_put, cl_qcpool_put_tail, cl_qcpool_get
+*********/
+
+/****f* Component Library: Quick Composite Pool/cl_qcpool_grow
+* NAME
+*	cl_qcpool_grow
+*
+* DESCRIPTION
+*	The cl_qcpool_grow function grows a quick composite pool by
+*	the specified number of objects.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qcpool_t structure whose capacity to grow.
+*
+*	obj_count
+*		[in] Number of objects by which to grow the pool.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the quick composite pool grew successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the
+*	quick composite pool.
+*
+*	cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter passed to the
+*	cl_qcpool_init function.
+*
+* NOTES
+*	It is not necessary to call cl_qcpool_grow if the pool is
+*	configured to grow automatically.
+*
+* SEE ALSO
+*	Quick Composite Pool
+*********/
+
+END_C_DECLS
+#endif				/* _CL_QUICK_COMPOSITE_POOL_H_ */
diff --git a/include/complib/cl_qlist.h b/include/complib/cl_qlist.h
new file mode 100644
index 0000000..accbd98
--- /dev/null
+++ b/include/complib/cl_qlist.h
@@ -0,0 +1,1702 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of quick list.
+ */
+
+#ifndef _CL_QUICK_LIST_H_
+#define _CL_QUICK_LIST_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Quick List
+* NAME
+*	Quick List
+*
+* DESCRIPTION
+*	Quick list implements a doubly linked that stores user provided
+*	cl_list_item_t structures.
+*	Quick list does not allocate any memory, and can therefore not fail any
+*	operations.  Quick list can therefore be useful in minimizing the error
+*	paths in code.
+*
+*	Quick list is not thread safe, and users must provide serialization when
+*	adding and removing items from the list. Note that it is possible to
+*	walk a quick list while simultaneously adding to it.
+*
+*	The Quick List functions operate on a cl_qlist_t structure which should be
+*	treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_qlist_t, cl_list_item_t, cl_list_obj_t
+*
+*	Callbacks:
+*		cl_pfn_qlist_apply_t, cl_pfn_qlist_find_t
+*
+*	Item Manipulation:
+*		cl_qlist_set_obj, cl_qlist_obj
+*
+*	Initialization:
+*		cl_qlist_init
+*
+*	Iteration:
+*		cl_qlist_next, cl_qlist_prev, cl_qlist_head, cl_qlist_tail,
+*		cl_qlist_end
+*
+*	Manipulation:
+*		cl_qlist_insert_head, cl_qlist_insert_tail,
+*		cl_qlist_insert_list_head, cl_qlist_insert_list_tail,
+*		cl_qlist_insert_array_head, cl_qlist_insert_array_tail,
+*		cl_qlist_insert_prev, cl_qlist_insert_next,
+*		cl_qlist_remove_head, cl_qlist_remove_tail,
+*		cl_qlist_remove_item, cl_qlist_remove_all
+*
+*	Search:
+*		cl_is_item_in_qlist, cl_qlist_find_next, cl_qlist_find_prev,
+*		cl_qlist_find_from_head, cl_qlist_find_from_tail
+*		cl_qlist_apply_func, cl_qlist_move_items
+*
+*	Attributes:
+*		cl_qlist_count, cl_is_qlist_empty
+*********/
+/****s* Component Library: Quick List/cl_list_item_t
+* NAME
+*	cl_list_item_t
+*
+* DESCRIPTION
+*	The cl_list_item_t structure is used by lists to store objects.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_list_item {
+	struct _cl_list_item *p_next;
+	struct _cl_list_item *p_prev;
+#ifdef _DEBUG_
+	struct _cl_qlist *p_list;
+#endif
+} cl_list_item_t;
+/*
+* FIELDS
+*	p_next
+*		Used internally by the list. Users should not use this field.
+*
+*	p_prev
+*		Used internally by the list. Users should not use this field.
+*
+* SEE ALSO
+*	Quick List
+*********/
+
+#define cl_item_obj(item_ptr, obj_ptr, item_field) (typeof(obj_ptr)) \
+	((void *)item_ptr - (unsigned long)&((typeof(obj_ptr))0)->item_field)
+
+
+/****s* Component Library: Quick List/cl_list_obj_t
+* NAME
+*	cl_list_obj_t
+*
+* DESCRIPTION
+*	The cl_list_obj_t structure is used by lists to store objects.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_list_obj {
+	cl_list_item_t list_item;
+	const void *p_object;	/* User's context */
+} cl_list_obj_t;
+/*
+* FIELDS
+*	list_item
+*		Used internally by the list. Users should not use this field.
+*
+*	p_object
+*		User defined context. Users should not access this field directly.
+*		Use cl_qlist_set_obj and cl_qlist_obj to set and retrieve the value
+*		of this field.
+*
+* NOTES
+*	Users can use the cl_qlist_set_obj and cl_qlist_obj functions to store
+*	and retrieve context information in the list item.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_set_obj, cl_qlist_obj, cl_list_item_t
+*********/
+
+/****s* Component Library: Quick List/cl_qlist_t
+* NAME
+*	cl_qlist_t
+*
+* DESCRIPTION
+*	Quick list structure.
+*
+*	The cl_qlist_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_qlist {
+	cl_list_item_t end;
+	size_t count;
+	cl_state_t state;
+} cl_qlist_t;
+/*
+* FIELDS
+*	end
+*		List item used to mark the end of the list.
+*
+*	count
+*		Number of items in the list.
+*
+*	state
+*		State of the quick list.
+*
+* SEE ALSO
+*	Quick List
+*********/
+
+/****d* Component Library: Quick List/cl_pfn_qlist_apply_t
+* NAME
+*	cl_pfn_qlist_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_qlist_apply_t function type defines the prototype for functions
+*	used to iterate items in a quick list.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_qlist_apply_t) (IN cl_list_item_t * const p_list_item,
+			  IN void *context);
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure.
+*
+*	context
+*		[in] Value passed to the callback function.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_qlist_apply_func
+*	function.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_apply_func
+*********/
+
+/****d* Component Library: Quick List/cl_pfn_qlist_find_t
+* NAME
+*	cl_pfn_qlist_find_t
+*
+* DESCRIPTION
+*	The cl_pfn_qlist_find_t function type defines the prototype for functions
+*	used to find items in a quick list.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_qlist_find_t) (IN const cl_list_item_t * const p_list_item,
+			    IN void *context);
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t.
+*
+*	context
+*		[in] Value passed to the callback function.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS if the desired item was found. This stops list iteration.
+*
+*	Return CL_NOT_FOUND to continue list iteration.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_qlist_find_from_head,
+*	cl_qlist_find_from_tail, cl_qlist_find_next, and cl_qlist_find_prev
+*	functions.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail,
+*	cl_qlist_find_next, cl_qlist_find_prev
+*********/
+
+/****i* Component Library: Quick List/__cl_primitive_insert
+* NAME
+*	__cl_primitive_insert
+*
+* DESCRIPTION
+*	Add a new item in front of the specified item.  This is a low level
+*	function for use internally by the queuing routines.
+*
+* SYNOPSIS
+*/
+static inline void
+__cl_primitive_insert(IN cl_list_item_t * const p_list_item,
+		      IN cl_list_item_t * const p_new_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_new_item);
+
+	p_new_item->p_next = p_list_item;
+	p_new_item->p_prev = p_list_item->p_prev;
+	p_list_item->p_prev = p_new_item;
+	p_new_item->p_prev->p_next = p_new_item;
+}
+
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to cl_list_item_t to insert in front of
+*
+*	p_new_item
+*		[in] Pointer to cl_list_item_t to add
+*
+* RETURN VALUE
+*	This function does not return a value.
+*********/
+
+/****i* Component Library: Quick List/__cl_primitive_remove
+* NAME
+*	__cl_primitive_remove
+*
+* DESCRIPTION
+*	Remove an item from a list.  This is a low level routine
+*	for use internally by the queuing routines.
+*
+* SYNOPSIS
+*/
+static inline void __cl_primitive_remove(IN cl_list_item_t * const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+
+	/* set the back pointer */
+	p_list_item->p_next->p_prev = p_list_item->p_prev;
+	/* set the next pointer */
+	p_list_item->p_prev->p_next = p_list_item->p_next;
+
+	/* if we're debugging, spruce up the pointers to help find bugs */
+#if defined( _DEBUG_ )
+	if (p_list_item != p_list_item->p_next) {
+		p_list_item->p_next = NULL;
+		p_list_item->p_prev = NULL;
+	}
+#endif				/* defined( _DEBUG_ ) */
+}
+
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to cl_list_item_t to remove
+*
+* RETURN VALUE
+*	This function does not return a value.
+*********/
+
+/*
+ * Declaration of quick list functions
+ */
+
+/****f* Component Library: Quick List/cl_qlist_set_obj
+* NAME
+*	cl_qlist_set_obj
+*
+* DESCRIPTION
+*	The cl_qlist_set_obj function sets the object stored in a list object.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_set_obj(IN cl_list_obj_t * const p_list_obj,
+		 IN const void *const p_object)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_obj);
+	p_list_obj->p_object = p_object;
+}
+
+/*
+* PARAMETERS
+*	p_list_obj
+*		[in] Pointer to a cl_list_obj_t structure.
+*
+*	p_object
+*		[in] User defined context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_obj
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_obj
+* NAME
+*	cl_qlist_obj
+*
+* DESCRIPTION
+*	The cl_qlist_set_obj function returns the object stored in a list object.
+*
+* SYNOPSIS
+*/
+static inline void *cl_qlist_obj(IN const cl_list_obj_t * const p_list_obj)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_obj);
+
+	return ((void *)p_list_obj->p_object);
+}
+
+/*
+* PARAMETERS
+*	p_list_obj
+*		[in] Pointer to a cl_list_obj_t structure.
+*
+* RETURN VALUE
+*	Returns the value of the object pointer stored in the list object.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_set_obj
+*********/
+
+static inline void __cl_qlist_reset(IN cl_qlist_t * const p_list)
+{
+	/* Point the end item to itself. */
+	p_list->end.p_next = &p_list->end;
+	p_list->end.p_prev = &p_list->end;
+#if defined( _DEBUG_ )
+	p_list->end.p_list = p_list;
+#endif
+
+	/* Clear the count. */
+	p_list->count = 0;
+}
+
+/****f* Component Library: Quick List/cl_qlist_init
+* NAME
+*	cl_qlist_init
+*
+* DESCRIPTION
+*	The cl_qlist_init function initializes a quick list.
+*
+* SYNOPSIS
+*/
+static inline void cl_qlist_init(IN cl_qlist_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+
+	p_list->state = CL_INITIALIZED;
+
+	/* Reset the quick list data structure. */
+	__cl_qlist_reset(p_list);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure to initialize.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling quick list manipulation functions.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_head, cl_qlist_insert_tail,
+*	cl_qlist_remove_head, cl_qlist_remove_tail
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_count
+* NAME
+*	cl_qlist_count
+*
+* DESCRIPTION
+*	The cl_qlist_count function returns the number of list items stored
+*	in a quick list.
+*
+* SYNOPSIS
+*/
+static inline uint32_t cl_qlist_count(IN const cl_qlist_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	return ((uint32_t) p_list->count);
+
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUE
+*	Number of items in the list.  This function iterates though the quick
+*	list to count the items.
+*
+* SEE ALSO
+*	Quick List, cl_is_qlist_empty
+*********/
+
+/****f* Component Library: Quick List/cl_is_qlist_empty
+* NAME
+*	cl_is_qlist_empty
+*
+* DESCRIPTION
+*	The cl_is_qlist_empty function returns whether a quick list is empty.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_qlist_empty(IN const cl_qlist_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	return (!cl_qlist_count(p_list));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUES
+*	TRUE if the specified quick list is empty.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_count, cl_qlist_remove_all
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_next
+* NAME
+*	cl_qlist_next
+*
+* DESCRIPTION
+*	The cl_qlist_next function returns a pointer to the list item following
+*	a given list item in a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_next(IN const cl_list_item_t *
+					    const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list_item->p_list->state == CL_INITIALIZED);
+
+	/* Return the next item. */
+	return (p_list_item->p_next);
+}
+
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to the cl_list_item_t whose successor to return.
+*
+* Returns:
+*	Pointer to the list item following the list item specified by
+*	the p_list_item parameter in the quick list.
+*
+*	Pointer to the list end if p_list_item was at the tail of the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_prev, cl_qlist_end,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_prev
+* NAME
+*	cl_qlist_prev
+*
+* DESCRIPTION
+*	The cl_qlist_prev function returns a poirter to the list item preceding
+*	a given list item in a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_prev(IN const cl_list_item_t *
+					    const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list_item->p_list->state == CL_INITIALIZED);
+
+	/* Return the previous item. */
+	return (p_list_item->p_prev);
+}
+
+/*
+* PARAMETERS
+*	p_list_item
+*		[in] Pointer to the cl_list_item_t whose predecessor to return.
+*
+* Returns:
+*	Pointer to the list item preceding the list item specified by
+*	the p_list_item parameter in the quick list.
+*
+*	Pointer to the list end if p_list_item was at the tail of the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_end,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_head
+* NAME
+*	cl_qlist_head
+*
+* DESCRIPTION
+*	The cl_qlist_head function returns the list item at
+*	the head of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_head(IN const cl_qlist_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	return (cl_qlist_next(&p_list->end));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUES
+*	Pointer to the list item at the head of the quick list.
+*
+*	Pointer to the list end if the list was empty.
+*
+* NOTES
+*	cl_qlist_head does not remove the item from the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_tail, cl_qlist_next, cl_qlist_prev, cl_qlist_end,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_tail
+* NAME
+*	cl_qlist_tail
+*
+* DESCRIPTION
+*	The cl_qlist_tail function returns the list item at
+*	the tail of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_tail(IN const cl_qlist_t * const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	return (cl_qlist_prev(&p_list->end));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUES
+*	Pointer to the list item at the tail of the quick list.
+*
+*	Pointer to the list end if the list was empty.
+*
+* NOTES
+*	cl_qlist_tail does not remove the item from the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_head, cl_qlist_next, cl_qlist_prev, cl_qlist_end,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_end
+* NAME
+*	cl_qlist_end
+*
+* DESCRIPTION
+*	The cl_qlist_end function returns the end of a quick list.
+*
+* SYNOPSIS
+*/
+static inline const cl_list_item_t *cl_qlist_end(IN const cl_qlist_t *
+						 const p_list)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	return (&p_list->end);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUE
+*	Pointer to the end of the list.
+*
+* NOTES
+*	cl_qlist_end is useful for determining the validity of list items returned
+*	by cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_prev, as well as
+*	the cl_qlist_find functions.  If the list item pointer returned by any of
+*	these functions compares to the end, the end of the list was encoutered.
+*	When using cl_qlist_head or cl_qlist_tail, this condition indicates that
+*	the list is empty.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_prev,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_head
+* NAME
+*	cl_qlist_insert_head
+*
+* DESCRIPTION
+*	The cl_qlist_insert_head function inserts a list item at the
+*	head of a quick list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_insert_head(IN cl_qlist_t * const p_list,
+		     IN cl_list_item_t * const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	/*
+	 * The list item must not already be part of the list.  Note that this
+	 * assertion may fail if an uninitialized list item happens to have its
+	 * list pointer equal to the specified list.  The chances of this
+	 * happening are acceptable in light of the value of this check.
+	 */
+	CL_ASSERT(p_list_item->p_list != p_list);
+
+#if defined( _DEBUG_ )
+	p_list_item->p_list = p_list;
+#endif
+
+	/* Insert before the head. */
+	__cl_primitive_insert(cl_qlist_head(p_list), p_list_item);
+
+	p_list->count++;
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to insert the object.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure to add.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	In debug builds, cl_qlist_insert_head asserts that the specified list item
+*	is not already in the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_tail, cl_qlist_insert_list_head,
+*	cl_qlist_insert_list_tail, cl_qlist_insert_array_head,
+*	cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next,
+*	cl_qlist_remove_head, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_tail
+* NAME
+*	cl_qlist_insert_tail
+*
+* DESCRIPTION
+*	The cl_qlist_insert_tail function inserts a list item at the tail
+*	of a quick list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_insert_tail(IN cl_qlist_t * const p_list,
+		     IN cl_list_item_t * const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	/*
+	 * The list item must not already be part of the list.  Note that this
+	 * assertion may fail if an uninitialized list item happens to have its
+	 * list pointer equal to the specified list.  The chances of this
+	 * happening are acceptable in light of the value of this check.
+	 */
+	CL_ASSERT(p_list_item->p_list != p_list);
+
+#if defined( _DEBUG_ )
+	p_list_item->p_list = p_list;
+#endif
+
+	/*
+	 * Put the new element in front of the end which is the same
+	 * as being at the tail
+	 */
+	__cl_primitive_insert(&p_list->end, p_list_item);
+
+	p_list->count++;
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to insert the object.
+*
+*	p_list_item
+*		[in] Pointer to cl_list_item_t structure to add.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	In debug builds, cl_qlist_insert_tail asserts that the specified list item
+*	is not already in the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_head, cl_qlist_insert_list_head,
+*	cl_qlist_insert_list_tail, cl_qlist_insert_array_head,
+*	cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next,
+*	cl_qlist_remove_tail, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_list_head
+* NAME
+*	cl_qlist_insert_list_head
+*
+* DESCRIPTION
+*	The cl_qlist_insert_list_head function merges two quick lists by
+*	inserting one at the head of the other.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list,
+			  IN cl_qlist_t * const p_src_list);
+/*
+* PARAMETERS
+*	p_dest_list
+*		[in] Pointer to destination quicklist object.
+*
+*	p_src_list
+*		[in] Pointer to quicklist to add.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts all list items in the source list to the head of the
+*	destination list. The ordering of the list items is preserved.
+*
+*	The list pointed to by the p_src_list parameter is empty when
+*	the call returns.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_list_tail, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_array_head,
+*	cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_list_tail
+* NAME
+*	cl_qlist_insert_list_tail
+*
+* DESCRIPTION
+*	The cl_qlist_insert_list_tail function merges two quick lists by
+*	inserting one at the tail of the other.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list,
+			  IN cl_qlist_t * const p_src_list);
+/*
+* PARAMETERS
+*	p_dest_list
+*		[in] Pointer to destination quicklist object
+*
+*	p_src_list
+*		[in] Pointer to quicklist to add
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts all list items in the source list to the tail of the
+*	destination list. The ordering of the list items is preserved.
+*
+*	The list pointed to by the p_src_list parameter is empty when
+*	the call returns.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_list_head, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_array_head,
+*	cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_array_head
+* NAME
+*	cl_qlist_insert_array_head
+*
+* DESCRIPTION
+*	The cl_qlist_insert_array_head function inserts an array of list items
+*	at the head of a quick list.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_insert_array_head(IN cl_qlist_t * const p_list,
+			   IN cl_list_item_t * const p_array,
+			   IN uint32_t item_count, IN const uint32_t item_size);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to insert
+*		the objects.
+*
+*	p_array
+*		[in] Pointer to the first list item in an array of cl_list_item_t
+*		structures.
+*
+*	item_count
+*		[in] Number of cl_list_item_t structures in the array.
+*
+*	item_size
+*		[in] Size of the items added to the list. This is the stride in the
+*		array from one cl_list_item_t structure to the next.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts all the list items in the array specified by the p_array parameter
+*	to the head of the quick list specified by the p_list parameter,
+*	preserving ordering of the list items.
+*
+*	The array pointer passed into the function points to the cl_list_item_t
+*	in the first element of the caller's element array.  There is no
+*	restriction on where the element is stored in the parent structure.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_array_tail, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail,
+*	cl_qlist_insert_prev, cl_qlist_insert_next, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_array_tail
+* NAME
+*	cl_qlist_insert_array_tail
+*
+* DESCRIPTION
+*	The cl_qlist_insert_array_tail function inserts an array of list items
+*	at the tail of a quick list.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list,
+			   IN cl_list_item_t * const p_array,
+			   IN uint32_t item_count, IN const uint32_t item_size);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to insert
+*		the objects.
+*
+*	p_array
+*		[in] Pointer to the first list item in an array of cl_list_item_t
+*		structures.
+*
+*	item_count
+*		[in] Number of cl_list_item_t structures in the array.
+*
+*	item_size
+*		[in] Size of the items added to the list. This is the stride in the
+*		array from one cl_list_item_t structure to the next.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts all the list items in the array specified by the p_array parameter
+*	to the tail of the quick list specified by the p_list parameter,
+*	preserving ordering of the list items.
+*
+*	The array pointer passed into the function points to the cl_list_item_t
+*	in the first element of the caller's element array.  There is no
+*	restriction on where the element is stored in the parent structure.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_array_head, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail,
+*	cl_qlist_insert_prev, cl_qlist_insert_next, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_prev
+* NAME
+*	cl_qlist_insert_prev
+*
+* DESCRIPTION
+*	The cl_qlist_insert_prev function inserts a list item before a
+*	specified list item in a quick list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_insert_prev(IN cl_qlist_t * const p_list,
+		     IN cl_list_item_t * const p_list_item,
+		     IN cl_list_item_t * const p_new_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_new_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	/*
+	 * The list item must not already be part of the list.  Note that this
+	 * assertion may fail if an uninitialized list item happens to have its
+	 * list pointer equal to the specified list.  The chances of this
+	 * happening are acceptable in light of the value of this check.
+	 */
+	CL_ASSERT(p_new_item->p_list != p_list);
+
+#if defined( _DEBUG_ )
+	p_new_item->p_list = p_list;
+#endif
+
+	__cl_primitive_insert(p_list_item, p_new_item);
+
+	p_list->count++;
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to add the new item.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure.
+*
+*	p_new_item
+*		[in] Pointer to a cl_list_item_t structure to add to the quick list.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts the new list item before the list item specified by p_list_item.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_next, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail,
+*	cl_qlist_insert_array_head, cl_qlist_insert_array_tail, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_insert_next
+* NAME
+*	cl_qlist_insert_next
+*
+* DESCRIPTION
+*	The cl_qlist_insert_next function inserts a list item after a specified
+*	list item in a quick list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_insert_next(IN cl_qlist_t * const p_list,
+		     IN cl_list_item_t * const p_list_item,
+		     IN cl_list_item_t * const p_new_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_new_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	/*
+	 * The list item must not already be part of the list.  Note that this
+	 * assertion may fail if an uninitialized list item happens to have its
+	 * list pointer equal to the specified list.  The chances of this
+	 * happening are acceptable in light of the value of this check.
+	 */
+	CL_ASSERT(p_new_item->p_list != p_list);
+
+#if defined( _DEBUG_ )
+	p_new_item->p_list = p_list;
+#endif
+
+	__cl_primitive_insert(cl_qlist_next(p_list_item), p_new_item);
+
+	p_list->count++;
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure into which to add the new item.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure.
+*
+*	p_new_item
+*		[in] Pointer to a cl_list_item_t structure to add to the quick list.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Inserts the new list item after the list item specified by p_list_item.
+*	The list item specified by p_list_item must be in the quick list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_insert_prev, cl_qlist_insert_head,
+*	cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail,
+*	cl_qlist_insert_array_head, cl_qlist_insert_array_tail, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_remove_head
+* NAME
+*	cl_qlist_remove_head
+*
+* DESCRIPTION
+*	The cl_qlist_remove_head function removes and returns the list item
+*	at the head of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_remove_head(IN cl_qlist_t * const p_list)
+{
+	cl_list_item_t *p_item;
+
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	p_item = cl_qlist_head(p_list);
+	/* CL_ASSERT that the list item is part of the list. */
+	CL_ASSERT(p_item->p_list == p_list);
+
+	if (p_item == cl_qlist_end(p_list))
+		return (p_item);
+
+#if defined( _DEBUG_ )
+	/* Clear the item's link to the list. */
+	p_item->p_list = NULL;
+#endif
+
+	__cl_primitive_remove(p_item);
+
+	p_list->count--;
+
+	return (p_item);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUES
+*	Returns a pointer to the list item formerly at the head of the quick list.
+*
+*	Pointer to the list end if the list was empty.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_remove_tail, cl_qlist_remove_all, cl_qlist_remove_item,
+*	cl_qlist_end, cl_qlist_head, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_remove_tail
+* NAME
+*	cl_qlist_remove_tail
+*
+* DESCRIPTION
+*	The cl_qlist_remove_tail function removes and returns the list item
+*	at the tail of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_remove_tail(IN cl_qlist_t * const p_list)
+{
+	cl_list_item_t *p_item;
+
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+
+	p_item = cl_qlist_tail(p_list);
+	/* CL_ASSERT that the list item is part of the list. */
+	CL_ASSERT(p_item->p_list == p_list);
+
+	if (p_item == cl_qlist_end(p_list))
+		return (p_item);
+
+#if defined( _DEBUG_ )
+	/* Clear the item's link to the list. */
+	p_item->p_list = NULL;
+#endif
+
+	__cl_primitive_remove(p_item);
+
+	p_list->count--;
+
+	return (p_item);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUES
+*	Returns a pointer to the list item formerly at the tail of the quick list.
+*
+*	Pointer to the list end if the list was empty.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_remove_head, cl_qlist_remove_all, cl_qlist_remove_item,
+*	cl_qlist_end, cl_qlist_tail, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_remove_item
+* NAME
+*	cl_qlist_remove_item
+*
+* DESCRIPTION
+*	The cl_qlist_remove_item function removes a specific list item from a quick list.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qlist_remove_item(IN cl_qlist_t * const p_list,
+		     IN cl_list_item_t * const p_list_item)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list_item);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	/* CL_ASSERT that the list item is part of the list. */
+	CL_ASSERT(p_list_item->p_list == p_list);
+
+	if (p_list_item == cl_qlist_end(p_list))
+		return;
+
+#if defined( _DEBUG_ )
+	/* Clear the item's link to the list. */
+	p_list_item->p_list = NULL;
+#endif
+
+	__cl_primitive_remove(p_list_item);
+
+	p_list->count--;
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure from which to remove the item.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure to remove.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Removes the list item pointed to by the p_list_item parameter from
+*	its list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_remove_head, cl_qlist_remove_tail, cl_qlist_remove_all,
+*	cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_remove_all
+* NAME
+*	cl_qlist_remove_all
+*
+* DESCRIPTION
+*	The cl_qlist_remove_all function removes all items from a quick list.
+*
+* SYNOPSIS
+*/
+static inline void cl_qlist_remove_all(IN cl_qlist_t * const p_list)
+{
+#if defined( _DEBUG_ )
+	cl_list_item_t *p_list_item;
+
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	p_list_item = cl_qlist_head(p_list);
+	while (p_list_item != cl_qlist_end(p_list)) {
+		p_list_item = cl_qlist_next(p_list_item);
+		cl_qlist_prev(p_list_item)->p_list = NULL;
+	}
+#endif
+
+	__cl_qlist_reset(p_list);
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_remove_head, cl_qlist_remove_tail,
+*	cl_qlist_remove_item, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_is_item_in_qlist
+* NAME
+*	cl_is_item_in_qlist
+*
+* DESCRIPTION
+*	The cl_is_item_in_qlist function checks for the presence of a
+*	list item in a quick list.
+*
+* SYNOPSIS
+*/
+boolean_t
+cl_is_item_in_qlist(IN const cl_qlist_t * const p_list,
+		    IN const cl_list_item_t * const p_list_item);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+*	p_list_item
+*		[in] Pointer to the cl_list_item_t to find.
+*
+* RETURN VALUES
+*	TRUE if the list item was found in the quick list.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_remove_item, cl_list_item_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_find_next
+* NAME
+*	cl_qlist_find_next
+*
+* DESCRIPTION
+*	The cl_qlist_find_next function invokes a specified function to
+*	search for an item, starting from a given list item.
+*
+* SYNOPSIS
+*/
+cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list,
+				   IN const cl_list_item_t * const p_list_item,
+				   IN cl_pfn_qlist_find_t pfn_func,
+				   IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure in which to search.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure from which to start the search.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_qlist_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context if a
+*		callback function is provided, or value compared to the quick list's
+*		list items.
+*
+* Returns:
+*	Pointer to the list item, if found.
+*
+*	p_list_item if not found.
+*
+* NOTES
+*	cl_qlist_find_next does not remove list items from the list.
+*	The list item is returned when the function specified by the pfn_func
+*	parameter returns CL_SUCCESS.  The list item from which the search starts is
+*	excluded from the search.
+*
+*	The function provided by the pfn_func must not perform any list operations,
+*	as these would corrupt the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_prev, cl_qlist_find_from_head,
+*	cl_qlist_find_from_tail, cl_qlist_end, cl_qlist_apply_func,
+*	cl_qlist_move_items, cl_list_item_t, cl_pfn_qlist_find_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_find_prev
+* NAME
+*	cl_qlist_find_prev
+*
+* DESCRIPTION
+*	The cl_qlist_find_prev function invokes a specified function to
+*	search backward for an item, starting from a given list item.
+*
+* SYNOPSIS
+*/
+cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list,
+				   IN const cl_list_item_t * const p_list_item,
+				   IN cl_pfn_qlist_find_t pfn_func,
+				   IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure in which to search.
+*
+*	p_list_item
+*		[in] Pointer to a cl_list_item_t structure from which to start the search.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_qlist_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context if a
+*		callback function is provided, or value compared to the quick list's
+*		list items.
+*
+* Returns:
+*	Pointer to the list item, if found.
+*
+*	p_list_item if not found.
+*
+* NOTES
+*	cl_qlist_find_prev does not remove list items from the list.
+*	The list item is returned when the function specified by the pfn_func
+*	parameter returns CL_SUCCESS.  The list item from which the search starts is
+*	excluded from the search.
+*
+*	The function provided by the pfn_func must not perform any list operations,
+*	as these would corrupt the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_next, cl_qlist_find_from_head,
+*	cl_qlist_find_from_tail, cl_qlist_end, cl_qlist_apply_func,
+*	cl_qlist_move_items, cl_list_item_t, cl_pfn_qlist_find_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_find_from_head
+* NAME
+*	cl_qlist_find_from_head
+*
+* DESCRIPTION
+*	The cl_qlist_find_from_head function invokes a specified function to
+*	search for an item, starting at the head of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_find_from_head(IN const cl_qlist_t *
+						      const p_list,
+						      IN cl_pfn_qlist_find_t
+						      pfn_func,
+						      IN const void *const
+						      context)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	/* CL_ASSERT that a find function is provided. */
+	CL_ASSERT(pfn_func);
+
+	return (cl_qlist_find_next(p_list, cl_qlist_end(p_list), pfn_func,
+				   context));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_qlist_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context if a
+*		callback function is provided, or value compared to the quick list's
+*		list items.
+*
+* Returns:
+*	Pointer to the list item, if found.
+*
+*	Pointer to the list end otherwise
+*
+* NOTES
+*	cl_qlist_find_from_head does not remove list items from the list.
+*	The list item is returned when the function specified by the pfn_func
+*	parameter returns CL_SUCCESS.
+*
+*	The function provided by the pfn_func parameter must not perform any list
+*	operations, as these would corrupt the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_from_tail, cl_qlist_find_next, cl_qlist_find_prev,
+*	cl_qlist_end, cl_qlist_apply_func, cl_qlist_move_items, cl_list_item_t,
+*	cl_pfn_qlist_find_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_find_from_tail
+* NAME
+*	cl_qlist_find_from_tail
+*
+* DESCRIPTION
+*	The cl_qlist_find_from_tail function invokes a specified function to
+*	search for an item, starting at the tail of a quick list.
+*
+* SYNOPSIS
+*/
+static inline cl_list_item_t *cl_qlist_find_from_tail(IN const cl_qlist_t *
+						      const p_list,
+						      IN cl_pfn_qlist_find_t
+						      pfn_func,
+						      IN const void *const
+						      context)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_list);
+	/* CL_ASSERT that the list was initialized. */
+	CL_ASSERT(p_list->state == CL_INITIALIZED);
+	/* CL_ASSERT that a find function is provided. */
+	CL_ASSERT(pfn_func);
+
+	return (cl_qlist_find_prev(p_list, cl_qlist_end(p_list), pfn_func,
+				   context));
+}
+
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_qlist_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context if a
+*		callback function is provided, or value compared to the quick list's
+*		list items.
+*
+* Returns:
+*	Pointer to the list item, if found.
+*
+*	Pointer to the list end otherwise
+*
+* NOTES
+*	cl_qlist_find_from_tail does not remove list items from the list.
+*	The list item is returned when the function specified by the pfn_func
+*	parameter returns CL_SUCCESS.
+*
+*	The function provided by the pfn_func parameter must not perform any list
+*	operations, as these would corrupt the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_from_head, cl_qlist_find_next, cl_qlist_find_prev,
+*	cl_qlist_apply_func, cl_qlist_end, cl_qlist_move_items, cl_list_item_t,
+*	cl_pfn_qlist_find_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_apply_func
+* NAME
+*	cl_qlist_apply_func
+*
+* DESCRIPTION
+*	The cl_qlist_apply_func function executes a specified function
+*	for every list item stored in a quick list.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_apply_func(IN const cl_qlist_t * const p_list,
+		    IN cl_pfn_qlist_apply_t pfn_func,
+		    IN const void *const context);
+/*
+* PARAMETERS
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure.
+*
+*	pfn_func
+*		[in] Function invoked for every item in the quick list.
+*		See the cl_pfn_qlist_apply_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	The function provided must not perform any list operations, as these
+*	would corrupt the quick list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail,
+*	cl_qlist_move_items, cl_pfn_qlist_apply_t
+*********/
+
+/****f* Component Library: Quick List/cl_qlist_move_items
+* NAME
+*	cl_qlist_move_items
+*
+* DESCRIPTION
+*	The cl_qlist_move_items function moves list items from one list to
+*	another based on the return value of a user supplied function.
+*
+* SYNOPSIS
+*/
+void
+cl_qlist_move_items(IN cl_qlist_t * const p_src_list,
+		    IN cl_qlist_t * const p_dest_list,
+		    IN cl_pfn_qlist_find_t pfn_func,
+		    IN const void *const context);
+/*
+* PARAMETERS
+*	p_src_list
+*		[in] Pointer to a cl_qlist_t structure from which
+*		list items are removed.
+*
+*	p_dest_list
+*		[in] Pointer to a cl_qlist_t structure to which the source
+*		list items are added.
+*
+*	pfn_func
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_qlist_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	If the function specified by the pfn_func parameter returns CL_SUCCESS,
+*	the related list item is removed from p_src_list and inserted at the tail
+*	of the p_dest_list.
+*
+*	The cl_qlist_move_items function continues iterating through p_src_list
+*	from the last item moved, allowing multiple items to be located and moved
+*	in a single list iteration.
+*
+*	The function specified by pfn_func must not perform any list operations,
+*	as these would corrupt the list.
+*
+* SEE ALSO
+*	Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail,
+*	cl_qlist_apply_func, cl_pfn_qlist_find_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_QUICK_LIST_H_ */
diff --git a/include/complib/cl_qmap.h b/include/complib/cl_qmap.h
new file mode 100644
index 0000000..130c2ef
--- /dev/null
+++ b/include/complib/cl_qmap.h
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of quick map, a binary tree where the caller always provides
+ *	all necessary storage.
+ */
+
+#ifndef _CL_QMAP_H_
+#define _CL_QMAP_H_
+
+#include <complib/cl_qpool.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/Quick Map
+* NAME
+*	Quick Map
+*
+* DESCRIPTION
+*	Quick map implements a binary tree that stores user provided cl_map_item_t
+*	structures.  Each item stored in a quick map has a unique 64-bit key
+*	(duplicates are not allowed).  Quick map provides the ability to
+*	efficiently search for an item given a key.
+*
+*	Quick map does not allocate any memory, and can therefore not fail
+*	any operations due to insufficient memory.  Quick map can thus be useful
+*	in minimizing the error paths in code.
+*
+*	Quick map is not thread safe, and users must provide serialization when
+*	adding and removing items from the map.
+*
+*	The quick map functions operate on a cl_qmap_t structure which should be
+*	treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_qmap_t, cl_map_item_t, cl_map_obj_t
+*
+*	Callbacks:
+*		cl_pfn_qmap_apply_t
+*
+*	Item Manipulation:
+*		cl_qmap_set_obj, cl_qmap_obj, cl_qmap_key
+*
+*	Initialization:
+*		cl_qmap_init
+*
+*	Iteration:
+*		cl_qmap_end, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev
+*
+*	Manipulation:
+*		cl_qmap_insert, cl_qmap_get, cl_qmap_remove_item, cl_qmap_remove,
+*		cl_qmap_remove_all, cl_qmap_merge, cl_qmap_delta, cl_qmap_get_next
+*
+*	Search:
+*		cl_qmap_apply_func
+*
+*	Attributes:
+*		cl_qmap_count, cl_is_qmap_empty,
+*********/
+/****i* Component Library: Quick Map/cl_map_color_t
+* NAME
+*	cl_map_color_t
+*
+* DESCRIPTION
+*	The cl_map_color_t enumerated type is used to note the color of
+*	nodes in a map.
+*
+* SYNOPSIS
+*/
+typedef enum _cl_map_color {
+	CL_MAP_RED,
+	CL_MAP_BLACK
+} cl_map_color_t;
+/*
+* VALUES
+*	CL_MAP_RED
+*		The node in the map is red.
+*
+*	CL_MAP_BLACK
+*		The node in the map is black.
+*
+* SEE ALSO
+*	Quick Map, cl_map_item_t
+*********/
+
+/****s* Component Library: Quick Map/cl_map_item_t
+* NAME
+*	cl_map_item_t
+*
+* DESCRIPTION
+*	The cl_map_item_t structure is used by maps to store objects.
+*
+*	The cl_map_item_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_map_item {
+	/* Must be first to allow casting. */
+	cl_pool_item_t pool_item;
+	struct _cl_map_item *p_left;
+	struct _cl_map_item *p_right;
+	struct _cl_map_item *p_up;
+	cl_map_color_t color;
+	uint64_t key;
+#ifdef _DEBUG_
+	struct _cl_qmap *p_map;
+#endif
+} cl_map_item_t;
+/*
+* FIELDS
+*	pool_item
+*		Used to store the item in a doubly linked list, allowing more
+*		efficient map traversal.
+*
+*	p_left
+*		Pointer to the map item that is a child to the left of the node.
+*
+*	p_right
+*		Pointer to the map item that is a child to the right of the node.
+*
+*	p_up
+*		Pointer to the map item that is the parent of the node.
+*
+*	p_nil
+*		Pointer to the map's NIL item, used as a terminator for leaves.
+*		The NIL sentinel is in the cl_qmap_t structure.
+*
+*	color
+*		Indicates whether a node is red or black in the map.
+*
+*	key
+*		Value that uniquely represents a node in a map.  This value is
+*		set by calling cl_qmap_insert and can be retrieved by calling
+*		cl_qmap_key.
+*
+* NOTES
+*	None of the fields of this structure should be manipulated by users, as
+*	they are crititcal to the proper operation of the map in which they
+*	are stored.
+*
+*	To allow storing items in either a quick list, a quick pool, or a quick
+*	map, the map implementation guarantees that the map item can be safely
+*	cast to a pool item used for storing an object in a quick pool, or cast
+*	to a list item used for storing an object in a quick list.  This removes
+*	the need to embed a map item, a list item, and a pool item in objects
+*	that need to be stored in a quick list, a quick pool, and a quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_insert, cl_qmap_key, cl_pool_item_t, cl_list_item_t
+*********/
+
+/****s* Component Library: Quick Map/cl_map_obj_t
+* NAME
+*	cl_map_obj_t
+*
+* DESCRIPTION
+*	The cl_map_obj_t structure is used to store objects in maps.
+*
+*	The cl_map_obj_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_map_obj {
+	cl_map_item_t item;
+	const void *p_object;
+} cl_map_obj_t;
+/*
+* FIELDS
+*	item
+*		Map item used by internally by the map to store an object.
+*
+*	p_object
+*		User defined context. Users should not access this field directly.
+*		Use cl_qmap_set_obj and cl_qmap_obj to set and retrieve the value
+*		of this field.
+*
+* NOTES
+*	None of the fields of this structure should be manipulated by users, as
+*	they are crititcal to the proper operation of the map in which they
+*	are stored.
+*
+*	Use cl_qmap_set_obj and cl_qmap_obj to set and retrieve the object
+*	stored in a map item, respectively.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_set_obj, cl_qmap_obj, cl_map_item_t
+*********/
+
+/****s* Component Library: Quick Map/cl_qmap_t
+* NAME
+*	cl_qmap_t
+*
+* DESCRIPTION
+*	Quick map structure.
+*
+*	The cl_qmap_t structure should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_qmap {
+	cl_map_item_t root;
+	cl_map_item_t nil;
+	cl_state_t state;
+	size_t count;
+} cl_qmap_t;
+/*
+* PARAMETERS
+*	root
+*		Map item that serves as root of the map.  The root is set up to
+*		always have itself as parent.  The left pointer is set to point
+*		to the item at the root.
+*
+*	nil
+*		Map item that serves as terminator for all leaves, as well as
+*		providing the list item used as quick list for storing map items
+*		in a list for faster traversal.
+*
+*	state
+*		State of the map, used to verify that operations are permitted.
+*
+*	count
+*		Number of items in the map.
+*
+* SEE ALSO
+*	Quick Map
+*********/
+
+/****d* Component Library: Quick Map/cl_pfn_qmap_apply_t
+* NAME
+*	cl_pfn_qmap_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_qmap_apply_t function type defines the prototype for
+*	functions used to iterate items in a quick map.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_qmap_apply_t) (IN cl_map_item_t * const p_map_item, IN void *context);
+/*
+* PARAMETERS
+*	p_map_item
+*		[in] Pointer to a cl_map_item_t structure.
+*
+*	context
+*		[in] Value passed to the callback function.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_qmap_apply_func
+*	function.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_apply_func
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_count
+* NAME
+*	cl_qmap_count
+*
+* DESCRIPTION
+*	The cl_qmap_count function returns the number of items stored
+*	in a quick map.
+*
+* SYNOPSIS
+*/
+static inline uint32_t cl_qmap_count(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return ((uint32_t) p_map->count);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure whose item count to return.
+*
+* RETURN VALUE
+*	Returns the number of items stored in the map.
+*
+* SEE ALSO
+*	Quick Map, cl_is_qmap_empty
+*********/
+
+/****f* Component Library: Quick Map/cl_is_qmap_empty
+* NAME
+*	cl_is_qmap_empty
+*
+* DESCRIPTION
+*	The cl_is_qmap_empty function returns whether a quick map is empty.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_qmap_empty(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	return (p_map->count == 0);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure to test for emptiness.
+*
+* RETURN VALUES
+*	TRUE if the quick map is empty.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_count, cl_qmap_remove_all
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_set_obj
+* NAME
+*	cl_qmap_set_obj
+*
+* DESCRIPTION
+*	The cl_qmap_set_obj function sets the object stored in a map object.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qmap_set_obj(IN cl_map_obj_t * const p_map_obj,
+		IN const void *const p_object)
+{
+	CL_ASSERT(p_map_obj);
+	p_map_obj->p_object = p_object;
+}
+
+/*
+* PARAMETERS
+*	p_map_obj
+*		[in] Pointer to a map object stucture whose object pointer
+*		is to be set.
+*
+*	p_object
+*		[in] User defined context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_obj
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_obj
+* NAME
+*	cl_qmap_obj
+*
+* DESCRIPTION
+*	The cl_qmap_obj function returns the object stored in a map object.
+*
+* SYNOPSIS
+*/
+static inline void *cl_qmap_obj(IN const cl_map_obj_t * const p_map_obj)
+{
+	CL_ASSERT(p_map_obj);
+	return ((void *)p_map_obj->p_object);
+}
+
+/*
+* PARAMETERS
+*	p_map_obj
+*		[in] Pointer to a map object stucture whose object pointer to return.
+*
+* RETURN VALUE
+*	Returns the value of the object pointer stored in the map object.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_set_obj
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_key
+* NAME
+*	cl_qmap_key
+*
+* DESCRIPTION
+*	The cl_qmap_key function retrieves the key value of a map item.
+*
+* SYNOPSIS
+*/
+static inline uint64_t cl_qmap_key(IN const cl_map_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	return (p_item->key);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose key value to return.
+*
+* RETURN VALUE
+*	Returns the 64-bit key value for the specified map item.
+*
+* NOTES
+*	The key value is set in a call to cl_qmap_insert.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_insert
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_init
+* NAME
+*	cl_qmap_init
+*
+* DESCRIPTION
+*	The cl_qmap_init function initialized a quick map for use.
+*
+* SYNOPSIS
+*/
+void cl_qmap_init(IN cl_qmap_t * const p_map);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure to initialize.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling quick map manipulation functions.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_insert, cl_qmap_remove
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_end
+* NAME
+*	cl_qmap_end
+*
+* DESCRIPTION
+*	The cl_qmap_end function returns the end of a quick map.
+*
+* SYNOPSIS
+*/
+static inline const cl_map_item_t *cl_qmap_end(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	/* Nil is the end of the map. */
+	return (&p_map->nil);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure whose end to return.
+*
+* RETURN VALUE
+*	Pointer to the end of the map.
+*
+* NOTES
+*	cl_qmap_end is useful for determining the validity of map items returned
+*	by cl_qmap_head, cl_qmap_tail, cl_qmap_next, or cl_qmap_prev.  If the
+*	map item pointer returned by any of these functions compares to the end,
+*	the end of the map was encoutered.
+*	When using cl_qmap_head or cl_qmap_tail, this condition indicates that
+*	the map is empty.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_head
+* NAME
+*	cl_qmap_head
+*
+* DESCRIPTION
+*	The cl_qmap_head function returns the map item with the lowest key
+*	value stored in a quick map.
+*
+* SYNOPSIS
+*/
+static inline cl_map_item_t *cl_qmap_head(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return ((cl_map_item_t *) p_map->nil.pool_item.list_item.p_next);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure whose item with the lowest
+*		key is returned.
+*
+* RETURN VALUES
+*	Pointer to the map item with the lowest key in the quick map.
+*
+*	Pointer to the map end if the quick map was empty.
+*
+* NOTES
+*	cl_qmap_head does not remove the item from the map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_tail, cl_qmap_next, cl_qmap_prev, cl_qmap_end,
+*	cl_qmap_item_t
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_tail
+* NAME
+*	cl_qmap_tail
+*
+* DESCRIPTION
+*	The cl_qmap_tail function returns the map item with the highest key
+*	value stored in a quick map.
+*
+* SYNOPSIS
+*/
+static inline cl_map_item_t *cl_qmap_tail(IN const cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+	return ((cl_map_item_t *) p_map->nil.pool_item.list_item.p_prev);
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure whose item with the
+*		highest key is returned.
+*
+* RETURN VALUES
+*	Pointer to the map item with the highest key in the quick map.
+*
+*	Pointer to the map end if the quick map was empty.
+*
+* NOTES
+*	cl_qmap_end does not remove the item from the map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_head, cl_qmap_next, cl_qmap_prev, cl_qmap_end,
+*	cl_qmap_item_t
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_next
+* NAME
+*	cl_qmap_next
+*
+* DESCRIPTION
+*	The cl_qmap_next function returns the map item with the next higher
+*	key value than a specified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_map_item_t *cl_qmap_next(IN const cl_map_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	return ((cl_map_item_t *) p_item->pool_item.list_item.p_next);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose successor to return.
+*
+* RETURN VALUES
+*	Pointer to the map item with the next higher key value in a quick map.
+*
+*	Pointer to the map end if the specified item was the last item in
+*	the quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_prev, cl_qmap_end,
+*	cl_map_item_t
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_prev
+* NAME
+*	cl_qmap_prev
+*
+* DESCRIPTION
+*	The cl_qmap_prev function returns the map item with the next lower
+*	key value than a precified map item.
+*
+* SYNOPSIS
+*/
+static inline cl_map_item_t *cl_qmap_prev(IN const cl_map_item_t * const p_item)
+{
+	CL_ASSERT(p_item);
+	return ((cl_map_item_t *) p_item->pool_item.list_item.p_prev);
+}
+
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item whose predecessor to return.
+*
+* RETURN VALUES
+*	Pointer to the map item with the next lower key value in a quick map.
+*
+*	Pointer to the map end if the specifid item was the first item in
+*	the quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_end,
+*	cl_map_item_t
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_insert
+* NAME
+*	cl_qmap_insert
+*
+* DESCRIPTION
+*	The cl_qmap_insert function inserts a map item into a quick map.
+*  NOTE: Only if such a key does not alerady exist in the map !!!!
+*
+* SYNOPSIS
+*/
+cl_map_item_t *cl_qmap_insert(IN cl_qmap_t * const p_map,
+			      IN const uint64_t key,
+			      IN cl_map_item_t * const p_item);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure into which to add the item.
+*
+*	key
+*		[in] Value to assign to the item.
+*
+*	p_item
+*		[in] Pointer to a cl_map_item_t stucture to insert into the quick map.
+*
+* RETURN VALUE
+*	Pointer to the item in the map with the specified key.  If insertion
+*	was successful, this is the pointer to the item.  If an item with the
+*	specified key already exists in the map, the pointer to that item is
+*	returned - but the new key is NOT inserted...
+*
+* NOTES
+*	Insertion operations may cause the quick map to rebalance.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_remove, cl_map_item_t
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_get
+* NAME
+*	cl_qmap_get
+*
+* DESCRIPTION
+*	The cl_qmap_get function returns the map item associated with a key.
+*
+* SYNOPSIS
+*/
+cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map,
+			   IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure from which to retrieve the
+*		item with the specified key.
+*
+*	key
+*		[in] Key value used to search for the desired map item.
+*
+* RETURN VALUES
+*	Pointer to the map item with the desired key value.
+*
+*	Pointer to the map end if there was no item with the desired key value
+*	stored in the quick map.
+*
+* NOTES
+*	cl_qmap_get does not remove the item from the quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_get_next, cl_qmap_remove
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_get_next
+* NAME
+*	cl_qmap_get_next
+*
+* DESCRIPTION
+*	The cl_qmap_get_next function returns the first map item associated with a
+*	key > the key specified.
+*
+* SYNOPSIS
+*/
+cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map,
+				IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure from which to retrieve the
+*		first item with a key > the specified key.
+*
+*	key
+*		[in] Key value used to search for the desired map item.
+*
+* RETURN VALUES
+*	Pointer to the first map item with a key > the desired key value.
+*
+*	Pointer to the map end if there was no item with a key > the desired key
+*	value stored in the quick map.
+*
+* NOTES
+*	cl_qmap_get_next does not remove the item from the quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_get, cl_qmap_remove
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_remove_item
+* NAME
+*	cl_qmap_remove_item
+*
+* DESCRIPTION
+*	The cl_qmap_remove_item function removes the specified map item
+*	from a quick map.
+*
+* SYNOPSIS
+*/
+void
+cl_qmap_remove_item(IN cl_qmap_t * const p_map,
+		    IN cl_map_item_t * const p_item);
+/*
+* PARAMETERS
+*	p_item
+*		[in] Pointer to a map item to remove from its quick map.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+*	In a debug build, cl_qmap_remove_item asserts that the item being removed
+*	is in the specified map.
+*
+* NOTES
+*	Removes the map item pointed to by p_item from its quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_remove, cl_qmap_remove_all, cl_qmap_insert
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_remove
+* NAME
+*	cl_qmap_remove
+*
+* DESCRIPTION
+*	The cl_qmap_remove function removes the map item with the specified key
+*	from a quick map.
+*
+* SYNOPSIS
+*/
+cl_map_item_t *cl_qmap_remove(IN cl_qmap_t * const p_map,
+			      IN const uint64_t key);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure from which to remove the item
+*		with the specified key.
+*
+*	key
+*		[in] Key value used to search for the map item to remove.
+*
+* RETURN VALUES
+*	Pointer to the removed map item if it was found.
+*
+*	Pointer to the map end if no item with the specified key exists in the
+*	quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_remove_item, cl_qmap_remove_all, cl_qmap_insert
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_remove_all
+* NAME
+*	cl_qmap_remove_all
+*
+* DESCRIPTION
+*	The cl_qmap_remove_all function removes all items in a quick map,
+*	leaving it empty.
+*
+* SYNOPSIS
+*/
+static inline void cl_qmap_remove_all(IN cl_qmap_t * const p_map)
+{
+	CL_ASSERT(p_map);
+	CL_ASSERT(p_map->state == CL_INITIALIZED);
+
+	p_map->root.p_left = &p_map->nil;
+	p_map->nil.pool_item.list_item.p_next = &p_map->nil.pool_item.list_item;
+	p_map->nil.pool_item.list_item.p_prev = &p_map->nil.pool_item.list_item;
+	p_map->count = 0;
+}
+
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure to empty.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_remove, cl_qmap_remove_item
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_merge
+* NAME
+*	cl_qmap_merge
+*
+* DESCRIPTION
+*	The cl_qmap_merge function moves all items from one map to another,
+*	excluding duplicates.
+*
+* SYNOPSIS
+*/
+void
+cl_qmap_merge(OUT cl_qmap_t * const p_dest_map,
+	      IN OUT cl_qmap_t * const p_src_map);
+/*
+* PARAMETERS
+*	p_dest_map
+*		[out] Pointer to a cl_qmap_t structure to which items should be added.
+*
+*	p_src_map
+*		[in/out] Pointer to a cl_qmap_t structure whose items to add
+*		to p_dest_map.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Items are evaluated based on their keys only.
+*
+*	Upon return from cl_qmap_merge, the quick map referenced by p_src_map
+*	contains all duplicate items.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_delta
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_delta
+* NAME
+*	cl_qmap_delta
+*
+* DESCRIPTION
+*	The cl_qmap_delta function computes the differences between two maps.
+*
+* SYNOPSIS
+*/
+void
+cl_qmap_delta(IN OUT cl_qmap_t * const p_map1,
+	      IN OUT cl_qmap_t * const p_map2,
+	      OUT cl_qmap_t * const p_new, OUT cl_qmap_t * const p_old);
+/*
+* PARAMETERS
+*	p_map1
+*		[in/out] Pointer to the first of two cl_qmap_t structures whose
+*		differences to compute.
+*
+*	p_map2
+*		[in/out] Pointer to the second of two cl_qmap_t structures whose
+*		differences to compute.
+*
+*	p_new
+*		[out] Pointer to an empty cl_qmap_t structure that contains the
+*		items unique to p_map2 upon return from the function.
+*
+*	p_old
+*		[out] Pointer to an empty cl_qmap_t structure that contains the
+*		items unique to p_map1 upon return from the function.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*	Items are evaluated based on their keys.  Items that exist in both
+*	p_map1 and p_map2 remain in their respective maps.  Items that
+*	exist only p_map1 are moved to p_old.  Likewise, items that exist only
+*	in p_map2 are moved to p_new.  This function can be useful in evaluating
+*	changes between two maps.
+*
+*	Both maps pointed to by p_new and p_old must be empty on input.  This
+*	requirement removes the possibility of failures.
+*
+* SEE ALSO
+*	Quick Map, cl_qmap_merge
+*********/
+
+/****f* Component Library: Quick Map/cl_qmap_apply_func
+* NAME
+*	cl_qmap_apply_func
+*
+* DESCRIPTION
+*	The cl_qmap_apply_func function executes a specified function
+*	for every item stored in a quick map.
+*
+* SYNOPSIS
+*/
+void
+cl_qmap_apply_func(IN const cl_qmap_t * const p_map,
+		   IN cl_pfn_qmap_apply_t pfn_func,
+		   IN const void *const context);
+/*
+* PARAMETERS
+*	p_map
+*		[in] Pointer to a cl_qmap_t structure.
+*
+*	pfn_func
+*		[in] Function invoked for every item in the quick map.
+*		See the cl_pfn_qmap_apply_t function type declaration for
+*		details about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	The function provided must not perform any map operations, as these
+*	would corrupt the quick map.
+*
+* SEE ALSO
+*	Quick Map, cl_pfn_qmap_apply_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_QMAP_H_ */
diff --git a/include/complib/cl_qpool.h b/include/complib/cl_qpool.h
new file mode 100644
index 0000000..f144cb3
--- /dev/null
+++ b/include/complib/cl_qpool.h
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of the quick pool.
+ *	The quick pool manages a pool of objects.
+ *	The pool can grow to meet demand, limited only by system memory.
+ */
+
+#ifndef _CL_QUICK_POOL_H_
+#define _CL_QUICK_POOL_H_
+
+#include <complib/cl_qcomppool.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/Quick Pool
+* NAME
+*	Quick Pool
+*
+* DESCRIPTION
+*	The quick pool provides a self-contained and self-sustaining pool
+*	of user defined objects.
+*
+*	To aid in object oriented design, the quick pool provides the user
+*	the ability to specify callbacks that are invoked for each object for
+*	construction, initialization, and destruction. Constructor and destructor
+*	callback functions may not fail.
+*
+*	A quick pool does not return memory to the system as the user returns
+*	objects to the pool. The only method of returning memory to the system is
+*	to destroy the pool.
+*
+*	The quick pool operates on cl_pool_item_t structures that describe
+*	objects. This can provides for more efficient memory use and operation.
+*	If using a cl_pool_item_t is not desired, the Pool provides similar
+*	functionality but operates on opaque objects.
+*
+*	The quick pool functions operates on a cl_qpool_t structure which should
+*	be treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_qpool_t, cl_pool_item_t
+*
+*	Callbacks:
+*		cl_pfn_qpool_init_t, cl_pfn_qpool_dtor_t
+*
+*	Initialization/Destruction:
+*		cl_qpool_construct, cl_qpool_init, cl_qpool_destroy
+*
+*	Manipulation:
+*		cl_qpool_get, cl_qpool_put, cl_qpool_put_list, cl_qpool_grow
+*
+*	Attributes:
+*		cl_is_qpool_inited, cl_qpool_count
+*********/
+/****d* Component Library: Quick Pool/cl_pfn_qpool_init_t
+* NAME
+*	cl_pfn_qpool_init_t
+*
+* DESCRIPTION
+*	The cl_pfn_qpool_init_t function type defines the prototype for
+*	functions used as constructor for objects being allocated by a
+*	quick pool.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_qpool_init_t) (IN void *const p_object,
+			    IN void *context,
+			    OUT cl_pool_item_t ** const pp_pool_item);
+/*
+* PARAMETERS
+*	p_object
+*		[in] Pointer to an object to initialize.
+*
+*	context
+*		[in] Context provided in a call to cl_qpool_init.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS to indicate that initialization of the object
+*	was successful and that initialization of further objects may continue.
+*
+*	Other cl_status_t values will be returned by cl_qcpool_init
+*	and cl_qcpool_grow.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_qpool_init function.
+*
+*	The initializer is invoked once per allocated object, allowing the user
+*	to perform any necessary initialization.  Returning a status other than
+*	CL_SUCCESS aborts a grow operation, initiated either through cl_qcpool_init
+*	or cl_qcpool_grow, causing the initiating function to fail.
+*	Any non-CL_SUCCESS status will be returned by the function that initiated
+*	the grow operation.
+*
+*	All memory for the object is pre-allocated.  Users should include space in
+*	their objects for the cl_pool_item_t structure that will represent the
+*	object to avoid having to allocate that structure in the initialization
+*	callback.
+*
+*	When later performing a cl_qcpool_get call, the return value is a pointer
+*	to the cl_pool_item_t returned by this function in the pp_pool_item
+*	parameter.  Users must set pp_pool_item to a valid pointer to the
+*	cl_pool_item_t representing the object if they return CL_SUCCESS.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_init
+*********/
+
+/****d* Component Library: Quick Pool/cl_pfn_qpool_dtor_t
+* NAME
+*	cl_pfn_qpool_dtor_t
+*
+* DESCRIPTION
+*	The cl_pfn_qpool_dtor_t function type defines the prototype for
+*	functions used as destructor for objects being deallocated by a
+*	quick pool.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_qpool_dtor_t) (IN const cl_pool_item_t * const p_pool_item,
+			 IN void *context);
+/*
+* PARAMETERS
+*	p_pool_item
+*		[in] Pointer to a cl_pool_item_t structure representing an object.
+*
+*	context
+*		[in] Context provided in a call to cl_qpool_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by the user as an optional parameter to the
+*	cl_qpool_init function.
+*
+*	The destructor is invoked once per allocated object, allowing the user
+*	to perform any necessary cleanup. Users should not attempt to deallocate
+*	the memory for the object, as the quick pool manages object
+*	allocation and deallocation.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_init
+*********/
+
+/****s* Component Library: Quick Pool/cl_qpool_t
+* NAME
+*	cl_qpool_t
+*
+* DESCRIPTION
+*	Quick pool structure.
+*
+*	The cl_qpool_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_qpool {
+	cl_qcpool_t qcpool;
+	cl_pfn_qpool_init_t pfn_init;
+	cl_pfn_qpool_dtor_t pfn_dtor;
+	const void *context;
+} cl_qpool_t;
+/*
+* FIELDS
+*	qcpool
+*		Quick composite pool that manages all objects.
+*
+*	pfn_init
+*		Pointer to the user's initializer callback, used by the pool
+*		to translate the quick composite pool's initializer callback to
+*		a quick pool initializer callback.
+*
+*	pfn_dtor
+*		Pointer to the user's destructor callback, used by the pool
+*		to translate the quick composite pool's destructor callback to
+*		a quick pool destructor callback.
+*
+*	context
+*		User's provided context for callback functions, used by the pool
+*		to when invoking callbacks.
+*
+* SEE ALSO
+*	Quick Pool
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_construct
+* NAME
+*	cl_qpool_construct
+*
+* DESCRIPTION
+*	The cl_qpool_construct function constructs a quick pool.
+*
+* SYNOPSIS
+*/
+void cl_qpool_construct(IN cl_qpool_t * const p_pool);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_qpool_init, cl_qpool_destroy, cl_is_qpool_inited.
+*
+*	Calling cl_qpool_construct is a prerequisite to calling any other
+*	quick pool function except cl_pool_init.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_init, cl_qpool_destroy, cl_is_qpool_inited.
+*********/
+
+/****f* Component Library: Quick Pool/cl_is_qpool_inited
+* NAME
+*	cl_is_qpool_inited
+*
+* DESCRIPTION
+*	The cl_is_qpool_inited function returns whether a quick pool was
+*	successfully initialized.
+*
+* SYNOPSIS
+*/
+static inline uint32_t cl_is_qpool_inited(IN const cl_qpool_t * const p_pool)
+{
+	/* CL_ASSERT that a non-null pointer is provided. */
+	CL_ASSERT(p_pool);
+	return (cl_is_qcpool_inited(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure whose initialization state
+*		to check.
+*
+* RETURN VALUES
+*	TRUE if the quick pool was initialized successfully.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	Allows checking the state of a quick pool to determine if
+*	invoking member functions is appropriate.
+*
+* SEE ALSO
+*	Quick Pool
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_init
+* NAME
+*	cl_qpool_init
+*
+* DESCRIPTION
+*	The cl_qpool_init function initializes a quick pool for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_qpool_init(IN cl_qpool_t * const p_pool,
+	      IN const size_t min_size,
+	      IN const size_t max_size,
+	      IN const size_t grow_size,
+	      IN const size_t object_size,
+	      IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL,
+	      IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL,
+	      IN const void *const context);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure to initialize.
+*
+*	min_size
+*		[in] Minimum number of objects that the pool should support. All
+*		necessary allocations to allow storing the minimum number of items
+*		are performed at initialization time, and all necessary callbacks
+*		successfully invoked.
+*
+*	max_size
+*		[in] Maximum number of objects to which the pool is allowed to grow.
+*		A value of zero specifies no maximum.
+*
+*	grow_size
+*		[in] Number of objects to allocate when incrementally growing the pool.
+*		A value of zero disables automatic growth.
+*
+*	object_size
+*		[in] Size, in bytes, of each object.
+*
+*	pfn_initializer
+*		[in] Initialization callback to invoke for every new object when
+*		growing the pool. This parameter is optional and may be NULL. If NULL,
+*		the pool assumes the cl_pool_item_t structure describing objects is
+*		located at the head of each object. See the cl_pfn_qpool_init_t
+*		function type declaration for details about the callback function.
+*
+*	pfn_destructor
+*		[in] Destructor callback to invoke for every object before memory for
+*		that object is freed. This parameter is optional and may be NULL.
+*		See the cl_pfn_qpool_dtor_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the quick pool was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the
+*	quick pool.
+*
+*	CL_INVALID_SETTING if a the maximum size is non-zero and less than the
+*	minimum size.
+*
+*	Other cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter.
+*
+* NOTES
+*	cl_qpool_init initializes, and if necessary, grows the pool to
+*	the capacity desired.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_construct, cl_qpool_destroy,
+*	cl_qpool_get, cl_qpool_put, cl_qpool_grow,
+*	cl_qpool_count, cl_pfn_qpool_init_t, cl_pfn_qpool_init_t,
+*	cl_pfn_qpool_dtor_t
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_destroy
+* NAME
+*	cl_qpool_destroy
+*
+* DESCRIPTION
+*	The cl_qpool_destroy function destroys a quick pool.
+*
+* SYNOPSIS
+*/
+static inline void cl_qpool_destroy(IN cl_qpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	cl_qcpool_destroy(&p_pool->qcpool);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	All memory allocated for objects is freed. The destructor callback,
+*	if any, will be invoked for every allocated object. Further operations
+*	on the pool should not be attempted after cl_qpool_destroy
+*	is invoked.
+*
+*	This function should only be called after a call to
+*	cl_qpool_construct or cl_qpool_init.
+*
+*	In a debug build, cl_qpool_destroy asserts that all objects are in
+*	the pool.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_construct, cl_qpool_init
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_count
+* NAME
+*	cl_qpool_count
+*
+* DESCRIPTION
+*	The cl_qpool_count function returns the number of available objects
+*	in a quick pool.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_qpool_count(IN cl_qpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_count(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure for which the number of
+*		available objects is requested.
+*
+* RETURN VALUE
+*	Returns the number of objects available in the specified quick pool.
+*
+* SEE ALSO
+*	Quick Pool
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_get
+* NAME
+*	cl_qpool_get
+*
+* DESCRIPTION
+*	The cl_qpool_get function retrieves an object from a
+*	quick pool.
+*
+* SYNOPSIS
+*/
+static inline cl_pool_item_t *cl_qpool_get(IN cl_qpool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_get(&p_pool->qcpool));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure from which to retrieve
+*		an object.
+*
+* RETURN VALUES
+*	Returns a pointer to a cl_pool_item_t for an object.
+*
+*	Returns NULL if the pool is empty and can not be grown automatically.
+*
+* NOTES
+*	cl_qpool_get returns the object at the head of the pool. If the pool is
+*	empty, it is automatically grown to accommodate this request unless the
+*	grow_size parameter passed to the cl_qpool_init function was zero.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_get_tail, cl_qpool_put, cl_qpool_grow, cl_qpool_count
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_put
+* NAME
+*	cl_qpool_put
+*
+* DESCRIPTION
+*	The cl_qpool_put function returns an object to the head of a quick pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qpool_put(IN cl_qpool_t * const p_pool,
+	     IN cl_pool_item_t * const p_pool_item)
+{
+	CL_ASSERT(p_pool);
+	cl_qcpool_put(&p_pool->qcpool, p_pool_item);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure to which to return
+*		an object.
+*
+*	p_pool_item
+*		[in] Pointer to a cl_pool_item_t structure for the object
+*		being returned.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_qpool_put places the returned object at the head of the pool.
+*
+*	The object specified by the p_pool_item parameter must have been
+*	retrieved from the pool by a previous call to cl_qpool_get.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_put_tail, cl_qpool_get
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_put_list
+* NAME
+*	cl_qpool_put_list
+*
+* DESCRIPTION
+*	The cl_qpool_put_list function returns a list of objects to the head
+*	of a quick pool.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_qpool_put_list(IN cl_qpool_t * const p_pool, IN cl_qlist_t * const p_list)
+{
+	CL_ASSERT(p_pool);
+	cl_qcpool_put_list(&p_pool->qcpool, p_list);
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure to which to return
+*		a list of objects.
+*
+*	p_list
+*		[in] Pointer to a cl_qlist_t structure for the list of objects
+*		being returned.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_qpool_put_list places the returned objects at the head of the pool.
+*
+*	The objects in the list specified by the p_list parameter must have been
+*	retrieved from the pool by a previous call to cl_qpool_get.
+*
+* SEE ALSO
+*	Quick Pool, cl_qpool_put, cl_qpool_put_tail, cl_qpool_get
+*********/
+
+/****f* Component Library: Quick Pool/cl_qpool_grow
+* NAME
+*	cl_qpool_grow
+*
+* DESCRIPTION
+*	The cl_qpool_grow function grows a quick pool by
+*	the specified number of objects.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+cl_qpool_grow(IN cl_qpool_t * const p_pool, IN const size_t obj_count)
+{
+	CL_ASSERT(p_pool);
+	return (cl_qcpool_grow(&p_pool->qcpool, obj_count));
+}
+
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to a cl_qpool_t structure whose capacity to grow.
+*
+*	obj_count
+*		[in] Number of objects by which to grow the pool.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the quick pool grew successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the
+*	quick pool.
+*
+*	cl_status_t value returned by optional initialization callback function
+*	specified by the pfn_initializer parameter passed to the
+*	cl_qpool_init function.
+*
+* NOTES
+*	It is not necessary to call cl_qpool_grow if the pool is
+*	configured to grow automatically.
+*
+* SEE ALSO
+*	Quick Pool
+*********/
+
+END_C_DECLS
+#endif				/* _CL_QUICK_POOL_H_ */
diff --git a/include/complib/cl_spinlock.h b/include/complib/cl_spinlock.h
new file mode 100644
index 0000000..1a04b56
--- /dev/null
+++ b/include/complib/cl_spinlock.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of spin lock object.
+ */
+
+#ifndef _CL_SPINLOCK_H_
+#define _CL_SPINLOCK_H_
+
+#include <complib/cl_spinlock_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Public/Spinlock
+* NAME
+*	Spinlock
+*
+* DESCRIPTION
+*	Spinlock provides synchronization between threads for exclusive access to
+*	a resource.
+*
+*	The spinlock functions manipulate a cl_spinlock_t structure which should
+*	be treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_spinlock_t
+*
+*	Initialization:
+*		cl_spinlock_construct, cl_spinlock_init, cl_spinlock_destroy
+*
+*	Manipulation
+*		cl_spinlock_acquire, cl_spinlock_release
+*		cl_spinlock_acquire_irq, cl_spinlock_release_irq
+*********/
+/****f* Component Library: Spinlock/cl_spinlock_construct
+* NAME
+*	cl_spinlock_construct
+*
+* DESCRIPTION
+*	The cl_spinlock_construct function initializes the state of a
+*	spin lock.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_construct(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_spinlock_destroy without first calling
+*	cl_spinlock_init.
+*
+*	Calling cl_spinlock_construct is a prerequisite to calling any other
+*	spin lock function except cl_spinlock_init.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_init, cl_spinlock_destroy
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_init
+* NAME
+*	cl_spinlock_init
+*
+* DESCRIPTION
+*	The cl_spinlock_init function initializes a spin lock for use.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_spinlock_init(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to initialize.
+*
+* RETURN VALUES
+*	CL_SUCCESS if initialization succeeded.
+*
+*	CL_ERROR if initialization failed. Callers should call
+*	cl_spinlock_destroy to clean up any resources allocated during
+*	initialization.
+*
+* NOTES
+*	Initialize the spin lock structure. Allows calling cl_spinlock_aquire
+*	and cl_spinlock_release.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_construct, cl_spinlock_destroy,
+*	cl_spinlock_acquire, cl_spinlock_acquire_irq,
+*	cl_spinlock_release, cl_spinlock_release
+*	cl_spinlock_release_irq, cl_spinlock_release_irq
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_destroy
+* NAME
+*	cl_spinlock_destroy
+*
+* DESCRIPTION
+*	The cl_spinlock_destroy function performs all necessary cleanup of a
+*	spin lock.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_destroy(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Performs any necessary cleanup of a spin lock. This function must only
+*	be called if either cl_spinlock_construct or cl_spinlock_init has been
+*	called.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_construct, cl_spinlock_init
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_acquire
+* NAME
+*	cl_spinlock_acquire
+*
+* DESCRIPTION
+*	The cl_spinlock_acquire function acquires a spin lock.
+*	This version of lock does not prevent an interrupt from
+*	occuring on the processor on which the code is being
+*	executed. To protect from an interrupt level resource
+*	use the cl_spinlock_acquire_irq function.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_acquire(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to acquire.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_acquire_irq, cl_spinlock_release
+*	cl_spinlock_release_irq
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_acquire_irq
+* NAME
+*	cl_spinlock_acquire_irq
+*
+* DESCRIPTION
+*	The cl_spinlock_acquire_irq function acquires a spin lock and protects
+*	the current processor from taking interrupts. If you need to protect
+*	a variable from an interrupt resource, use this version to acquire
+*	a lock.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_acquire_irq(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to acquire.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_release_irq
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_release
+* NAME
+*	cl_spinlock_release
+*
+* DESCRIPTION
+*	The cl_spinlock_release function releases a spin lock object.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_release(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to release.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Releases a spin lock after a call to cl_spinlock_acquire.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_acquire
+*********/
+
+/****f* Component Library: Spinlock/cl_spinlock_release_irq
+* NAME
+*	cl_spinlock_release_irq
+*
+* DESCRIPTION
+*	The cl_spinlock_release_irq function releases a spin lock object.
+*
+* SYNOPSIS
+*/
+void cl_spinlock_release_irq(IN cl_spinlock_t * const p_spinlock);
+/*
+* PARAMETERS
+*	p_spin_lock
+*		[in] Pointer to a spin lock structure to release.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Releases a spin lock after a call to cl_spinlock_acquire.
+*
+* SEE ALSO
+*	Spinlock, cl_spinlock_acquire_irq
+*********/
+
+END_C_DECLS
+#endif				/* _CL_SPINLOCK_H_ */
diff --git a/include/complib/cl_spinlock_osd.h b/include/complib/cl_spinlock_osd.h
new file mode 100644
index 0000000..beb6405
--- /dev/null
+++ b/include/complib/cl_spinlock_osd.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Implementation of spin lock object.
+ */
+
+#ifndef _CL_SPINLOCK_OSD_H_
+#define _CL_SPINLOCK_OSD_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#include <complib/cl_types.h>
+#include <pthread.h>		/* usr/include/ */
+typedef struct _cl_spinlock_t {
+	pthread_mutex_t mutex;
+	cl_state_t state;
+} cl_spinlock_t;
+
+END_C_DECLS
+#endif				/* _CL_SPINLOCK_OSD_H_ */
diff --git a/include/complib/cl_thread.h b/include/complib/cl_thread.h
new file mode 100644
index 0000000..0a622a1
--- /dev/null
+++ b/include/complib/cl_thread.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of thread abstraction and thread related operations.
+ */
+
+#ifndef _CL_THREAD_H_
+#define _CL_THREAD_H_
+
+#include <complib/cl_thread_osd.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****i* Component Library/Thread
+* NAME
+*	Thread
+*
+* DESCRIPTION
+*	The Thread provides a separate thread of execution.
+*
+*	The cl_thread_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*********/
+/****d* Component Library: Thread/cl_pfn_thread_callback_t
+* NAME
+*	cl_pfn_thread_callback_t
+*
+* DESCRIPTION
+*	The cl_pfn_thread_callback_t function type defines the prototype
+*	for functions invoked by thread objects
+*
+* SYNOPSIS
+*/
+typedef void (*cl_pfn_thread_callback_t) (IN void *context);
+/*
+* PARAMETERS
+*	context
+*		[in] Value specified in a call to cl_thread_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function provided by users as a parameter to cl_thread_init.
+*
+* SEE ALSO
+*	Thread Pool
+*********/
+
+/****i* Component Library: Thread/cl_thread_t
+* NAME
+*	cl_thread_t
+*
+* DESCRIPTION
+*	Thread structure.
+*
+*	The cl_thread_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_thread {
+	cl_thread_osd_t osd;
+	cl_pfn_thread_callback_t pfn_callback;
+	const void *context;
+	char name[16];
+} cl_thread_t;
+/*
+* FIELDS
+*	osd
+*		Implementation specific structure for managing thread information.
+*
+*	pfn_callback
+*		Callback function for the thread to invoke.
+*
+*	context
+*		Context to pass to the thread callback function.
+*
+*	name
+*		Name to assign to the thread.
+*
+* SEE ALSO
+*	Thread
+*********/
+
+/****i* Component Library: Thread/cl_thread_construct
+* NAME
+*	cl_thread_construct
+*
+* DESCRIPTION
+*	The cl_thread_construct function initializes the state of a thread.
+*
+* SYNOPSIS
+*/
+void cl_thread_construct(IN cl_thread_t * const p_thread);
+/*
+* PARAMETERS
+*	p_thread
+*		[in] Pointer to a cl_thread_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_thread_destroy without first calling cl_thread_init.
+*
+*	Calling cl_thread_construct is a prerequisite to calling any other
+*	thread function except cl_thread_init.
+*
+* SEE ALSO
+*	Thread, cl_thread_init, cl_thread_destroy
+*********/
+
+/****i* Component Library: Thread/cl_thread_init
+* NAME
+*	cl_thread_init
+*
+* DESCRIPTION
+*	The cl_thread_init function creates a new thread of execution.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_thread_init(IN cl_thread_t * const p_thread,
+	       IN cl_pfn_thread_callback_t pfn_callback,
+	       IN const void *const context, IN const char *const name);
+/*
+* PARAMETERS
+*	p_thread
+*		[in] Pointer to a cl_thread_t structure to initialize.
+*
+*	pfn_callback
+*		[in] Address of a function to be invoked by a thread.
+*		See the cl_pfn_thread_callback_t function type definition for
+*		details about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+*	name
+*		[in] Name to associate with the thread.  The name may be up to 16
+*		characters, including a terminating null character.
+*
+* RETURN VALUES
+*	CL_SUCCESS if thread creation succeeded.
+*
+*	CL_ERROR if thread creation failed.
+*
+* NOTES
+*	The thread created with cl_thread_init will invoke the callback
+*	specified by the callback parameter with context as single parameter.
+*
+*	The callback function is invoked once, and the thread exits when the
+*	callback returns.
+*
+*	It is invalid to call cl_thread_destroy from the callback function,
+*	as doing so will result in a deadlock.
+*
+* SEE ALSO
+*	Thread, cl_thread_construct, cl_thread_destroy, cl_thread_suspend,
+*	cl_thread_stall, cl_pfn_thread_callback_t
+*********/
+
+/****i* Component Library: Thread/cl_thread_destroy
+* NAME
+*	cl_thread_destroy
+*
+* DESCRIPTION
+*	The cl_thread_destroy function performs any necessary cleanup to free
+*	resources associated with the specified thread.
+*
+* SYNOPSIS
+*/
+void cl_thread_destroy(IN cl_thread_t * const p_thread);
+/*
+* PARAMETERS
+*	p_thread
+*		[in] Pointer to a cl_thread_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function blocks until the thread exits and must not be called by the
+*	thread itself.  Callers must therefore ensure that such a blocking call is
+*	possible from the context of the call.
+*
+*	This function must only be called after a call to cl_thread_construct or
+*	cl_thread_init.
+*
+* SEE ALSO
+*	Thread, cl_thread_construct, cl_thread_init
+*********/
+
+/****f* Component Library: Thread/cl_thread_suspend
+* NAME
+*	cl_thread_suspend
+*
+* DESCRIPTION
+*	The cl_thread_suspend function suspends the calling thread for a minimum
+*	of the specified number of milliseconds.
+*
+* SYNOPSIS
+*/
+void cl_thread_suspend(IN const uint32_t pause_ms);
+/*
+* PARAMETERS
+*	pause_ms
+*		[in] Number of milliseconds to suspend the calling thread.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function should only be called if it is valid for the caller's thread
+*	to enter a wait state. For stalling a thread that cannot enter a wait
+*	state, callers should use cl_thread_stall.
+*
+* SEE ALSO
+*	Thread, cl_thread_stall
+*********/
+
+/****f* Component Library: Thread/cl_thread_stall
+* NAME
+*	cl_thread_stall
+*
+* DESCRIPTION
+*	The cl_thread_stall function stalls the calling thread for a minimum of
+*	the specified number of microseconds.
+*
+* SYNOPSIS
+*/
+void cl_thread_stall(IN const uint32_t pause_us);
+/*
+* PARAMETERS
+*	pause_us
+*		[in] Number of microseconds to stall the calling thread.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	The cl_thread_stall function performs a busy wait for the specified
+*	number of microseconds. Care should be taken when using this function as
+*	it does not relinquish its quantum of operation. For longer wait
+*	operations, users should call cl_thread_suspend if possible.
+*
+* SEE ALSO
+*	Thread, cl_thread_suspend
+*********/
+
+/****f* Component Library: Thread/cl_proc_count
+* NAME
+*	cl_proc_count
+*
+* DESCRIPTION
+*	The cl_proc_count function returns the number of processors in the system.
+*
+* SYNOPSIS
+*/
+int cl_proc_count(void);
+/*
+* RETURN VALUE
+*	Returns the number of processors in the system.
+*********/
+
+/****i* Component Library: Thread/cl_is_current_thread
+* NAME
+*	cl_is_current_thread
+*
+* DESCRIPTION
+*	The cl_is_current_thread function compares the calling thread to the
+*	specified thread and returns whether they are the same.
+*
+* SYNOPSIS
+*/
+boolean_t cl_is_current_thread(IN const cl_thread_t * const p_thread);
+/*
+* PARAMETERS
+*	p_thread
+*		[in] Pointer to a cl_thread_t structure to compare to the
+*		caller's thead.
+*
+* RETURN VALUES
+*	TRUE if the thread specified by the p_thread parameter is the
+*	calling thread.
+*
+*	FALSE otherwise.
+*
+* SEE ALSO
+*	Thread, cl_threadinit_t
+*********/
+
+/****f* Component Library: Thread/cl_is_blockable
+* NAME
+*	cl_is_blockable
+*
+* DESCRIPTION
+*	The cl_is_blockable indicates if the current caller context is
+*	blockable.
+*
+* SYNOPSIS
+*/
+boolean_t cl_is_blockable(void);
+/*
+* RETURN VALUE
+*	TRUE
+*		Current caller context can be blocked, i.e it is safe to perform
+*		a sleep, or call a down operation on a semaphore.
+*
+*********/
+
+END_C_DECLS
+#endif				/* _CL_THREAD_H_ */
diff --git a/include/complib/cl_thread_osd.h b/include/complib/cl_thread_osd.h
new file mode 100644
index 0000000..ad7df90
--- /dev/null
+++ b/include/complib/cl_thread_osd.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of thread abstraction and thread related operations.
+ */
+
+#ifndef _CL_THREAD_OSD_H_
+#define _CL_THREAD_OSD_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#include <complib/cl_types.h>
+#include <complib/cl_event.h>
+#include <pthread.h>
+/* Linux user mode thread object structure definition. */
+typedef struct _cl_thread_osd_t {
+	pthread_t id;
+	cl_state_t state;
+} cl_thread_osd_t;
+
+static inline boolean_t cl_is_blockable(void)
+{
+	return TRUE;
+}
+
+END_C_DECLS
+#endif				/* _CL_THREAD_OSD_H_ */
diff --git a/include/complib/cl_threadpool.h b/include/complib/cl_threadpool.h
new file mode 100644
index 0000000..e9b2c78
--- /dev/null
+++ b/include/complib/cl_threadpool.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of thread pool.
+ */
+
+#ifndef _CL_THREAD_POOL_H_
+#define _CL_THREAD_POOL_H_
+
+#include <pthread.h>
+#include <complib/cl_types.h>
+#include <complib/cl_thread.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/Thread Pool
+* NAME
+*	Thread Pool
+*
+* DESCRIPTION
+*	The Thread Pool manages a user specified number of threads.
+*
+*	Each thread in the thread pool waits for a user initiated signal before
+*	invoking a user specified callback function. All threads in the thread
+*	pool invoke the same callback function.
+*
+*	The thread pool functions operate on a cl_thread_pool_t structure which
+*	should be treated as opaque, and should be manipulated only through the
+*	provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_thread_pool_t
+*
+*	Initialization:
+*		cl_thread_pool_construct, cl_thread_pool_init, cl_thread_pool_destroy
+*
+*	Manipulation
+*		cl_thread_pool_signal
+*********/
+/****s* Component Library: Thread Pool/cl_thread_pool_t
+* NAME
+*	cl_thread_pool_t
+*
+* DESCRIPTION
+*	Thread pool structure.
+*
+*	The cl_thread_pool_t structure should be treated as opaque, and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_thread_pool {
+	void (*pfn_callback) (void *);
+	void *context;
+	unsigned running_count;
+	unsigned events;
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+	pthread_t *tid;
+} cl_thread_pool_t;
+/*
+* FIELDS
+*	pfn_callback
+*		Callback function for the thread to invoke.
+*
+*	context
+*		Context to pass to the thread callback function.
+*
+*	running_count
+*		Number of threads running.
+*
+*	events
+*		events counter
+*
+*	mutex
+*		mutex for cond variable protection
+*
+*	cond
+*		conditional variable to signal an event to thread
+*
+*	tid
+*		array of allocated thread ids.
+*
+* SEE ALSO
+*	Thread Pool
+*********/
+
+/****f* Component Library: Thread Pool/cl_thread_pool_init
+* NAME
+*	cl_thread_pool_init
+*
+* DESCRIPTION
+*	The cl_thread_pool_init function creates the threads to be
+*	managed by a thread pool.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_thread_pool_init(IN cl_thread_pool_t * const p_thread_pool,
+		    IN unsigned count,
+		    IN void (*pfn_callback) (void *),
+		    IN void *context, IN const char *const name);
+/*
+* PARAMETERS
+*	p_thread_pool
+*		[in] Pointer to a thread pool structure to initialize.
+*
+*	thread_count
+*		[in] Number of threads to be managed by the thread pool.
+*
+*	pfn_callback
+*		[in] Address of a function to be invoked by a thread.
+*		See the cl_pfn_thread_callback_t function type definition for
+*		details about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+*	name
+*		[in] Name to associate with the threads.  The name may be up to 16
+*		characters, including a terminating null character.  All threads
+*		created in the pool have the same name.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the thread pool creation succeeded.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to inititalize
+*	the thread pool.
+*
+*	CL_ERROR if the threads could not be created.
+*
+* NOTES
+*	cl_thread_pool_init creates and starts the specified number of threads.
+*	If thread_count is zero, the thread pool creates as many threads as there
+*	are processors in the system.
+*
+* SEE ALSO
+*	Thread Pool, cl_thread_pool_construct, cl_thread_pool_destroy,
+*	cl_thread_pool_signal, cl_pfn_thread_callback_t
+*********/
+
+/****f* Component Library: Thread Pool/cl_thread_pool_destroy
+* NAME
+*	cl_thread_pool_destroy
+*
+* DESCRIPTION
+*	The cl_thread_pool_destroy function performs any necessary cleanup
+*	for a thread pool.
+*
+* SYNOPSIS
+*/
+void cl_thread_pool_destroy(IN cl_thread_pool_t * const p_thread_pool);
+/*
+* PARAMETERS
+*	p_thread_pool
+*		[in] Pointer to a thread pool structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function blocks until all threads exit, and must therefore not
+*	be called from any of the thread pool's threads. Because of its blocking
+*	nature, callers of cl_thread_pool_destroy must ensure that entering a wait
+*	state is valid from the calling thread context.
+*
+*	This function should only be called after a call to
+*	cl_thread_pool_construct or cl_thread_pool_init.
+*
+* SEE ALSO
+*	Thread Pool, cl_thread_pool_construct, cl_thread_pool_init
+*********/
+
+/****f* Component Library: Thread Pool/cl_thread_pool_signal
+* NAME
+*	cl_thread_pool_signal
+*
+* DESCRIPTION
+*	The cl_thread_pool_signal function signals a single thread of
+*	the thread pool to invoke the thread pool's callback function.
+*
+* SYNOPSIS
+*/
+cl_status_t cl_thread_pool_signal(IN cl_thread_pool_t * const p_thread_pool);
+/*
+* PARAMETERS
+*	p_thread_pool
+*		[in] Pointer to a thread pool structure to signal.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the thread pool was successfully signalled.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	Each call to this function wakes up at most one waiting thread in
+*	the thread pool.
+*
+*	If all threads are running, cl_thread_pool_signal has no effect.
+*
+* SEE ALSO
+*	Thread Pool
+*********/
+
+END_C_DECLS
+#endif				/* _CL_THREAD_POOL_H_ */
diff --git a/include/complib/cl_timer.h b/include/complib/cl_timer.h
new file mode 100644
index 0000000..194e374
--- /dev/null
+++ b/include/complib/cl_timer.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of timer abstraction.
+ */
+
+#ifndef _CL_TIMER_H_
+#define _CL_TIMER_H_
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* Component Library/Timer
+* NAME
+*	Timer
+*
+* DESCRIPTION
+*	The Timer provides the ability to schedule a function to be invoked at
+*	a given time in the future.
+*
+*	The timer callback function must not perform any blocking operations.
+*
+*	The timer functions operate on a cl_timer_t structure which should be
+*	treated as opaque and should be manipulated only through the provided
+*	functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_timer_t
+*
+*	Callbacks:
+*		cl_pfn_timer_callback_t
+*
+*	Initialization:
+*		cl_timer_construct, cl_timer_init, cl_timer_destroy
+*
+*	Manipulation:
+*		cl_timer_start, cl_timer_stop
+*********/
+/****d* Component Library: Timer/cl_pfn_timer_callback_t
+* NAME
+*	cl_pfn_timer_callback_t
+*
+* DESCRIPTION
+*	The cl_pfn_timer_callback_t function type defines the prototype for
+*	functions used to notify users of a timer expiration.
+*
+* SYNOPSIS
+*/
+typedef void (*cl_pfn_timer_callback_t) (IN void *context);
+/*
+* PARAMETERS
+*	context
+*		[in] Value specified in a previous call to cl_timer_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_timer_init function.
+*
+* SEE ALSO
+*	Timer, cl_timer_init
+*********/
+
+/*
+ * This include file defines the timer structure, and depends on the timer
+ * callback definition.
+ */
+#include <complib/cl_timer_osd.h>
+
+/****f* Component Library: Timer/cl_timer_construct
+* NAME
+*	cl_timer_construct
+*
+* DESCRIPTION
+*	The cl_timer_construct function initializes the state of a timer.
+*
+* SYNOPSIS
+*/
+void cl_timer_construct(IN cl_timer_t * const p_timer);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure whose state to initialize.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_timer_destroy without first calling cl_timer_init.
+*
+*	Calling cl_timer_construct is a prerequisite to calling any other
+*	timer function except cl_timer_init.
+*
+* SEE ALSO
+*	Timer, cl_timer_init, cl_timer_destroy
+*********/
+
+/****f* Component Library: Timer/cl_timer_init
+* NAME
+*	cl_timer_init
+*
+* DESCRIPTION
+*	The cl_timer_init function initializes a timer for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_timer_init(IN cl_timer_t * const p_timer,
+	      IN cl_pfn_timer_callback_t pfn_callback,
+	      IN const void *const context);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure to initialize.
+*
+*	pfn_callback
+*		[in] Address of a callback function to be invoked when a timer expires.
+*		See the cl_pfn_timer_callback_t function type definition for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the timer was successfully initialized.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	Allows calling cl_timer_start and cl_timer_stop.
+*
+* SEE ALSO
+*	Timer, cl_timer_construct, cl_timer_destroy, cl_timer_start,
+*	cl_timer_stop, cl_pfn_timer_callback_t
+*********/
+
+/****f* Component Library: Timer/cl_timer_destroy
+* NAME
+*	cl_timer_destroy
+*
+* DESCRIPTION
+*	The cl_timer_destroy function performs any necessary cleanup of a timer.
+*
+* SYNOPSIS
+*/
+void cl_timer_destroy(IN cl_timer_t * const p_timer);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_timer_destroy cancels any pending callbacks.
+*
+*	This function should only be called after a call to cl_timer_construct
+*	or cl_timer_init.
+*
+* SEE ALSO
+*	Timer, cl_timer_construct, cl_timer_init
+*********/
+
+/****f* Component Library: Timer/cl_timer_start
+* NAME
+*	cl_timer_start
+*
+* DESCRIPTION
+*	The cl_timer_start function sets a timer to expire after a given interval.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure to schedule.
+*
+*	time_ms
+*		[in] Time, in milliseconds, before the timer should expire.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the timer was successfully scheduled.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	cl_timer_start implicitly stops the timer before being scheduled.
+*
+*	The interval specified by the time_ms parameter is a minimum interval.
+*	The timer is guaranteed to expire no sooner than the desired interval, but
+*	may take longer to expire.
+*
+* SEE ALSO
+*	Timer, cl_timer_stop, cl_timer_trim
+*********/
+
+/****f* Component Library: Timer/cl_timer_stop
+* NAME
+*	cl_timer_stop
+*
+* DESCRIPTION
+*	The cl_timer_stop function stops a pending timer from expiring.
+*
+* SYNOPSIS
+*/
+void cl_timer_stop(IN cl_timer_t * const p_timer);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Timer, cl_timer_start, cl_timer_trim
+*********/
+
+/****f* Component Library: Timer/cl_timer_trim
+* NAME
+*	cl_timer_trim
+*
+* DESCRIPTION
+*	The cl_timer_trim function pulls in the absolute expiration
+*	time of a timer if the current expiration time exceeds the specified
+*	interval.
+*
+*	sets a timer to expire after a given
+*	interval if that interval is less than the current timer expiration.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_timer_trim(IN cl_timer_t * const p_timer, IN const uint32_t time_ms);
+/*
+* PARAMETERS
+*	p_timer
+*		[in] Pointer to a cl_timer_t structure to schedule.
+*
+*	time_ms
+*		[in] Maximum time, in milliseconds, before the timer should expire.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the timer was successfully scheduled.
+*
+*	CL_ERROR otherwise.
+*
+* NOTES
+*	cl_timer_trim has no effect if the time interval is greater than the
+*	remaining time when the timer is set.
+*
+*	If the new interval time is less than the remaining time, cl_timer_trim
+*	implicitly stops the timer before resetting it.
+*
+*	If the timer is reset, it is guaranteed to expire no sooner than the
+*	new interval, but may take longer to expire.
+*
+* SEE ALSO
+*	Timer, cl_timer_start, cl_timer_stop
+*********/
+
+/****f* Component Library: Time Stamp/cl_get_time_stamp
+* NAME
+*	cl_get_time_stamp
+*
+* DESCRIPTION
+*	The cl_get_time_stamp function returns the current time stamp in
+*	microseconds since the system was booted.
+*
+* SYNOPSIS
+*/
+uint64_t cl_get_time_stamp(void);
+/*
+* RETURN VALUE
+*	Time elapsed, in microseconds, since the system was booted.
+*
+* SEE ALSO
+*	Timer, cl_get_time_stamp_sec
+*********/
+
+/****f* Component Library: Time Stamp/cl_get_time_stamp_sec
+* NAME
+*	cl_get_time_stamp_sec
+*
+* DESCRIPTION
+*	The cl_get_time_stamp_sec function returns the current time stamp in
+*	seconds since the system was booted.
+*
+* SYNOPSIS
+*/
+uint32_t cl_get_time_stamp_sec(void);
+/*
+* RETURN VALUE
+*	Time elapsed, in seconds, since the system was booted.
+*
+* SEE ALSO
+*	Timer, cl_get_time_stamp
+*********/
+
+END_C_DECLS
+#endif				/* _CL_TIMER_H_ */
diff --git a/include/complib/cl_timer_osd.h b/include/complib/cl_timer_osd.h
new file mode 100644
index 0000000..ed36fea
--- /dev/null
+++ b/include/complib/cl_timer_osd.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of timer object.
+ */
+
+#ifndef _CL_TIMER_OSD_H_
+#define _CL_TIMER_OSD_H_
+
+#include <complib/cl_types.h>
+#include <complib/cl_spinlock.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#include <complib/cl_qlist.h>
+#include <pthread.h>
+typedef enum _cl_timer_state {
+	CL_TIMER_IDLE,
+	CL_TIMER_QUEUED,
+	CL_TIMER_RUNNING
+} cl_timer_state_t;
+
+typedef struct _cl_timer_t {
+	cl_list_item_t list_item;
+	cl_timer_state_t timer_state;
+	cl_state_t state;
+	cl_pfn_timer_callback_t pfn_callback;
+	const void *context;
+	pthread_cond_t cond;
+	struct timespec timeout;
+} cl_timer_t;
+
+/* Internal functions to create the timer provider. */
+cl_status_t __cl_timer_prov_create(void);
+
+/* Internal function to destroy the timer provider. */
+void __cl_timer_prov_destroy(void);
+
+END_C_DECLS
+#endif				/* _CL_TIMER_OSD_H_ */
diff --git a/include/complib/cl_types.h b/include/complib/cl_types.h
new file mode 100644
index 0000000..84f629d
--- /dev/null
+++ b/include/complib/cl_types.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Defines standard return codes, keywords, macros, and debug levels.
+ */
+
+#ifdef __WIN__
+#pragma warning(disable : 4996)
+#endif
+
+#ifndef _CL_TYPES_H_
+#define _CL_TYPES_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#include <complib/cl_types_osd.h>
+#include <stddef.h>
+typedef uint16_t net16_t;
+typedef uint32_t net32_t;
+typedef uint64_t net64_t;
+
+/* explicit cast of void* to uint32_t */
+#ifndef ASSERT_VOIDP2UINTN
+#if __WORDSIZE == 64
+#define ASSERT_VOIDP2UINTN(var) \
+	CL_ASSERT( (intptr_t)var <= 0xffffffffffffffffL )
+#else				/*  __WORDSIZE == 64 */
+#if __WORDSIZE == 32
+  /* need to cast carefully to avoid the warining of un-needed check */
+#define ASSERT_VOIDP2UINTN(var) \
+	CL_ASSERT( (intptr_t)var <= 0x100000000ULL )
+#else				/*  __WORDSIZE == 32 */
+#error "Need to know WORDSIZE to tell how to cast to unsigned long int"
+#endif				/*  __WORDSIZE == 32 */
+#endif				/*  __WORDSIZE == 64 */
+#endif
+
+/* explicit casting of void* to long */
+#ifndef CAST_P2LONG
+#define CAST_P2LONG(var) ((intptr_t)(var))
+#endif
+
+/****d* Component Library: Pointer Manipulation/offsetof
+* NAME
+*	offsetof
+*
+* DESCRIPTION
+*	The offsetof macro returns the offset of a member within a structure.
+*
+* SYNOPSIS
+*	uintn_t
+*	offsetof(
+*		IN TYPE,
+*		IN MEMBER );
+*
+* PARAMETERS
+*	TYPE
+*		[in] Name of the structure containing the specified member.
+*
+*	MEMBER
+*		[in] Name of the member whose offset in the specified structure
+*		is to be returned.
+*
+* RETURN VALUE
+*	Number of bytes from the beginning of the structure to the
+*	specified member.
+*
+* SEE ALSO
+*	PARENT_STRUCT
+*********/
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((uintn_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/****d* Component Library: Pointer Manipulation/PARENT_STRUCT
+* NAME
+*	PARENT_STRUCT
+*
+* DESCRIPTION
+*	The PARENT_STRUCT macro returns a pointer to a structure
+*	given a name and pointer to one of its members.
+*
+* SYNOPSIS
+*	PARENT_TYPE*
+*	PARENT_STRUCT(
+*		IN void* const p_member,
+*		IN PARENT_TYPE,
+*		IN MEMBER_NAME );
+*
+* PARAMETERS
+*	p_member
+*		[in] Pointer to the MEMBER_NAME member of a PARENT_TYPE structure.
+*
+*	PARENT_TYPE
+*		[in] Name of the structure containing the specified member.
+*
+*	MEMBER_NAME
+*		[in] Name of the member whose address is passed in the p_member
+*		parameter.
+*
+* RETURN VALUE
+*	Pointer to a structure of type PARENT_TYPE whose MEMBER_NAME member is
+*	located at p_member.
+*
+* SEE ALSO
+*	offsetof
+*********/
+#define PARENT_STRUCT(p_member, PARENT_TYPE, MEMBER_NAME) \
+	((PARENT_TYPE*)((uint8_t*)(p_member) - offsetof(PARENT_TYPE, MEMBER_NAME)))
+
+/****d* Component Library/Parameter Keywords
+* NAME
+*	Parameter Keywords
+*
+* DESCRIPTION
+*	The Parameter Keywords can be used to clarify the usage of function
+*	parameters to users.
+*
+* VALUES
+*	IN
+*		Designates that the parameter is used as input to a function.
+*
+*	OUT
+*		Designates that the parameter's value will be set by the function.
+*
+*	OPTIONAL
+*		Designates that the parameter is optional, and may be NULL.
+*		The OPTIONAL keyword, if used, follows the parameter name.
+*
+* EXAMPLE
+*	// Function declaration.
+*	void*
+*	my_func(
+*	    IN void* const p_param1,
+*	    OUT void** const p_handle OPTIONAL );
+*
+* NOTES
+*	Multiple keywords can apply to a single parameter. The IN and OUT
+*	keywords precede the parameter type. The OPTIONAL
+*	keyword, if used, follows the parameter name.
+*********/
+#ifndef		IN
+#define		IN		/* Function input parameter */
+#endif
+#ifndef		OUT
+#define		OUT		/* Function output parameter */
+#endif
+#ifndef		OPTIONAL
+#define		OPTIONAL	/* Optional function parameter - NULL if not used */
+#endif
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%                  Function Returns And Completion Codes					 %%
+%%																			 %%
+%% The text for any addition to this enumerated type must be added to the	 %%
+%% string array defined in <cl_statustext.c>.								 %%
+%%																			 %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/****d* Component Library/Data Types
+* NAME
+*	Data Types
+*
+* DESCRIPTION
+*	The component library provides and uses explicitly sized types.
+*
+* VALUES
+*	char
+*		8-bit, defined by compiler.
+*
+*	void
+*		0-bit, defined by compiler.
+*
+*	int8_t
+*		8-bit signed integer.
+*
+*	uint8_t
+*		8-bit unsigned integer.
+*
+*	int16_t
+*		16-bit signed integer.
+*
+*	uint16_t
+*		16-bit unsigned integer.
+*
+*	net16_t
+*		16-bit network byte order value.
+*
+*	int32_t
+*		32-bit signed integer.
+*
+*	uint32_t
+*		32-bit unsigned integer.
+*
+*	net32_t
+*		32-bit network byte order value.
+*
+*	int64_t
+*		64-bit signed integer.
+*
+*	uint64_t
+*		64-bit unsigned integer.
+*
+*	net64_t
+*		64-bit network byte order value.
+*
+*	intn_t
+*		Signed natural sized integer.  32-bit on a 32-bit platform, 64-bit on
+*		a 64-bit platform.
+*
+*	uintn_t
+*		Unsigned natural sized integer.  32-bit on a 32-bit platform, 64-bit on
+*		a 64-bit platform.
+*
+*	boolean_t
+*		integral sized.  Set to TRUE or FALSE and used in logical expressions.
+*
+* NOTES
+*	Pointer types are not defined as these provide no value and can potentially
+*	lead to naming confusion.
+*********/
+
+/****d* Component Library: Data Types/cl_status_t
+* NAME
+*	cl_status_t
+*
+* DESCRIPTION
+*	The cl_status_t return types are used by the component library to
+*	provide detailed function return values.
+*
+* SYNOPSIS
+*/
+typedef enum _cl_status {
+	CL_SUCCESS = 0,
+	CL_ERROR,
+	CL_INVALID_STATE,
+	CL_INVALID_OPERATION,
+	CL_INVALID_SETTING,
+	CL_INVALID_PARAMETER,
+	CL_INSUFFICIENT_RESOURCES,
+	CL_INSUFFICIENT_MEMORY,
+	CL_INVALID_PERMISSION,
+	CL_COMPLETED,
+	CL_NOT_DONE,
+	CL_PENDING,
+	CL_TIMEOUT,
+	CL_CANCELED,
+	CL_REJECT,
+	CL_OVERRUN,
+	CL_NOT_FOUND,
+	CL_UNAVAILABLE,
+	CL_BUSY,
+	CL_DISCONNECT,
+	CL_DUPLICATE,
+
+	CL_STATUS_COUNT		/* should be the last value */
+} cl_status_t;
+/*
+* SEE ALSO
+*	Data Types, CL_STATUS_MSG
+*********/
+
+/* Status values above converted to text for easier printing. */
+extern const char *cl_status_text[];
+
+#ifndef cl_panic
+/****f* Component Library: Error Trapping/cl_panic
+* NAME
+*	cl_panic
+*
+* DESCRIPTION
+*	Halts execution of the current process.  Halts the system if called in
+*	from the kernel.
+*
+* SYNOPSIS
+*/
+void cl_panic(IN const char *const message, IN ...);
+/*
+* PARAMETERS
+*	message
+*		[in] ANSI string formatted identically as for a call to the standard C
+*		function printf describing the cause for the panic.
+*
+*	...
+*		[in] Extra parameters for string formatting, as defined for the
+*		standard C function printf.
+*
+* RETURN VALUE
+*	This function does not return.
+*
+* NOTES
+*	The formatting of the message string is the same as for printf
+*
+*	cl_panic sends the message to the current message logging target.
+*********/
+#endif				/* cl_panic */
+
+/****d* Component Library: Data Types/CL_STATUS_MSG
+* NAME
+*	CL_STATUS_MSG
+*
+* DESCRIPTION
+*	The CL_STATUS_MSG macro returns a textual representation of
+*	an cl_status_t code.
+*
+* SYNOPSIS
+*	const char*
+*	CL_STATUS_MSG(
+*		IN cl_status_t errcode );
+*
+* PARAMETERS
+*	errcode
+*		[in] cl_status_t code for which to return a text representation.
+*
+* RETURN VALUE
+*	Pointer to a string containing a textual representation of the errcode
+*	parameter.
+*
+* NOTES
+*	This function performs boundary checking on the cl_status_t value,
+*	masking off the upper 24-bits. If the value is out of bounds, the string
+*	"invalid status code" is returned.
+*
+* SEE ALSO
+*	cl_status_t
+*********/
+#define CL_STATUS_MSG( errcode ) \
+	((errcode < CL_STATUS_COUNT)?cl_status_text[errcode]:"invalid status code")
+
+#if !defined( FALSE )
+#define FALSE	0
+#endif				/* !defined( FALSE ) */
+
+#if !defined( TRUE )
+#define TRUE	(!FALSE)
+#endif				/* !defined( TRUE ) */
+
+/****d* Component Library: Unreferenced Parameters/UNUSED_PARAM
+* NAME
+*	UNUSED_PARAM
+*
+* DESCRIPTION
+*	The UNUSED_PARAM macro can be used to eliminates compiler warnings related
+*	to intentionally unused formal parameters in function implementations.
+*
+* SYNOPSIS
+*	UNUSED_PARAM( P )
+*
+* EXAMPLE
+*	void my_func( int32_t value )
+*	{
+*		UNUSED_PARAM( value );
+*	}
+*********/
+
+/****d* Component Library/Object States
+* NAME
+*	Object States
+*
+* DESCRIPTION
+*	The object states enumerated type defines the valid states of components.
+*
+* SYNOPSIS
+*/
+typedef enum _cl_state {
+	CL_UNINITIALIZED = 1,
+	CL_INITIALIZED,
+	CL_DESTROYING,
+	CL_DESTROYED
+} cl_state_t;
+/*
+* VALUES
+*	CL_UNINITIALIZED
+*		Indicates that initialization was not invoked successfully.
+*
+*	CL_INITIALIZED
+*		Indicates initialization was successful.
+*
+*	CL_DESTROYING
+*		Indicates that the object is undergoing destruction.
+*
+*	CL_DESTROYED
+*		Indicates that the object's destructor has already been called.  Most
+*		objects set their final state to CL_DESTROYED before freeing the
+*		memory associated with the object.
+*********/
+
+/****d* Component Library: Object States/cl_is_state_valid
+* NAME
+*	cl_is_state_valid
+*
+* DESCRIPTION
+*	The cl_is_state_valid function returns whether a state has a valid value.
+*
+* SYNOPSIS
+*/
+static inline boolean_t cl_is_state_valid(IN const cl_state_t state)
+{
+	return ((state == CL_UNINITIALIZED) || (state == CL_INITIALIZED) ||
+		(state == CL_DESTROYING) || (state == CL_DESTROYED));
+}
+
+/*
+* PARAMETERS
+*	state
+*		State whose value to validate.
+*
+* RETURN VALUES
+*	TRUE if the specified state has a valid value.
+*
+*	FALSE otherwise.
+*
+* NOTES
+*	This function is used in debug builds to check for valid states.  If an
+*	uninitialized object is passed, the memory for the state may cause the
+*	state to have an invalid value.
+*
+* SEE ALSO
+*	Object States
+*********/
+
+END_C_DECLS
+#endif				/* _DATA_TYPES_H_ */
diff --git a/include/complib/cl_types_osd.h b/include/complib/cl_types_osd.h
new file mode 100644
index 0000000..d12aa4c
--- /dev/null
+++ b/include/complib/cl_types_osd.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Defines sized datatypes for Linux User mode
+ *  exported sizes are int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t
+ *  int64_t, uint64_t. uintn_t is a polymorphic type, size is native size and
+ *  also size of the pointer.
+ */
+
+#ifndef _CL_TYPES_OSD_H_
+#define _CL_TYPES_OSD_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#if defined (_DEBUG_)
+#ifdef __IA64__
+#define cl_break() asm("   break 0")
+#else				/* __IA64__ */
+#define cl_break() asm("   int $3")
+#endif				/* __IA64__ */
+#else				/* _DEBUG_ */
+#define cl_break
+#endif
+#include <inttypes.h>
+#include <assert.h>
+#include <string.h>
+#if defined (_DEBUG_)
+#define CL_ASSERT	assert
+#else				/* _DEBUG_ */
+#define CL_ASSERT( __exp__ )
+#endif				/* _DEBUG_ */
+/*
+ * Types not explicitly defined are native to the platform.
+ */
+typedef unsigned long uintn_t;
+typedef long intn_t;
+typedef int boolean_t;
+typedef volatile int32_t atomic32_t;
+
+#ifndef NULL
+#define NULL	(void*)0
+#endif
+
+#define UNUSED_PARAM( P )
+
+END_C_DECLS
+#endif				/* _CL_TYPES_OSD_H_ */
diff --git a/include/complib/cl_vector.h b/include/complib/cl_vector.h
new file mode 100644
index 0000000..11c45f8
--- /dev/null
+++ b/include/complib/cl_vector.h
@@ -0,0 +1,945 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	This file contains vector definitions.  Vector provides dynmically
+ *	resizable array functionality.  Objects in a Vector are not relocated
+ *	when the array is resized.
+ */
+
+#ifndef _CL_VECTOR_H_
+#define _CL_VECTOR_H_
+
+#include <complib/cl_qlist.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/Vector
+* NAME
+*	Vector
+*
+* DESCRIPTION
+*	The Vector is a self-sizing array. Like a traditonal array, a vector
+*	allows efficient constant time access to elements with a specified index.
+*	A vector grows transparently as the user adds elements to the array.
+*
+*	As the vector grows in size, it does not relocate existing elements in
+*	memory. This allows using pointers to elements stored in a Vector.
+*
+*	Users can supply an initializer functions that allow a vector to ensure
+*	that new items added to the vector are properly initialized. A vector
+*	calls the initializer function on a per object basis when growing the
+*	array. The initializer is optional.
+*
+*	The initializer function can fail, and returns a cl_status_t. The vector
+*	will call the destructor function, if provided, for an element that
+*	failed initialization. If an initializer fails, a vector does not call
+*	the initializer for objects in the remainder of the new memory allocation.
+*
+*	The cl_vector_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SEE ALSO
+*	Structures:
+*		cl_vector_t
+*
+*	Callbacks:
+*		cl_pfn_vec_init_t, cl_pfn_vec_dtor_t, cl_pfn_vec_apply_t,
+*		cl_pfn_vec_find_t
+*
+*	Item Manipulation:
+*		cl_vector_set_obj, cl_vector_obj
+*
+*	Initialization:
+*		cl_vector_construct, cl_vector_init, cl_vector_destroy
+*
+*	Manipulation:
+*		cl_vector_get_capacity, cl_vector_set_capacity,
+*		cl_vector_get_size, cl_vector_set_size, cl_vector_set_min_size
+*		cl_vector_get_ptr, cl_vector_get, cl_vector_at, cl_vector_set
+*
+*	Search:
+*		cl_vector_find_from_start, cl_vector_find_from_end
+*		cl_vector_apply_func
+*********/
+/****d* Component Library: Vector/cl_pfn_vec_init_t
+* NAME
+*	cl_pfn_vec_init_t
+*
+* DESCRIPTION
+*	The cl_pfn_vec_init_t function type defines the prototype for functions
+*	used as initializer for elements being allocated by a vector.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_vec_init_t) (IN void *const p_element, IN void *context);
+/*
+* PARAMETERS
+*	p_element
+*		[in] Pointer to an element being added to a vector.
+*
+*	context
+*		[in] Context provided in a call to cl_vector_init.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS to indicate that the element was initialized successfully.
+*
+*	Other cl_status_t values will be returned by the cl_vector_init,
+*	cl_vector_set_size, and cl_vector_set_min_size functions.
+*
+*	In situations where the vector's size needs to grows in order to satisfy
+*	a call to cl_vector_set, a non-successful status returned by the
+*	initializer callback causes the growth to stop.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the initializer function provided by users as an optional parameter to
+*	the cl_vector_init function.
+*
+* SEE ALSO
+*	Vector, cl_vector_init
+*********/
+
+/****d* Component Library: Vector/cl_pfn_vec_dtor_t
+* NAME
+*	cl_pfn_vec_dtor_t
+*
+* DESCRIPTION
+*	The cl_pfn_vec_dtor_t function type defines the prototype for functions
+*	used as destructor for elements being deallocated from a vector.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_vec_dtor_t) (IN void *const p_element, IN void *context);
+/*
+* PARAMETERS
+*	p_element
+*		[in] Pointer to an element being deallocated from a vector.
+*
+*	context
+*		[in] Context provided in a call to cl_vector_init.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the destructor function provided by users as an optional parameter to
+*	the cl_vector_init function.
+*
+* SEE ALSO
+*	Vector, cl_vector_init
+*********/
+
+/****d* Component Library: Vector/cl_pfn_vec_apply_t
+* NAME
+*	cl_pfn_vec_apply_t
+*
+* DESCRIPTION
+*	The cl_pfn_vec_apply_t function type defines the prototype for functions
+*	used to iterate elements in a vector.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_vec_apply_t) (IN const size_t index,
+			IN void *const p_element, IN void *context);
+/*
+* PARAMETERS
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[in] Pointer to an element at the specified index in the vector.
+*
+*	context
+*		[in] Context provided in a call to cl_vector_apply_func.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	This function type is provided as function prototype reference for
+*	the function passed by users as a parameter to the cl_vector_apply_func
+*	function.
+*
+* SEE ALSO
+*	Vector, cl_vector_apply_func
+*********/
+
+/****d* Component Library: Vector/cl_pfn_vec_find_t
+* NAME
+*	cl_pfn_vec_find_t
+*
+* DESCRIPTION
+*	The cl_pfn_vec_find_t function type defines the prototype for functions
+*	used to find elements in a vector.
+*
+* SYNOPSIS
+*/
+typedef cl_status_t
+    (*cl_pfn_vec_find_t) (IN const size_t index,
+			  IN const void *const p_element, IN void *context);
+/*
+* PARAMETERS
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[in] Pointer to an element at the specified index in the vector.
+*
+*	context
+*		[in] Context provided in a call to cl_vector_find_from_start or
+*		cl_vector_find_from_end.
+*
+* RETURN VALUES
+*	Return CL_SUCCESS if the element was found. This stops vector iteration.
+*
+*	CL_NOT_FOUND to continue the vector iteration.
+*
+* NOTES
+*	This function type is provided as function prototype reference for the
+*	function provided by users as a parameter to the cl_vector_find_from_start
+*	and cl_vector_find_from_end functions.
+*
+* SEE ALSO
+*	Vector, cl_vector_find_from_start, cl_vector_find_from_end
+*********/
+
+/****i* Component Library: Vector/cl_pfn_vec_copy_t
+* NAME
+*	cl_pfn_vec_copy_t
+*
+* DESCRIPTION
+*	The cl_pfn_vec_copy_t function type defines the prototype for functions
+*	used to copy elements in a vector.
+*
+* SYNOPSIS
+*/
+typedef void
+ (*cl_pfn_vec_copy_t) (IN void *const p_dest,
+		       IN const void *const p_src, IN const size_t size);
+/*
+* PARAMETERS
+*	p_dest
+*		[in] Pointer to the destination buffer into which to copy p_src.
+*
+*	p_src
+*		[in] Pointer to the destination buffer from which to copy.
+*
+*	size
+*		[in] Number of bytes to copy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* SEE ALSO
+*	Vector
+*********/
+
+/****s* Component Library: Vector/cl_vector_t
+* NAME
+*	cl_vector_t
+*
+* DESCRIPTION
+*	Vector structure.
+*
+*	The cl_vector_t structure should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_vector {
+	size_t size;
+	size_t grow_size;
+	size_t capacity;
+	size_t element_size;
+	cl_pfn_vec_init_t pfn_init;
+	cl_pfn_vec_dtor_t pfn_dtor;
+	cl_pfn_vec_copy_t pfn_copy;
+	const void *context;
+	cl_qlist_t alloc_list;
+	void **p_ptr_array;
+	cl_state_t state;
+} cl_vector_t;
+/*
+* FIELDS
+*	size
+*		 Number of elements successfully initialized in the vector.
+*
+*	grow_size
+*		 Number of elements to allocate when growing.
+*
+*	capacity
+*		 total # of elements allocated.
+*
+*	element_size
+*		 Size of each element.
+*
+*	pfn_init
+*		 User supplied element initializer.
+*
+*	pfn_dtor
+*		 User supplied element destructor.
+*
+*	pfn_copy
+*		 Copy operator.
+*
+*	context
+*		 User context for callbacks.
+*
+*	alloc_list
+*		 List of allocations.
+*
+*	p_ptr_array
+*		 Internal array of pointers to elements.
+*
+*	state
+*		State of the vector.
+*
+* SEE ALSO
+*	Vector
+*********/
+
+/****f* Component Library: Vector/cl_vector_construct
+* NAME
+*	cl_vector_construct
+*
+* DESCRIPTION
+*	The cl_vector_construct function constructs a vector.
+*
+* SYNOPSIS
+*/
+void cl_vector_construct(IN cl_vector_t * const p_vector);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure to construct.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Allows calling cl_vector_destroy without first calling cl_vector_init.
+*
+*	Calling cl_vector_construct is a prerequisite to calling any other
+*	vector function except cl_vector_init.
+*
+* SEE ALSO
+*	Vector, cl_vector_init, cl_vector_destroy
+*********/
+
+/****f* Component Library: Vector/cl_vector_init
+* NAME
+*	cl_vector_init
+*
+* DESCRIPTION
+*	The cl_vector_init function initializes a vector for use.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_init(IN cl_vector_t * const p_vector,
+	       IN const size_t min_size,
+	       IN const size_t grow_size,
+	       IN const size_t element_size,
+	       IN cl_pfn_vec_init_t pfn_init OPTIONAL,
+	       IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,
+	       IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure to inititalize.
+*
+*	initial_size
+*		[in] Initial number of elements.
+*
+*	grow_size
+*		[in] Number of elements to allocate when incrementally growing
+*		the vector.  A value of zero disables automatic growth.
+*
+*	element_size
+*		[in] Size of each element.
+*
+*	pfn_init
+*		[in] Initializer callback to invoke for every new element.
+*		See the cl_pfn_vec_init_t function type declaration for details about
+*		the callback function.
+*
+*	pfn_dtor
+*		[in] Destructor callback to invoke for elements being deallocated.
+*		See the cl_pfn_vec_dtor_t function type declaration for details about
+*		the callback function.
+*
+*	context
+*		[in] Value to pass to the callback functions to provide context.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the vector was initialized successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if the initialization failed.
+*
+*	cl_status_t value returned by optional initializer function specified by
+*	the pfn_init parameter.
+*
+* NOTES
+*	The constructor and initializer functions, if any, are invoked for every
+*	new element in the array.
+*
+* SEE ALSO
+*	Vector, cl_vector_construct, cl_vector_destroy, cl_vector_set,
+*	cl_vector_get, cl_vector_get_ptr, cl_vector_at
+*********/
+
+/****f* Component Library: Vector/cl_vector_destroy
+* NAME
+*	cl_vector_destroy
+*
+* DESCRIPTION
+*	The cl_vector_destroy function destroys a vector.
+*
+* SYNOPSIS
+*/
+void cl_vector_destroy(IN cl_vector_t * const p_vector);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure to destroy.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_vector_destroy frees all memory allocated for the vector. The vector
+*	is left initialized to a zero capacity and size.
+*
+*	This function should only be called after a call to cl_vector_construct
+*	or cl_vector_init.
+*
+* SEE ALSO
+*	Vector, cl_vector_construct, cl_vector_init
+*********/
+
+/****f* Component Library: Vector/cl_vector_get_capacity
+* NAME
+*	cl_vector_get_capacity
+*
+* DESCRIPTION
+*	The cl_vector_get_capacity function returns the capacity of a vector.
+*
+* SYNOPSIS
+*/
+static inline size_t
+cl_vector_get_capacity(IN const cl_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	return (p_vector->capacity);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose capacity to return.
+*
+* RETURN VALUE
+*	Capacity, in elements, of the vector.
+*
+* NOTES
+*	The capacity is the number of elements that the vector can store, and
+*	can be greater than the number of elements stored. To get the number of
+*	elements stored in the vector, use cl_vector_get_size.
+*
+* SEE ALSO
+*	Vector, cl_vector_set_capacity, cl_vector_get_size
+*********/
+
+/****f* Component Library: Vector/cl_vector_get_size
+* NAME
+*	cl_vector_get_size
+*
+* DESCRIPTION
+*	The cl_vector_get_size function returns the size of a vector.
+*
+* SYNOPSIS
+*/
+static inline size_t cl_vector_get_size(IN const cl_vector_t * const p_vector)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	return (p_vector->size);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose size to return.
+*
+* RETURN VALUE
+*	Size, in elements, of the vector.
+*
+* SEE ALSO
+*	Vector, cl_vector_set_size, cl_vector_get_capacity
+*********/
+
+/****f* Component Library: Vector/cl_vector_get_ptr
+* NAME
+*	cl_vector_get_ptr
+*
+* DESCRIPTION
+*	The cl_vector_get_ptr function returns a pointer to an element
+*	stored in a vector at a specified index.
+*
+* SYNOPSIS
+*/
+static inline void *cl_vector_get_ptr(IN const cl_vector_t * const p_vector,
+				      IN const size_t index)
+{
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+
+	return (p_vector->p_ptr_array[index]);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure from which to get a
+*		pointer to an element.
+*
+*	index
+*		[in] Index of the element.
+*
+* RETURN VALUE
+*	Pointer to the element stored at specified index.
+*
+* NOTES
+*	cl_vector_get_ptr provides constant access times regardless of the index.
+*
+*	cl_vector_get_ptr does not perform boundary checking. Callers are
+*	responsible for providing an index that is within the range of the vector.
+*
+* SEE ALSO
+*	Vector, cl_vector_get, cl_vector_at, cl_vector_set, cl_vector_get_size
+*********/
+
+/****f* Component Library: Vector/cl_vector_get
+* NAME
+*	cl_vector_get
+*
+* DESCRIPTION
+*	The cl_vector_get function copies an element stored in a vector at a
+*	specified index.
+*
+* SYNOPSIS
+*/
+static inline void
+cl_vector_get(IN const cl_vector_t * const p_vector,
+	      IN const size_t index, OUT void *const p_element)
+{
+	void *p_src;
+
+	CL_ASSERT(p_vector);
+	CL_ASSERT(p_vector->state == CL_INITIALIZED);
+	CL_ASSERT(p_element);
+
+	/* Get a pointer to the element. */
+	p_src = cl_vector_get_ptr(p_vector, index);
+	p_vector->pfn_copy(p_src, p_element, p_vector->element_size);
+}
+
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure from which to get a copy of
+*		an element.
+*
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[out] Pointer to storage for the element. Contains a copy of the
+*		desired element upon successful completion of the call.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_vector_get provides constant time access regardless of the index.
+*
+*	cl_vector_get does not perform boundary checking on the vector, and
+*	callers are responsible for providing an index that is within the range
+*	of the vector. To access elements after performing boundary checks,
+*	use cl_vector_at.
+*
+*	The p_element parameter contains a copy of the desired element upon
+*	return from this function.
+*
+* SEE ALSO
+*	Vector, cl_vector_get_ptr, cl_vector_at
+*********/
+
+/****f* Component Library: Vector/cl_vector_at
+* NAME
+*	cl_vector_at
+*
+* DESCRIPTION
+*	The cl_vector_at function copies an element stored in a vector at a
+*	specified index, performing boundary checks.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_at(IN const cl_vector_t * const p_vector,
+	     IN const size_t index, OUT void *const p_element);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure from which to get a copy of
+*		an element.
+*
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[out] Pointer to storage for the element. Contains a copy of the
+*		desired element upon successful completion of the call.
+*
+* RETURN VALUES
+*	CL_SUCCESS if an element was found at the specified index.
+*
+*	CL_INVALID_SETTING if the index was out of range.
+*
+* NOTES
+*	cl_vector_at provides constant time access regardless of the index, and
+*	performs boundary checking on the vector.
+*
+*	Upon success, the p_element parameter contains a copy of the desired element.
+*
+* SEE ALSO
+*	Vector, cl_vector_get, cl_vector_get_ptr
+*********/
+
+/****f* Component Library: Vector/cl_vector_set
+* NAME
+*	cl_vector_set
+*
+* DESCRIPTION
+*	The cl_vector_set function sets the element at the specified index.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_set(IN cl_vector_t * const p_vector,
+	      IN const size_t index, IN void *const p_element);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure into which to store
+*		an element.
+*
+*	index
+*		[in] Index of the element.
+*
+*	p_element
+*		[in] Pointer to an element to store in the vector.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the element was successfully set.
+*
+*	CL_INSUFFICIENT_MEMORY if the vector could not be resized to accommodate
+*	the new element.
+*
+* NOTES
+*	cl_vector_set grows the vector as needed to accommodate the new element,
+*	unless the grow_size parameter passed into the cl_vector_init function
+*	was zero.
+*
+* SEE ALSO
+*	Vector, cl_vector_get
+*********/
+
+/****f* Component Library: Vector/cl_vector_set_capacity
+* NAME
+*	cl_vector_set_capacity
+*
+* DESCRIPTION
+*	The cl_vector_set_capacity function reserves memory in a vector for a
+*	specified number of elements.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_set_capacity(IN cl_vector_t * const p_vector,
+		       IN const size_t new_capacity);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose capacity to set.
+*
+*	new_capacity
+*		[in] Total number of elements for which the vector should
+*		allocate memory.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the capacity was successfully set.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to satisfy the
+*	operation. The vector is left unchanged.
+*
+* NOTES
+*	cl_vector_set_capacity increases the capacity of the vector. It does
+*	not change the size of the vector. If the requested capacity is less
+*	than the current capacity, the vector is left unchanged.
+*
+* SEE ALSO
+*	Vector, cl_vector_get_capacity, cl_vector_set_size,
+*	cl_vector_set_min_size
+*********/
+
+/****f* Component Library: Vector/cl_vector_set_size
+* NAME
+*	cl_vector_set_size
+*
+* DESCRIPTION
+*	The cl_vector_set_size function resizes a vector, either increasing or
+*	decreasing its size.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_set_size(IN cl_vector_t * const p_vector, IN const size_t size);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose size to set.
+*
+*	size
+*		[in] Number of elements desired in the vector.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the size of the vector was set successfully.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to complete the
+*	operation. The vector is left unchanged.
+*
+* NOTES
+*	cl_vector_set_size sets the vector to the specified size. If size is
+*	smaller than the current size of the vector, the size is reduced.
+*	The destructor function, if any, will be invoked for all elements that
+*	are above size. Likewise, the constructor and initializer, if any, will
+*	be invoked for all new elements.
+*
+*	This function can only fail if size is larger than the current capacity.
+*
+* SEE ALSO
+*	Vector, cl_vector_get_size, cl_vector_set_min_size,
+*	cl_vector_set_capacity
+*********/
+
+/****f* Component Library: Vector/cl_vector_set_min_size
+* NAME
+*	cl_vector_set_min_size
+*
+* DESCRIPTION
+*	The cl_vector_set_min_size function resizes a vector to a specified size
+*	if the vector is smaller than the specified size.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_vector_set_min_size(IN cl_vector_t * const p_vector,
+		       IN const size_t min_size);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose minimum size to set.
+*
+*	min_size
+*		[in] Minimum number of elements that the vector should contain.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the vector size is greater than or equal to min_size.  This
+*	could indicate that the vector's capacity was increased to min_size or
+*	that the vector was already of sufficient size.
+*
+*	CL_INSUFFICIENT_MEMORY if there was not enough memory to resize the vector.
+*	The vector is left unchanged.
+*
+* NOTES
+*	If min_size is smaller than the current size of the vector, the vector is
+*	unchanged. The vector is unchanged if the size could not be changed due
+*	to insufficient memory being available to perform the operation.
+*
+* SEE ALSO
+*	Vector, cl_vector_get_size, cl_vector_set_size, cl_vector_set_capacity
+*********/
+
+/****f* Component Library: Vector/cl_vector_apply_func
+* NAME
+*	cl_vector_apply_func
+*
+* DESCRIPTION
+*	The cl_vector_apply_func function invokes a specified function for every
+*	element in a vector.
+*
+* SYNOPSIS
+*/
+void
+cl_vector_apply_func(IN const cl_vector_t * const p_vector,
+		     IN cl_pfn_vec_apply_t pfn_callback,
+		     IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure whose elements to iterate.
+*
+*	pfn_callback
+*		[in] Function invoked for every element in the array.
+*		See the cl_pfn_vec_apply_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	cl_vector_apply_func invokes the specified function for every element
+*	in the vector, starting from the beginning of the vector.
+*
+* SEE ALSO
+*	Vector, cl_vector_find_from_start, cl_vector_find_from_end,
+*	cl_pfn_vec_apply_t
+*********/
+
+/****f* Component Library: Vector/cl_vector_find_from_start
+* NAME
+*	cl_vector_find_from_start
+*
+* DESCRIPTION
+*	The cl_vector_find_from_start function uses a specified function to
+*	search for elements in a vector starting from the lowest index.
+*
+* SYNOPSIS
+*/
+size_t
+cl_vector_find_from_start(IN const cl_vector_t * const p_vector,
+			  IN cl_pfn_vec_find_t pfn_callback,
+			  IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure to inititalize.
+*
+*	pfn_callback
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_vec_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUES
+*	Index of the element, if found.
+*
+*	Size of the vector if the element was not found.
+*
+* NOTES
+*	cl_vector_find_from_start does not remove the found element from
+*	the vector. The index of the element is returned when the function
+*	provided by the pfn_callback parameter returns CL_SUCCESS.
+*
+* SEE ALSO
+*	Vector, cl_vector_find_from_end, cl_vector_apply_func, cl_pfn_vec_find_t
+*********/
+
+/****f* Component Library: Vector/cl_vector_find_from_end
+* NAME
+*	cl_vector_find_from_end
+*
+* DESCRIPTION
+*	The cl_vector_find_from_end function uses a specified function to search
+*	for elements in a vector starting from the highest index.
+*
+* SYNOPSIS
+*/
+size_t
+cl_vector_find_from_end(IN const cl_vector_t * const p_vector,
+			IN cl_pfn_vec_find_t pfn_callback,
+			IN const void *const context);
+/*
+* PARAMETERS
+*	p_vector
+*		[in] Pointer to a cl_vector_t structure to inititalize.
+*
+*	pfn_callback
+*		[in] Function invoked to determine if a match was found.
+*		See the cl_pfn_vec_find_t function type declaration for details
+*		about the callback function.
+*
+*	context
+*		[in] Value to pass to the callback function.
+*
+* RETURN VALUES
+*	Index of the element, if found.
+*
+*	Size of the vector if the element was not found.
+*
+* NOTES
+*	cl_vector_find_from_end does not remove the found element from
+*	the vector. The index of the element is returned when the function
+*	provided by the pfn_callback parameter returns CL_SUCCESS.
+*
+* SEE ALSO
+*	Vector, cl_vector_find_from_start, cl_vector_apply_func,
+*	cl_pfn_vec_find_t
+*********/
+
+END_C_DECLS
+#endif				/* _CL_VECTOR_H_ */
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100644
index 0000000..49af898
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,157 @@
+/* include/config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define as 1 if you want Dual Sided RMPP Support */
+#undef DUAL_SIDED_RMPP
+
+/* Define as 1 if you want to enable a console on a socket connection */
+#undef ENABLE_OSM_CONSOLE_SOCKET
+
+/* Define as 1 if you want to enable the event plugin */
+#undef ENABLE_OSM_DEFAULT_EVENT_PLUGIN
+
+/* Define as 1 if you want to enable the performance manager */
+#undef ENABLE_OSM_PERF_MGR
+
+/* Define as 1 if you want to enable the performance manager profiling code */
+#undef ENABLE_OSM_PERF_MGR_PROFILE
+
+/* Define a default node name map file */
+#undef HAVE_DEFAULT_NODENAME_MAP
+
+/* Define a default OpenSM config file */
+#undef HAVE_DEFAULT_OPENSM_CONFIG_FILE
+
+/* Define a Partition config file */
+#undef HAVE_DEFAULT_PARTITION_CONFIG_FILE
+
+/* Define a Prefix Routes config file */
+#undef HAVE_DEFAULT_PREFIX_ROUTES_FILE
+
+/* Define a QOS policy config file */
+#undef HAVE_DEFAULT_QOS_POLICY_FILE
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+#undef HAVE_LIBDL
+
+/* Define to 1 if you have the `ibumad' library (-libumad). */
+#undef HAVE_LIBIBUMAD
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
+/* Define to 1 if you have the `vapi' library (-lvapi). */
+#undef HAVE_LIBVAPI
+
+/* Define to 1 if you have the `wrap' library (-lwrap). */
+#undef HAVE_LIBWRAP
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define OpenSM config directory */
+#undef OPENSM_CONFIG_DIR
+
+/* define 1 if OpenSM build is in a debug mode */
+#undef OSM_DEBUG
+
+/* Define as 1 for vapi vendor */
+#undef OSM_VENDOR_INTF_MTL
+
+/* Define as 1 for OpenIB vendor */
+#undef OSM_VENDOR_INTF_OPENIB
+
+/* Define as 1 for sim vendor */
+#undef OSM_VENDOR_INTF_SIM
+
+/* Define as 1 for ts vendor */
+#undef OSM_VENDOR_INTF_TS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Define as 1 if you want Vendor RMPP Support */
+#undef VENDOR_RMPP_SUPPORT
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#undef YYTEXT_POINTER
+
+/* mark config.h inclusion */
+#undef _OSM_CONFIG_H_
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/include/iba/ib_cm_types.h b/include/iba/ib_cm_types.h
new file mode 100644
index 0000000..c1fbfaf
--- /dev/null
+++ b/include/iba/ib_cm_types.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if !defined(__IB_CM_TYPES_H__)
+#define __IB_CM_TYPES_H__
+
+#ifndef WIN32
+
+#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
+/*
+ * Defines known Communication management class versions
+ */
+#define IB_MCLASS_CM_VER_2				2
+#define IB_MCLASS_CM_VER_1				1
+/*
+ *	Defines the size of user available data in communication management MADs
+ */
+#define IB_REQ_PDATA_SIZE_VER2				92
+#define IB_MRA_PDATA_SIZE_VER2				222
+#define IB_REJ_PDATA_SIZE_VER2				148
+#define IB_REP_PDATA_SIZE_VER2				196
+#define IB_RTU_PDATA_SIZE_VER2				224
+#define IB_LAP_PDATA_SIZE_VER2				168
+#define IB_APR_PDATA_SIZE_VER2				148
+#define IB_DREQ_PDATA_SIZE_VER2				220
+#define IB_DREP_PDATA_SIZE_VER2				224
+#define IB_SIDR_REQ_PDATA_SIZE_VER2			216
+#define IB_SIDR_REP_PDATA_SIZE_VER2			136
+#define IB_REQ_PDATA_SIZE_VER1				92
+#define IB_MRA_PDATA_SIZE_VER1				222
+#define IB_REJ_PDATA_SIZE_VER1				148
+#define IB_REP_PDATA_SIZE_VER1				204
+#define IB_RTU_PDATA_SIZE_VER1				224
+#define IB_LAP_PDATA_SIZE_VER1				168
+#define IB_APR_PDATA_SIZE_VER1				151
+#define IB_DREQ_PDATA_SIZE_VER1				220
+#define IB_DREP_PDATA_SIZE_VER1				224
+#define IB_SIDR_REQ_PDATA_SIZE_VER1			216
+#define IB_SIDR_REP_PDATA_SIZE_VER1			140
+#define IB_ARI_SIZE					72	// redefine
+#define IB_APR_INFO_SIZE				72
+/****d* Access Layer/ib_rej_status_t
+* NAME
+*	ib_rej_status_t
+*
+* DESCRIPTION
+*	Rejection reasons.
+*
+* SYNOPSIS
+*/
+typedef ib_net16_t ib_rej_status_t;
+/*
+* SEE ALSO
+*	ib_cm_rej, ib_cm_rej_rec_t
+*
+* SOURCE
+*/
+#define IB_REJ_INSUF_QP					CL_HTON16(1)
+#define IB_REJ_INSUF_EEC				CL_HTON16(2)
+#define IB_REJ_INSUF_RESOURCES				CL_HTON16(3)
+#define IB_REJ_TIMEOUT					CL_HTON16(4)
+#define IB_REJ_UNSUPPORTED				CL_HTON16(5)
+#define IB_REJ_INVALID_COMM_ID				CL_HTON16(6)
+#define IB_REJ_INVALID_COMM_INSTANCE			CL_HTON16(7)
+#define IB_REJ_INVALID_SID				CL_HTON16(8)
+#define IB_REJ_INVALID_XPORT				CL_HTON16(9)
+#define IB_REJ_STALE_CONN				CL_HTON16(10)
+#define IB_REJ_RDC_NOT_EXIST				CL_HTON16(11)
+#define IB_REJ_INVALID_GID				CL_HTON16(12)
+#define IB_REJ_INVALID_LID				CL_HTON16(13)
+#define IB_REJ_INVALID_SL				CL_HTON16(14)
+#define IB_REJ_INVALID_TRAFFIC_CLASS			CL_HTON16(15)
+#define IB_REJ_INVALID_HOP_LIMIT			CL_HTON16(16)
+#define IB_REJ_INVALID_PKT_RATE				CL_HTON16(17)
+#define IB_REJ_INVALID_ALT_GID				CL_HTON16(18)
+#define IB_REJ_INVALID_ALT_LID				CL_HTON16(19)
+#define IB_REJ_INVALID_ALT_SL				CL_HTON16(20)
+#define IB_REJ_INVALID_ALT_TRAFFIC_CLASS		CL_HTON16(21)
+#define IB_REJ_INVALID_ALT_HOP_LIMIT			CL_HTON16(22)
+#define IB_REJ_INVALID_ALT_PKT_RATE			CL_HTON16(23)
+#define IB_REJ_PORT_REDIRECT				CL_HTON16(24)
+#define IB_REJ_INVALID_MTU				CL_HTON16(26)
+#define IB_REJ_INSUFFICIENT_RESP_RES			CL_HTON16(27)
+#define IB_REJ_USER_DEFINED				CL_HTON16(28)
+#define IB_REJ_INVALID_RNR_RETRY			CL_HTON16(29)
+#define IB_REJ_DUPLICATE_LOCAL_COMM_ID			CL_HTON16(30)
+#define IB_REJ_INVALID_CLASS_VER			CL_HTON16(31)
+#define IB_REJ_INVALID_FLOW_LBL				CL_HTON16(32)
+#define IB_REJ_INVALID_ALT_FLOW_LBL			CL_HTON16(33)
+
+#define IB_REJ_SERVICE_HANDOFF				CL_HTON16(65535)
+/******/
+
+/****d* Access Layer/ib_apr_status_t
+* NAME
+*	ib_apr_status_t
+*
+* DESCRIPTION
+*	Automatic path migration status information.
+*
+* SYNOPSIS
+*/
+typedef uint8_t ib_apr_status_t;
+/*
+* SEE ALSO
+*	ib_cm_apr, ib_cm_apr_rec_t
+*
+* SOURCE
+ */
+#define IB_AP_SUCCESS					0
+#define IB_AP_INVALID_COMM_ID				1
+#define IB_AP_UNSUPPORTED				2
+#define IB_AP_REJECT					3
+#define IB_AP_REDIRECT					4
+#define IB_AP_IS_CURRENT				5
+#define IB_AP_INVALID_QPN_EECN				6
+#define IB_AP_INVALID_LID				7
+#define IB_AP_INVALID_GID				8
+#define IB_AP_INVALID_FLOW_LBL				9
+#define IB_AP_INVALID_TCLASS				10
+#define IB_AP_INVALID_HOP_LIMIT				11
+#define IB_AP_INVALID_PKT_RATE				12
+#define IB_AP_INVALID_SL				13
+/******/
+
+/****d* Access Layer/ib_cm_cap_mask_t
+* NAME
+*	ib_cm_cap_mask_t
+*
+* DESCRIPTION
+*	Capability mask values in ClassPortInfo.
+*
+* SYNOPSIS
+*/
+#define IB_CM_RELIABLE_CONN_CAPABLE			CL_HTON16(9)
+#define IB_CM_RELIABLE_DGRM_CAPABLE			CL_HTON16(10)
+#define IB_CM_RDGRM_CAPABLE				CL_HTON16(11)
+#define IB_CM_UNRELIABLE_CONN_CAPABLE			CL_HTON16(12)
+#define IB_CM_SIDR_CAPABLE				CL_HTON16(13)
+/*
+* SEE ALSO
+*	ib_cm_rep, ib_class_port_info_t
+*
+* SOURCE
+*
+*******/
+
+/*
+ *	Service ID resolution status
+ */
+typedef uint16_t ib_sidr_status_t;
+#define IB_SIDR_SUCCESS					0
+#define IB_SIDR_UNSUPPORTED				1
+#define IB_SIDR_REJECT					2
+#define IB_SIDR_NO_QP					3
+#define IB_SIDR_REDIRECT				4
+#define IB_SIDR_UNSUPPORTED_VER				5
+
+END_C_DECLS
+#endif				/* ndef WIN32 */
+#endif				/* __IB_CM_TYPES_H__ */
diff --git a/include/iba/ib_types.h b/include/iba/ib_types.h
new file mode 100644
index 0000000..0f9d110
--- /dev/null
+++ b/include/iba/ib_types.h
@@ -0,0 +1,10720 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if !defined(__IB_TYPES_H__)
+#define __IB_TYPES_H__
+
+#include <string.h>
+#include <complib/cl_types.h>
+#include <complib/cl_byteswap.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#if defined( WIN32 ) || defined( _WIN64 )
+#if defined( EXPORT_AL_SYMBOLS )
+#define OSM_EXPORT	__declspec(dllexport)
+#else
+#define OSM_EXPORT	__declspec(dllimport)
+#endif
+#define OSM_API __stdcall
+#define OSM_CDECL __cdecl
+#else
+#define OSM_EXPORT	extern
+#define OSM_API
+#define OSM_CDECL
+#define __ptr64
+#endif
+/****h* IBA Base/Constants
+* NAME
+*	Constants
+*
+* DESCRIPTION
+*	The following constants are used throughout the IBA code base.
+*
+*	Definitions are from the InfiniBand Architecture Specification v1.2
+*
+*********/
+/****d* IBA Base: Constants/MAD_BLOCK_SIZE
+* NAME
+*	MAD_BLOCK_SIZE
+*
+* DESCRIPTION
+*	Size of a non-RMPP MAD datagram.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_SIZE						256
+/**********/
+/****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE
+* NAME
+*	MAD_RMPP_HDR_SIZE
+*
+* DESCRIPTION
+*	Size of an RMPP header, including the common MAD header.
+*
+* SOURCE
+*/
+#define MAD_RMPP_HDR_SIZE					36
+/**********/
+/****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE
+* NAME
+*	MAD_RMPP_DATA_SIZE
+*
+* DESCRIPTION
+*	Size of an RMPP transaction data section.
+*
+* SOURCE
+*/
+#define MAD_RMPP_DATA_SIZE		(MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE)
+/**********/
+/****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE
+* NAME
+*	MAD_BLOCK_GRH_SIZE
+*
+* DESCRIPTION
+*	Size of a MAD datagram, including the GRH.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_GRH_SIZE					296
+/**********/
+/****d* IBA Base: Constants/IB_LID_PERMISSIVE
+* NAME
+*	IB_LID_PERMISSIVE
+*
+* DESCRIPTION
+*	Permissive LID
+*
+* SOURCE
+*/
+#define IB_LID_PERMISSIVE					0xFFFF
+/**********/
+/****d* IBA Base: Constants/IB_DEFAULT_PKEY
+* NAME
+*	IB_DEFAULT_PKEY
+*
+* DESCRIPTION
+*	P_Key value for the default partition.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_PKEY						0xFFFF
+/**********/
+/****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY
+* NAME
+*	IB_QP1_WELL_KNOWN_Q_KEY
+*
+* DESCRIPTION
+*	Well-known Q_Key for QP1 privileged mode access (15.4.2).
+*
+* SOURCE
+*/
+#define IB_QP1_WELL_KNOWN_Q_KEY				CL_HTON32(0x80010000)
+/*********/
+#define IB_QP0								0
+#define IB_QP1								CL_HTON32(1)
+#define IB_QP_PRIVILEGED_Q_KEY				CL_HTON32(0x80000000)
+/****d* IBA Base: Constants/IB_LID_UCAST_START
+* NAME
+*	IB_LID_UCAST_START
+*
+* DESCRIPTION
+*	Lowest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_START_HO				0x0001
+#define IB_LID_UCAST_START					(CL_HTON16(IB_LID_UCAST_START_HO))
+/**********/
+/****d* IBA Base: Constants/IB_LID_UCAST_END
+* NAME
+*	IB_LID_UCAST_END
+*
+* DESCRIPTION
+*	Highest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_END_HO					0xBFFF
+#define IB_LID_UCAST_END					(CL_HTON16(IB_LID_UCAST_END_HO))
+/**********/
+/****d* IBA Base: Constants/IB_LID_MCAST_START
+* NAME
+*	IB_LID_MCAST_START
+*
+* DESCRIPTION
+*	Lowest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_START_HO				0xC000
+#define IB_LID_MCAST_START					(CL_HTON16(IB_LID_MCAST_START_HO))
+/**********/
+/****d* IBA Base: Constants/IB_LID_MCAST_END
+* NAME
+*	IB_LID_MCAST_END
+*
+* DESCRIPTION
+*	Highest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_END_HO					0xFFFE
+#define IB_LID_MCAST_END					(CL_HTON16(IB_LID_MCAST_END_HO))
+/**********/
+/****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX
+* NAME
+*	IB_DEFAULT_SUBNET_PREFIX
+*
+* DESCRIPTION
+*	Default subnet GID prefix.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_SUBNET_PREFIX			(CL_HTON64(0xFE80000000000000ULL))
+/**********/
+/****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX
+* NAME
+*	IB_NODE_NUM_PORTS_MAX
+*
+* DESCRIPTION
+*	Maximum number of ports in a single node (14.2.5.7).
+* SOURCE
+*/
+#define IB_NODE_NUM_PORTS_MAX				0xFE
+/**********/
+/****d* IBA Base: Constants/IB_INVALID_PORT_NUM
+* NAME
+*	IB_INVALID_PORT_NUM
+*
+* DESCRIPTION
+*	Value used to indicate an invalid port number (14.2.5.10).
+*
+* SOURCE
+*/
+#define IB_INVALID_PORT_NUM					0xFF
+/*********/
+/****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX
+* NAME
+*	IB_SUBNET_PATH_HOPS_MAX
+*
+* DESCRIPTION
+*	Maximum number of directed route switch hops in a subnet (14.2.1.2).
+*
+* SOURCE
+*/
+#define IB_SUBNET_PATH_HOPS_MAX				64
+/*********/
+/****d* IBA Base: Constants/IB_HOPLIMIT_MAX
+* NAME
+*	IB_HOPLIMIT_MAX
+*
+* DESCRIPTION
+*       Maximum number of router hops allowed.
+*
+* SOURCE
+*/
+#define IB_HOPLIMIT_MAX					255
+/*********/
+/****d* IBA Base: Constants/IB_MC_SCOPE_*
+* NAME
+*	IB_MC_SCOPE_*
+*
+* DESCRIPTION
+*	Scope component definitions from IBA 1.2 (Table 3 p. 146)
+*/
+#define IB_MC_SCOPE_LINK_LOCAL		0x2
+#define IB_MC_SCOPE_SITE_LOCAL		0x5
+#define IB_MC_SCOPE_ORG_LOCAL		0x8
+#define IB_MC_SCOPE_GLOBAL		0xE
+/*********/
+/****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS
+* NAME
+*	IB_PKEY_MAX_BLOCKS
+*
+* DESCRIPTION
+*	Maximum number of PKEY blocks (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_MAX_BLOCKS					2048
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID
+* NAME
+*	IB_MCAST_MAX_BLOCK_ID
+*
+* DESCRIPTION
+*	Maximum number of Multicast port mask blocks
+*
+* SOURCE
+*/
+#define IB_MCAST_MAX_BLOCK_ID				511
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO
+* NAME
+*	IB_MCAST_BLOCK_ID_MASK_HO
+*
+* DESCRIPTION
+*	Mask (host order) to recover the Multicast block ID.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_ID_MASK_HO			0x000001FF
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE
+* NAME
+*	IB_MCAST_BLOCK_SIZE
+*
+* DESCRIPTION
+*	Number of port mask entries in a multicast forwarding table block.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_SIZE					32
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_MASK_SIZE
+* NAME
+*	IB_MCAST_MASK_SIZE
+*
+* DESCRIPTION
+*	Number of port mask bits in each entry in the multicast forwarding table.
+*
+* SOURCE
+*/
+#define IB_MCAST_MASK_SIZE					16
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO
+* NAME
+*	IB_MCAST_POSITION_MASK_HO
+*
+* DESCRIPTION
+*	Mask (host order) to recover the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MASK_HO				0xF0000000
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MAX
+* NAME
+*	IB_MCAST_POSITION_MAX
+*
+* DESCRIPTION
+*	Maximum value for the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MAX				0xF
+/*********/
+/****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT
+* NAME
+*	IB_MCAST_POSITION_SHIFT
+*
+* DESCRIPTION
+*	Shift value to normalize the multicast block position value.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_SHIFT				28
+/*********/
+/****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX
+* NAME
+*	IB_PKEY_ENTRIES_MAX
+*
+* DESCRIPTION
+*	Maximum number of PKEY entries per port (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK)
+/*********/
+/****d* IBA Base: Constants/IB_PKEY_BASE_MASK
+* NAME
+*	IB_PKEY_BASE_MASK
+*
+* DESCRIPTION
+*	Masks for the base P_Key value given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_BASE_MASK					(CL_HTON16(0x7FFF))
+/*********/
+/****d* IBA Base: Constants/IB_PKEY_TYPE_MASK
+* NAME
+*	IB_PKEY_TYPE_MASK
+*
+* DESCRIPTION
+*	Masks for the P_Key membership type given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_TYPE_MASK					(CL_HTON16(0x8000))
+/*********/
+/****d* IBA Base: Constants/IB_DEFAULT_PARTIAL_PKEY
+* NAME
+*	IB_DEFAULT_PARTIAL_PKEY
+*
+* DESCRIPTION
+*	0x7FFF in network order
+*
+* SOURCE
+*/
+#define IB_DEFAULT_PARTIAL_PKEY				       (CL_HTON16(0x7FFF))
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_LID
+* NAME
+*	IB_MCLASS_SUBN_LID
+*
+* DESCRIPTION
+*	Subnet Management Class, Subnet Manager LID routed (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_LID					0x01
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR
+* NAME
+*	IB_MCLASS_SUBN_DIR
+*
+* DESCRIPTION
+*	Subnet Management Class, Subnet Manager directed route (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_DIR					0x81
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM
+* NAME
+*	IB_MCLASS_SUBN_ADM
+*
+* DESCRIPTION
+*	Management Class, Subnet Administration (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_ADM					0x03
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_PERF
+* NAME
+*	IB_MCLASS_PERF
+*
+* DESCRIPTION
+*	Management Class, Performance Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_PERF						0x04
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_BM
+* NAME
+*	IB_MCLASS_BM
+*
+* DESCRIPTION
+*	Management Class, Baseboard Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_BM						0x05
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT
+* NAME
+*	IB_MCLASS_DEV_MGMT
+*
+* DESCRIPTION
+*	Management Class, Device Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_DEV_MGMT					0x06
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT
+* NAME
+*	IB_MCLASS_COMM_MGMT
+*
+* DESCRIPTION
+*	Management Class, Communication Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_COMM_MGMT					0x07
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_SNMP
+* NAME
+*	IB_MCLASS_SNMP
+*
+* DESCRIPTION
+*	Management Class, SNMP Tunneling (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SNMP						0x08
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN
+* NAME
+*	IB_MCLASS_VENDOR_LOW_RANGE_MIN
+*
+* DESCRIPTION
+*	Management Class, Vendor Specific Low Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX
+* NAME
+*	IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*
+* DESCRIPTION
+*	Management Class, Vendor Specific Low Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0f
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_DEV_ADM
+* NAME
+*	IB_MCLASS_DEV_ADM
+*
+* DESCRIPTION
+*	Management Class, Device Administration
+*
+* SOURCE
+*/
+#define IB_MCLASS_DEV_ADM 0x10
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_BIS
+* NAME
+*	IB_MCLASS_BIS
+*
+* DESCRIPTION
+*	Management Class, BIS
+*
+* SOURCE
+*/
+#define IB_MCLASS_BIS 0x12
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+* NAME
+*	IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+*
+* DESCRIPTION
+*	Management Class, Vendor Specific High Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30
+/**********/
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+* NAME
+*	IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*
+* DESCRIPTION
+*	Management Class, Vendor Specific High Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4f
+/**********/
+/****f* IBA Base: Types/ib_class_is_vendor_specific_low
+* NAME
+*	ib_class_is_vendor_specific_low
+*
+* DESCRIPTION
+*	Indicates if the Class Code if a vendor specific class from
+*  the low range
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_class_is_vendor_specific_low(IN const uint8_t class_code)
+{
+	return ((class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) &&
+		(class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX));
+}
+
+/*
+* PARAMETERS
+*	class_code
+*		[in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*	TRUE if the class is in the Low range of Vendor Specific MADs
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific_high
+* NAME
+*	ib_class_is_vendor_specific_high
+*
+* DESCRIPTION
+*	Indicates if the Class Code if a vendor specific class from
+*  the high range
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_class_is_vendor_specific_high(IN const uint8_t class_code)
+{
+	return ((class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) &&
+		(class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX));
+}
+
+/*
+* PARAMETERS
+*	class_code
+*		[in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*	TRUE if the class is in the High range of Vendor Specific MADs
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific
+* NAME
+*	ib_class_is_vendor_specific
+*
+* DESCRIPTION
+*	Indicates if the Class Code if a vendor specific class
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_class_is_vendor_specific(IN const uint8_t class_code)
+{
+	return (ib_class_is_vendor_specific_low(class_code) ||
+		ib_class_is_vendor_specific_high(class_code));
+}
+
+/*
+* PARAMETERS
+*	class_code
+*		[in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*	TRUE if the class is a Vendor Specific MAD
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*  ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high
+*********/
+
+/****f* IBA Base: Types/ib_class_is_rmpp
+* NAME
+*	ib_class_is_rmpp
+*
+* DESCRIPTION
+*	Indicates if the Class Code supports RMPP
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API ib_class_is_rmpp(IN const uint8_t class_code)
+{
+	return ((class_code == IB_MCLASS_SUBN_ADM) ||
+		(class_code == IB_MCLASS_DEV_MGMT) ||
+		(class_code == IB_MCLASS_DEV_ADM) ||
+		(class_code == IB_MCLASS_BIS) ||
+		ib_class_is_vendor_specific_high(class_code));
+}
+
+/*
+* PARAMETERS
+*	class_code
+*		[in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*	TRUE if the class supports RMPP
+*	FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/*
+ *	MAD methods
+ */
+
+/****d* IBA Base: Constants/IB_MAX_METHOD
+* NAME
+*	IB_MAX_METHOD
+*
+* DESCRIPTION
+*	Total number of methods available to a class, not including the R-bit.
+*
+* SOURCE
+*/
+#define IB_MAX_METHODS						128
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK
+* NAME
+*	IB_MAD_METHOD_RESP_MASK
+*
+* DESCRIPTION
+*	Response mask to extract 'R' bit from the method field. (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_RESP_MASK				0x80
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET
+* NAME
+*	IB_MAD_METHOD_GET
+*
+* DESCRIPTION
+*	Get() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET					0x01
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_SET
+* NAME
+*	IB_MAD_METHOD_SET
+*
+* DESCRIPTION
+*	Set() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SET					0x02
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP
+* NAME
+*	IB_MAD_METHOD_GET_RESP
+*
+* DESCRIPTION
+*	GetResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET_RESP				0x81
+/**********/
+
+#define IB_MAD_METHOD_DELETE				0x15
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE
+* NAME
+*	IB_MAD_METHOD_GETTABLE
+*
+* DESCRIPTION
+*	SubnAdmGetTable() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE				0x12
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP
+* NAME
+*	IB_MAD_METHOD_GETTABLE_RESP
+*
+* DESCRIPTION
+*	SubnAdmGetTableResp() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE_RESP			0x92
+
+/**********/
+
+#define IB_MAD_METHOD_GETTRACETABLE			0x13
+#define IB_MAD_METHOD_GETMULTI				0x14
+#define IB_MAD_METHOD_GETMULTI_RESP			0x94
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_SEND
+* NAME
+*	IB_MAD_METHOD_SEND
+*
+* DESCRIPTION
+*	Send() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SEND					0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP
+* NAME
+*	IB_MAD_METHOD_TRAP
+*
+* DESCRIPTION
+*	Trap() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP					0x05
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT
+* NAME
+*	IB_MAD_METHOD_REPORT
+*
+* DESCRIPTION
+*	Report() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT				0x06
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP
+* NAME
+*	IB_MAD_METHOD_REPORT_RESP
+*
+* DESCRIPTION
+*	ReportResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT_RESP			0x86
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS
+* NAME
+*	IB_MAD_METHOD_TRAP_REPRESS
+*
+* DESCRIPTION
+*	TrapRepress() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP_REPRESS			0x07
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_BUSY
+* NAME
+*	IB_MAD_STATUS_BUSY
+*
+* DESCRIPTION
+*	Temporarily busy, MAD discarded (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_BUSY				(CL_HTON16(0x0001))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT
+* NAME
+*	IB_MAD_STATUS_REDIRECT
+*
+* DESCRIPTION
+*	QP Redirection required (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_REDIRECT				(CL_HTON16(0x0002))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER
+* NAME
+*	IB_MAD_STATUS_UNSUP_CLASS_VER
+*
+* DESCRIPTION
+*	Unsupported class version (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_CLASS_VER			(CL_HTON16(0x0004))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD
+* NAME
+*	IB_MAD_STATUS_UNSUP_METHOD
+*
+* DESCRIPTION
+*	Unsupported method (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD			(CL_HTON16(0x0008))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR
+* NAME
+*	IB_MAD_STATUS_UNSUP_METHOD_ATTR
+*
+* DESCRIPTION
+*	Unsupported method/attribute combination (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD_ATTR			(CL_HTON16(0x000C))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD
+* NAME
+*	IB_MAD_STATUS_INVALID_FIELD
+*
+* DESCRIPTION
+*	Attribute contains one or more invalid fields (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_INVALID_FIELD			(CL_HTON16(0x001C))
+/**********/
+
+#define IB_MAD_STATUS_CLASS_MASK			(CL_HTON16(0xFF00))
+
+#define IB_SA_MAD_STATUS_SUCCESS			(CL_HTON16(0x0000))
+#define IB_SA_MAD_STATUS_NO_RESOURCES			(CL_HTON16(0x0100))
+#define IB_SA_MAD_STATUS_REQ_INVALID			(CL_HTON16(0x0200))
+#define IB_SA_MAD_STATUS_NO_RECORDS			(CL_HTON16(0x0300))
+#define IB_SA_MAD_STATUS_TOO_MANY_RECORDS		(CL_HTON16(0x0400))
+#define IB_SA_MAD_STATUS_INVALID_GID			(CL_HTON16(0x0500))
+#define IB_SA_MAD_STATUS_INSUF_COMPS			(CL_HTON16(0x0600))
+#define IB_SA_MAD_STATUS_DENIED				(CL_HTON16(0x0700))
+#define IB_SA_MAD_STATUS_PRIO_SUGGESTED			(CL_HTON16(0x0800))
+
+#define IB_DM_MAD_STATUS_NO_IOC_RESP			(CL_HTON16(0x0100))
+#define IB_DM_MAD_STATUS_NO_SVC_ENTRIES			(CL_HTON16(0x0200))
+#define IB_DM_MAD_STATUS_IOC_FAILURE			(CL_HTON16(0x8000))
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO
+* NAME
+*	IB_MAD_ATTR_CLASS_PORT_INFO
+*
+* DESCRIPTION
+*	ClassPortInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_CLASS_PORT_INFO			(CL_HTON16(0x0001))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE
+* NAME
+*	IB_MAD_ATTR_NOTICE
+*
+* DESCRIPTION
+*	Notice attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NOTICE					(CL_HTON16(0x0002))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO
+* NAME
+*	IB_MAD_ATTR_INFORM_INFO
+*
+* DESCRIPTION
+*	InformInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_INFORM_INFO				(CL_HTON16(0x0003))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC
+* NAME
+*	IB_MAD_ATTR_NODE_DESC
+*
+* DESCRIPTION
+*	NodeDescription attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_DESC				(CL_HTON16(0x0010))
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL
+* NAME
+*	IB_MAD_ATTR_PORT_SMPL_CTRL
+*
+* DESCRIPTION
+*	PortSamplesControl attribute (16.1.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_CTRL			(CL_HTON16(0x0010))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO
+* NAME
+*	IB_MAD_ATTR_NODE_INFO
+*
+* DESCRIPTION
+*	NodeInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_INFO				(CL_HTON16(0x0011))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT
+* NAME
+*	IB_MAD_ATTR_PORT_SMPL_RSLT
+*
+* DESCRIPTION
+*	PortSamplesResult attribute (16.1.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_RSLT			(CL_HTON16(0x0011))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO
+* NAME
+*	IB_MAD_ATTR_SWITCH_INFO
+*
+* DESCRIPTION
+*	SwitchInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SWITCH_INFO				(CL_HTON16(0x0012))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS
+* NAME
+*	IB_MAD_ATTR_PORT_CNTRS
+*
+* DESCRIPTION
+*	PortCounters attribute (16.1.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_CNTRS				(CL_HTON16(0x0012))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO
+* NAME
+*	IB_MAD_ATTR_GUID_INFO
+*
+* DESCRIPTION
+*	GUIDInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_GUID_INFO				(CL_HTON16(0x0014))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO
+* NAME
+*	IB_MAD_ATTR_PORT_INFO
+*
+* DESCRIPTION
+*	PortInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_INFO				(CL_HTON16(0x0015))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE
+* NAME
+*	IB_MAD_ATTR_P_KEY_TABLE
+*
+* DESCRIPTION
+*	PartitionTable attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_P_KEY_TABLE				(CL_HTON16(0x0016))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE
+* NAME
+*	IB_MAD_ATTR_SLVL_TABLE
+*
+* DESCRIPTION
+*	SL VL Mapping Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_TABLE				(CL_HTON16(0x0017))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION
+* NAME
+*	IB_MAD_ATTR_VL_ARBITRATION
+*
+* DESCRIPTION
+*	VL Arbitration Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VL_ARBITRATION			(CL_HTON16(0x0018))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL
+* NAME
+*	IB_MAD_ATTR_LIN_FWD_TBL
+*
+* DESCRIPTION
+*	Switch linear forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LIN_FWD_TBL				(CL_HTON16(0x0019))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL
+* NAME
+*	IB_MAD_ATTR_RND_FWD_TBL
+*
+* DESCRIPTION
+*	Switch random forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_RND_FWD_TBL				(CL_HTON16(0x001A))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL
+* NAME
+*	IB_MAD_ATTR_MCAST_FWD_TBL
+*
+* DESCRIPTION
+*	Switch multicast forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCAST_FWD_TBL			(CL_HTON16(0x001B))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD
+* NAME
+*	IB_MAD_ATTR_NODE_RECORD
+*
+* DESCRIPTION
+*	NodeRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_RECORD				(CL_HTON16(0x0011))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD
+* NAME
+*	IB_MAD_ATTR_PORTINFO_RECORD
+*
+* DESCRIPTION
+*	PortInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORTINFO_RECORD			(CL_HTON16(0x0012))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO_RECORD
+* NAME
+*       IB_MAD_ATTR_SWITCH_INFO_RECORD
+*
+* DESCRIPTION
+*       SwitchInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SWITCH_INFO_RECORD			(CL_HTON16(0x0014))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD
+* NAME
+*	IB_MAD_ATTR_LINK_RECORD
+*
+* DESCRIPTION
+*	LinkRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LINK_RECORD				(CL_HTON16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO
+* NAME
+*	IB_MAD_ATTR_SM_INFO
+*
+* DESCRIPTION
+*	SMInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SM_INFO				(CL_HTON16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD
+* NAME
+*	IB_MAD_ATTR_SMINFO_RECORD
+*
+* DESCRIPTION
+*	SMInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SMINFO_RECORD			(CL_HTON16(0x0018))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUIDINFO_RECORD
+* NAME
+*       IB_MAD_ATTR_GUIDINFO_RECORD
+*
+* DESCRIPTION
+*       GuidInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_GUIDINFO_RECORD			(CL_HTON16(0x0030))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG
+* NAME
+*	IB_MAD_ATTR_VENDOR_DIAG
+*
+* DESCRIPTION
+*	VendorDiag attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VENDOR_DIAG				(CL_HTON16(0x0030))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO
+* NAME
+*	IB_MAD_ATTR_LED_INFO
+*
+* DESCRIPTION
+*	LedInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LED_INFO				(CL_HTON16(0x0031))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD
+* NAME
+*	IB_MAD_ATTR_SERVICE_RECORD
+*
+* DESCRIPTION
+*	ServiceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_RECORD			(CL_HTON16(0x0031))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD
+* NAME
+*	IB_MAD_ATTR_LFT_RECORD
+*
+* DESCRIPTION
+*	LinearForwardingTableRecord attribute (15.2.5.6)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LFT_RECORD				(CL_HTON16(0x0015))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_MFT_RECORD
+* NAME
+*       IB_MAD_ATTR_MFT_RECORD
+*
+* DESCRIPTION
+*       MulticastForwardingTableRecord attribute (15.2.5.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MFT_RECORD				(CL_HTON16(0x0017))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD
+* NAME
+*	IB_MAD_ATTR_PKEYTBL_RECORD
+*
+* DESCRIPTION
+*	PKEY Table Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PKEY_TBL_RECORD			(CL_HTON16(0x0033))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD
+* NAME
+*	IB_MAD_ATTR_PATH_RECORD
+*
+* DESCRIPTION
+*	PathRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PATH_RECORD				(CL_HTON16(0x0035))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD
+* NAME
+*	IB_MAD_ATTR_VLARB_RECORD
+*
+* DESCRIPTION
+*	VL Arbitration Table Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VLARB_RECORD			(CL_HTON16(0x0036))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD
+* NAME
+*	IB_MAD_ATTR_SLVL_RECORD
+*
+* DESCRIPTION
+*	SLtoVL Mapping Table Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_RECORD				(CL_HTON16(0x0013))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD
+* NAME
+*	IB_MAD_ATTR_MCMEMBER_RECORD
+*
+* DESCRIPTION
+*	MCMemberRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCMEMBER_RECORD			(CL_HTON16(0x0038))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD
+* NAME
+*	IB_MAD_ATTR_TRACE_RECORD
+*
+* DESCRIPTION
+*	TraceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TRACE_RECORD			(CL_HTON16(0x0039))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD
+* NAME
+*	IB_MAD_ATTR_MULTIPATH_RECORD
+*
+* DESCRIPTION
+*	MultiPathRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MULTIPATH_RECORD			(CL_HTON16(0x003A))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+*	IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+*	Service Association Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD		(CL_HTON16(0x003B))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO_RECORD
+* NAME
+*	IB_MAD_ATTR_INFORM_INFO_RECORD
+*
+* DESCRIPTION
+*	InformInfo Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_INFORM_INFO_RECORD			(CL_HTON16(0x00F3))
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO
+* NAME
+*	IB_MAD_ATTR_IO_UNIT_INFO
+*
+* DESCRIPTION
+*	IOUnitInfo attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_UNIT_INFO			(CL_HTON16(0x0010))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+* NAME
+*	IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+*
+* DESCRIPTION
+*	IOControllerProfile attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_CONTROLLER_PROFILE	(CL_HTON16(0x0011))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES
+* NAME
+*	IB_MAD_ATTR_SERVICE_ENTRIES
+*
+* DESCRIPTION
+*	ServiceEntries attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_ENTRIES			(CL_HTON16(0x0012))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+* NAME
+*	IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+*
+* DESCRIPTION
+*	DiagnosticTimeout attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT		(CL_HTON16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST
+* NAME
+*	IB_MAD_ATTR_PREPARE_TO_TEST
+*
+* DESCRIPTION
+*	PrepareToTest attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PREPARE_TO_TEST			(CL_HTON16(0x0021))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE
+* NAME
+*	IB_MAD_ATTR_TEST_DEVICE_ONCE
+*
+* DESCRIPTION
+*	TestDeviceOnce attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_ONCE		(CL_HTON16(0x0022))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP
+* NAME
+*	IB_MAD_ATTR_TEST_DEVICE_LOOP
+*
+* DESCRIPTION
+*	TestDeviceLoop attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_LOOP		(CL_HTON16(0x0023))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE
+* NAME
+*	IB_MAD_ATTR_DIAG_CODE
+*
+* DESCRIPTION
+*	DiagCode attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAG_CODE				(CL_HTON16(0x0024))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+*	IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+*	Service Association Record attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD	(CL_HTON16(0x003B))
+/**********/
+
+/****d* IBA Base: Constants/IB_NODE_TYPE_CA
+* NAME
+*	IB_NODE_TYPE_CA
+*
+* DESCRIPTION
+*	Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_CA						0x01
+/**********/
+
+/****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH
+* NAME
+*	IB_NODE_TYPE_SWITCH
+*
+* DESCRIPTION
+*	Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_SWITCH					0x02
+/**********/
+
+/****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER
+* NAME
+*	IB_NODE_TYPE_ROUTER
+*
+* DESCRIPTION
+*	Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_ROUTER					0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_CA
+* NAME
+*	IB_NOTICE_PRODUCER_TYPE_CA
+*
+* DESCRIPTION
+*	Encoded generic producer type used in Notice attribute (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_PRODUCER_TYPE_CA			(CL_HTON32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_SWITCH
+* NAME
+*	IB_NOTICE_PRODUCER_TYPE_SWITCH
+*
+* DESCRIPTION
+*	Encoded generic producer type used in Notice attribute (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_PRODUCER_TYPE_SWITCH			(CL_HTON32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_ROUTER
+* NAME
+*	IB_NOTICE_PRODUCER_TYPE_ROUTER
+*
+* DESCRIPTION
+*	Encoded generic producer type used in Notice attribute (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_PRODUCER_TYPE_ROUTER			(CL_HTON32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_CLASS_MGR
+* NAME
+*	IB_NOTICE_PRODUCER_TYPE_CLASS_MGR
+*
+* DESCRIPTION
+*	Encoded generic producer type used in Notice attribute (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_PRODUCER_TYPE_CLASS_MGR			(CL_HTON32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_MTU_LEN_TYPE
+* NAME
+*	IB_MTU_LEN_TYPE
+*
+* DESCRIPTION
+*	Encoded path MTU.
+*		1: 256
+*		2: 512
+*		3: 1024
+*		4: 2048
+*		5: 4096
+*		others: reserved
+*
+* SOURCE
+*/
+#define IB_MTU_LEN_256							1
+#define IB_MTU_LEN_512							2
+#define IB_MTU_LEN_1024							3
+#define IB_MTU_LEN_2048							4
+#define IB_MTU_LEN_4096							5
+
+#define IB_MIN_MTU    IB_MTU_LEN_256
+#define IB_MAX_MTU    IB_MTU_LEN_4096
+
+/**********/
+
+/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE
+* NAME
+*	IB_PATH_SELECTOR_TYPE
+*
+* DESCRIPTION
+*	Path selector.
+*		0: greater than specified
+*		1: less than specified
+*		2: exactly the specified
+*		3: largest available
+*
+* SOURCE
+*/
+#define IB_PATH_SELECTOR_GREATER_THAN		0
+#define IB_PATH_SELECTOR_LESS_THAN		1
+#define IB_PATH_SELECTOR_EXACTLY		2
+#define IB_PATH_SELECTOR_LARGEST		3
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE
+* NAME
+*	IB_SMINFO_STATE_NOTACTIVE
+*
+* DESCRIPTION
+*	Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_NOTACTIVE			0
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING
+* NAME
+*	IB_SMINFO_STATE_DISCOVERING
+*
+* DESCRIPTION
+*	Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_DISCOVERING			1
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY
+* NAME
+*	IB_SMINFO_STATE_STANDBY
+*
+* DESCRIPTION
+*	Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_STANDBY				2
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER
+* NAME
+*	IB_SMINFO_STATE_MASTER
+*
+* DESCRIPTION
+*	Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_MASTER				3
+/**********/
+
+/****d* IBA Base: Constants/IB_PATH_REC_SL_MASK
+* NAME
+*	IB_PATH_REC_SL_MASK
+*
+* DESCRIPTION
+*	Mask for the sl field for path record
+*
+* SOURCE
+*/
+#define IB_PATH_REC_SL_MASK				0x000F
+
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SL_MASK
+* NAME
+*	IB_MILTIPATH_REC_SL_MASK
+*
+* DESCRIPTION
+*	Mask for the sl field for MultiPath record
+*
+* SOURCE
+*/
+#define IB_MULTIPATH_REC_SL_MASK			0x000F
+
+/****d* IBA Base: Constants/IB_PATH_REC_QOS_CLASS_MASK
+* NAME
+*	IB_PATH_REC_QOS_CLASS_MASK
+*
+* DESCRIPTION
+*	Mask for the QoS class field for path record
+*
+* SOURCE
+*/
+#define IB_PATH_REC_QOS_CLASS_MASK			0xFFF0
+
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_QOS_CLASS_MASK
+* NAME
+*	IB_MULTIPATH_REC_QOS_CLASS_MASK
+*
+* DESCRIPTION
+*	Mask for the QoS class field for MultiPath record
+*
+* SOURCE
+*/
+#define IB_MULTIPATH_REC_QOS_CLASS_MASK			0xFFF0
+
+/****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK
+* NAME
+*	IB_PATH_REC_SELECTOR_MASK
+*
+* DESCRIPTION
+*	Mask for the selector field for path record MTU, rate,
+*	and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_SELECTOR_MASK			0xC0
+
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SELECTOR_MASK
+* NAME
+*       IB_MULTIPATH_REC_SELECTOR_MASK
+*
+* DESCRIPTION
+*       Mask for the selector field for multipath record MTU, rate,
+*       and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_MULTIPATH_REC_SELECTOR_MASK                       0xC0
+/**********/
+
+/****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK
+* NAME
+*	IB_PATH_REC_BASE_MASK
+*
+* DESCRIPTION
+*	Mask for the base value field for path record MTU, rate,
+*	and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_BASE_MASK				0x3F
+/**********/
+
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_BASE_MASK
+* NAME
+*       IB_MULTIPATH_REC_BASE_MASK
+*
+* DESCRIPTION
+*       Mask for the base value field for multipath record MTU, rate,
+*       and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_MULTIPATH_REC_BASE_MASK                      0x3F
+/**********/
+
+/****h* IBA Base/Type Definitions
+* NAME
+*	Type Definitions
+*
+* DESCRIPTION
+*	Definitions are from the InfiniBand Architecture Specification v1.2
+*
+*********/
+
+/****d* IBA Base: Types/ib_net16_t
+* NAME
+*	ib_net16_t
+*
+* DESCRIPTION
+*	Defines the network ordered type for 16-bit values.
+*
+* SOURCE
+*/
+typedef uint16_t ib_net16_t;
+/**********/
+
+/****d* IBA Base: Types/ib_net32_t
+* NAME
+*	ib_net32_t
+*
+* DESCRIPTION
+*	Defines the network ordered type for 32-bit values.
+*
+* SOURCE
+*/
+typedef uint32_t ib_net32_t;
+/**********/
+
+/****d* IBA Base: Types/ib_net64_t
+* NAME
+*	ib_net64_t
+*
+* DESCRIPTION
+*	Defines the network ordered type for 64-bit values.
+*
+* SOURCE
+*/
+typedef uint64_t ib_net64_t;
+/**********/
+
+/****d* IBA Base: Types/ib_gid_prefix_t
+* NAME
+*	ib_gid_prefix_t
+*
+* DESCRIPTION
+*
+* SOURCE
+*/
+typedef ib_net64_t ib_gid_prefix_t;
+/**********/
+
+/****d* IBA Base: Constants/ib_link_states_t
+* NAME
+*	ib_link_states_t
+*
+* DESCRIPTION
+*	Defines the link states of a port.
+*
+* SOURCE
+*/
+#define IB_LINK_NO_CHANGE 0
+#define IB_LINK_DOWN      1
+#define IB_LINK_INIT	  2
+#define IB_LINK_ARMED     3
+#define IB_LINK_ACTIVE    4
+#define IB_LINK_ACT_DEFER 5
+/**********/
+
+static const char *const __ib_node_type_str[] = {
+	"UNKNOWN",
+	"Channel Adapter",
+	"Switch",
+	"Router"
+};
+
+/****f* IBA Base: Types/ib_get_node_type_str
+* NAME
+*	ib_get_node_type_str
+*
+* DESCRIPTION
+*	Returns a string for the specified node type.
+*	14.2.5.3 NodeInfo
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API ib_get_node_type_str(IN uint8_t node_type)
+{
+	if (node_type > IB_NODE_TYPE_ROUTER)
+		node_type = 0;
+	return (__ib_node_type_str[node_type]);
+}
+
+/*
+* PARAMETERS
+*	node_type
+*		[in] Encoded node type as returned in the NodeInfo attribute.
+
+* RETURN VALUES
+*	Pointer to the node type string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_node_info_t
+*********/
+
+static const char *const __ib_producer_type_str[] = {
+	"UNKNOWN",
+	"Channel Adapter",
+	"Switch",
+	"Router",
+	"Class Manager"
+};
+
+/****f* IBA Base: Types/ib_get_producer_type_str
+* NAME
+*	ib_get_producer_type_str
+*
+* DESCRIPTION
+*	Returns a string for the specified producer type
+*	13.4.8.2 Notice
+*	13.4.8.3 InformInfo
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API
+ib_get_producer_type_str(IN ib_net32_t producer_type)
+{
+	if (cl_ntoh32(producer_type) >
+	    CL_NTOH32(IB_NOTICE_PRODUCER_TYPE_CLASS_MGR))
+		producer_type = 0;
+	return (__ib_producer_type_str[cl_ntoh32(producer_type)]);
+}
+
+/*
+* PARAMETERS
+*	producer_type
+*		[in] Encoded producer type from the Notice attribute
+
+* RETURN VALUES
+*	Pointer to the producer type string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_notice_get_prod_type
+*********/
+
+static const char *const __ib_port_state_str[] = {
+	"No State Change (NOP)",
+	"DOWN",
+	"INIT",
+	"ARMED",
+	"ACTIVE",
+	"ACTDEFER",
+	"UNKNOWN"
+};
+
+/****f* IBA Base: Types/ib_get_port_state_str
+* NAME
+*	ib_get_port_state_str
+*
+* DESCRIPTION
+*	Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API ib_get_port_state_str(IN uint8_t port_state)
+{
+	if (port_state > IB_LINK_ACTIVE)
+		port_state = IB_LINK_ACTIVE + 1;
+	return (__ib_port_state_str[port_state]);
+}
+
+/*
+* PARAMETERS
+*	port_state
+*		[in] Encoded port state as returned in the PortInfo attribute.
+
+* RETURN VALUES
+*	Pointer to the port state string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_get_port_state_from_str
+* NAME
+*	ib_get_port_state_from_str
+*
+* DESCRIPTION
+*	Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_get_port_state_from_str(IN char *p_port_state_str)
+{
+	if (!strncmp(p_port_state_str, "No State Change (NOP)", 12))
+		return (0);
+	else if (!strncmp(p_port_state_str, "DOWN", 4))
+		return (1);
+	else if (!strncmp(p_port_state_str, "INIT", 4))
+		return (2);
+	else if (!strncmp(p_port_state_str, "ARMED", 5))
+		return (3);
+	else if (!strncmp(p_port_state_str, "ACTIVE", 6))
+		return (4);
+	else if (!strncmp(p_port_state_str, "ACTDEFER", 8))
+		return (5);
+	return (6);
+}
+
+/*
+* PARAMETERS
+*	p_port_state_str
+*		[in] A string matching one returned by ib_get_port_state_str
+*
+* RETURN VALUES
+*	The appropriate code.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_port_info_t
+*********/
+
+/****d* IBA Base: Constants/Join States
+* NAME
+*	Join States
+*
+* DESCRIPTION
+*	Defines the join state flags for multicast group management.
+*
+* SOURCE
+*/
+#define IB_JOIN_STATE_FULL		1
+#define IB_JOIN_STATE_NON		2
+#define IB_JOIN_STATE_SEND_ONLY		4
+/**********/
+
+/****f* IBA Base: Types/ib_pkey_get_base
+* NAME
+*	ib_pkey_get_base
+*
+* DESCRIPTION
+*	Returns the base P_Key value with the membership bit stripped.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t OSM_API ib_pkey_get_base(IN const ib_net16_t pkey)
+{
+	return ((ib_net16_t) (pkey & IB_PKEY_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*	pkey
+*		[in] P_Key value
+*
+* RETURN VALUE
+*	Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_pkey_is_full_member
+* NAME
+*	ib_pkey_is_full_member
+*
+* DESCRIPTION
+*	Indicates if the port is a full member of the parition.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API ib_pkey_is_full_member(IN const ib_net16_t pkey)
+{
+	return ((pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK);
+}
+
+/*
+* PARAMETERS
+*	pkey
+*		[in] P_Key value
+*
+* RETURN VALUE
+*	TRUE if the port is a full member of the partition.
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_pkey_get_base, ib_net16_t
+*********/
+
+/****f* IBA Base: Types/ib_pkey_is_invalid
+* NAME
+*	ib_pkey_is_invalid
+*
+* DESCRIPTION
+*	Returns TRUE if the given P_Key is an invalid P_Key
+*  C10-116: the CI shall regard a P_Key as invalid if its low-order
+*           15 bits are all zero...
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API ib_pkey_is_invalid(IN const ib_net16_t pkey)
+{
+	if (ib_pkey_get_base(pkey) == 0x0000)
+		return TRUE;
+
+	return FALSE;
+}
+
+/*
+* PARAMETERS
+*	pkey
+*		[in] P_Key value
+*
+* RETURN VALUE
+*	Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* IBA Base: Types/ib_gid_t
+* NAME
+*	ib_gid_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef union _ib_gid {
+	uint8_t raw[16];
+	struct _ib_gid_unicast {
+		ib_gid_prefix_t prefix;
+		ib_net64_t interface_id;
+
+	} PACK_SUFFIX unicast;
+
+	struct _ib_gid_multicast {
+		uint8_t header[2];
+		uint8_t raw_group_id[14];
+
+	} PACK_SUFFIX multicast;
+
+} PACK_SUFFIX ib_gid_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	raw
+*		GID represented as an unformated byte array.
+*
+*	unicast
+*		Typical unicast representation with subnet prefix and
+*		port GUID.
+*
+*	multicast
+*		Representation for multicast use.
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_gid_is_multicast
+* NAME
+*	ib_gid_is_multicast
+*
+* DESCRIPTION
+*       Returns a boolean indicating whether a GID is a multicast GID.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API ib_gid_is_multicast(IN const ib_gid_t * p_gid)
+{
+	return (p_gid->raw[0] == 0xFF);
+}
+
+/****f* IBA Base: Types/ib_gid_get_scope
+* NAME
+*	ib_gid_get_scope
+*
+* DESCRIPTION
+*	Returns scope of (assumed) multicast GID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API ib_mgid_get_scope(IN const ib_gid_t * p_gid)
+{
+	return (p_gid->raw[1] & 0x0F);
+}
+
+/****f* IBA Base: Types/ib_gid_set_scope
+* NAME
+*	ib_gid_set_scope
+*
+* DESCRIPTION
+*	Sets scope of (assumed) multicast GID.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_mgid_set_scope(IN ib_gid_t * const p_gid, IN const uint8_t scope)
+{
+	p_gid->raw[1] &= 0xF0;
+	p_gid->raw[1] |= scope & 0x0F;
+}
+
+/****f* IBA Base: Types/ib_gid_set_default
+* NAME
+*	ib_gid_set_default
+*
+* DESCRIPTION
+*	Sets a GID to the default value.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_gid_set_default(IN ib_gid_t * const p_gid, IN const ib_net64_t interface_id)
+{
+	p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;
+	p_gid->unicast.interface_id = interface_id;
+}
+
+/*
+* PARAMETERS
+*	p_gid
+*		[in] Pointer to the GID object.
+*
+*	interface_id
+*		[in] Manufacturer assigned EUI64 value of a port.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_gid_get_subnet_prefix
+* NAME
+*	ib_gid_get_subnet_prefix
+*
+* DESCRIPTION
+*	Gets the subnet prefix from a GID.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t OSM_API
+ib_gid_get_subnet_prefix(IN const ib_gid_t * const p_gid)
+{
+	return (p_gid->unicast.prefix);
+}
+
+/*
+* PARAMETERS
+*	p_gid
+*		[in] Pointer to the GID object.
+*
+* RETURN VALUES
+*	64-bit subnet prefix value.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_gid_is_link_local
+* NAME
+*	ib_gid_is_link_local
+*
+* DESCRIPTION
+*	Returns TRUE if the unicast GID scoping indicates link local,
+*	FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_gid_is_link_local(IN const ib_gid_t * const p_gid)
+{
+	return ((ib_gid_get_subnet_prefix(p_gid) &
+		 CL_HTON64(0xFFC0000000000000ULL)) == IB_DEFAULT_SUBNET_PREFIX);
+}
+
+/*
+* PARAMETERS
+*	p_gid
+*		[in] Pointer to the GID object.
+*
+* RETURN VALUES
+*	Returns TRUE if the unicast GID scoping indicates link local,
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_gid_is_site_local
+* NAME
+*	ib_gid_is_site_local
+*
+* DESCRIPTION
+*	Returns TRUE if the unicast GID scoping indicates site local,
+*	FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_gid_is_site_local(IN const ib_gid_t * const p_gid)
+{
+	return ((ib_gid_get_subnet_prefix(p_gid) &
+		 CL_HTON64(0xFFFFFFFFFFFF0000ULL)) ==
+		CL_HTON64(0xFEC0000000000000ULL));
+}
+
+/*
+* PARAMETERS
+*	p_gid
+*		[in] Pointer to the GID object.
+*
+* RETURN VALUES
+*	Returns TRUE if the unicast GID scoping indicates site local,
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_gid_get_guid
+* NAME
+*	ib_gid_get_guid
+*
+* DESCRIPTION
+*	Gets the guid from a GID.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t OSM_API
+ib_gid_get_guid(IN const ib_gid_t * const p_gid)
+{
+	return (p_gid->unicast.interface_id);
+}
+
+/*
+* PARAMETERS
+*	p_gid
+*		[in] Pointer to the GID object.
+*
+* RETURN VALUES
+*	64-bit GUID value.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****s* IBA Base: Types/ib_path_rec_t
+* NAME
+*	ib_path_rec_t
+*
+* DESCRIPTION
+*	Path records encapsulate the properties of a given
+*	route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_path_rec {
+	ib_net64_t service_id;
+	ib_gid_t dgid;
+	ib_gid_t sgid;
+	ib_net16_t dlid;
+	ib_net16_t slid;
+	ib_net32_t hop_flow_raw;
+	uint8_t tclass;
+	uint8_t num_path;
+	ib_net16_t pkey;
+	ib_net16_t qos_class_sl;
+	uint8_t mtu;
+	uint8_t rate;
+	uint8_t pkt_life;
+	uint8_t preference;
+	uint8_t resv2[6];
+
+} PACK_SUFFIX ib_path_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	service_id
+*		Service ID for QoS.
+*
+*	dgid
+*		GID of destination port.
+*
+*	sgid
+*		GID of source port.
+*
+*	dlid
+*		LID of destination port.
+*
+*	slid
+*		LID of source port.
+*
+*	hop_flow_raw
+*		Global routing parameters: hop count, flow label and raw bit.
+*
+*	tclass
+*		Another global routing parameter.
+*
+*	num_path
+*     Reversible path - 1 bit to say if path is reversible.
+*		num_path [6:0] In queries, maximum number of paths to return.
+*		In responses, undefined.
+*
+*	pkey
+*		Partition key (P_Key) to use on this path.
+*
+*	qos_class_sl
+*		QoS class and service level to use on this path.
+*
+*	mtu
+*		MTU and MTU selector fields to use on this path
+*
+*	rate
+*		Rate and rate selector fields to use on this path.
+*
+*	pkt_life
+*		Packet lifetime
+*
+*	preference
+*		Indicates the relative merit of this path versus other path
+*		records returned from the SA.  Lower numbers are better.
+*
+*	resv2
+*		Reserved bytes.
+* SEE ALSO
+*********/
+
+/* Path Record Component Masks */
+#define  IB_PR_COMPMASK_SERVICEID_MSB     (CL_HTON64(((uint64_t)1)<<0))
+#define  IB_PR_COMPMASK_SERVICEID_LSB     (CL_HTON64(((uint64_t)1)<<1))
+#define  IB_PR_COMPMASK_DGID              (CL_HTON64(((uint64_t)1)<<2))
+#define  IB_PR_COMPMASK_SGID              (CL_HTON64(((uint64_t)1)<<3))
+#define  IB_PR_COMPMASK_DLID              (CL_HTON64(((uint64_t)1)<<4))
+#define  IB_PR_COMPMASK_SLID              (CL_HTON64(((uint64_t)1)<<5))
+#define  IB_PR_COMPMASK_RAWTRAFFIC        (CL_HTON64(((uint64_t)1)<<6))
+#define  IB_PR_COMPMASK_RESV0             (CL_HTON64(((uint64_t)1)<<7))
+#define  IB_PR_COMPMASK_FLOWLABEL         (CL_HTON64(((uint64_t)1)<<8))
+#define  IB_PR_COMPMASK_HOPLIMIT          (CL_HTON64(((uint64_t)1)<<9))
+#define  IB_PR_COMPMASK_TCLASS            (CL_HTON64(((uint64_t)1)<<10))
+#define  IB_PR_COMPMASK_REVERSIBLE        (CL_HTON64(((uint64_t)1)<<11))
+#define  IB_PR_COMPMASK_NUMBPATH          (CL_HTON64(((uint64_t)1)<<12))
+#define  IB_PR_COMPMASK_PKEY              (CL_HTON64(((uint64_t)1)<<13))
+#define  IB_PR_COMPMASK_QOS_CLASS         (CL_HTON64(((uint64_t)1)<<14))
+#define  IB_PR_COMPMASK_SL                (CL_HTON64(((uint64_t)1)<<15))
+#define  IB_PR_COMPMASK_MTUSELEC          (CL_HTON64(((uint64_t)1)<<16))
+#define  IB_PR_COMPMASK_MTU               (CL_HTON64(((uint64_t)1)<<17))
+#define  IB_PR_COMPMASK_RATESELEC         (CL_HTON64(((uint64_t)1)<<18))
+#define  IB_PR_COMPMASK_RATE              (CL_HTON64(((uint64_t)1)<<19))
+#define  IB_PR_COMPMASK_PKTLIFETIMESELEC  (CL_HTON64(((uint64_t)1)<<20))
+#define  IB_PR_COMPMASK_PKTLIFETIME       (CL_HTON64(((uint64_t)1)<<21))
+
+/* Link Record Component Masks */
+#define IB_LR_COMPMASK_FROM_LID           (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LR_COMPMASK_FROM_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_LR_COMPMASK_TO_PORT            (CL_HTON64(((uint64_t)1)<<2))
+#define IB_LR_COMPMASK_TO_LID             (CL_HTON64(((uint64_t)1)<<3))
+
+/* VL Arbitration Record Masks */
+#define IB_VLA_COMPMASK_LID               (CL_HTON64(((uint64_t)1)<<0))
+#define IB_VLA_COMPMASK_OUT_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_VLA_COMPMASK_BLOCK             (CL_HTON64(((uint64_t)1)<<2))
+
+/* SLtoVL Mapping Record Masks */
+#define IB_SLVL_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SLVL_COMPMASK_IN_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SLVL_COMPMASK_OUT_PORT         (CL_HTON64(((uint64_t)1)<<2))
+
+/* P_Key Table Record Masks */
+#define IB_PKEY_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PKEY_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PKEY_COMPMASK_PORT             (CL_HTON64(((uint64_t)1)<<2))
+
+/* Switch Info Record Masks */
+#define IB_SWIR_COMPMASK_LID		  (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SWIR_COMPMASK_RESERVED1	  (CL_HTON64(((uint64_t)1)<<1))
+
+/* LFT Record Masks */
+#define IB_LFTR_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LFTR_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))
+
+/* MFT Record Masks */
+#define IB_MFTR_COMPMASK_LID		  (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MFTR_COMPMASK_POSITION	  (CL_HTON64(((uint64_t)1)<<1))
+#define IB_MFTR_COMPMASK_RESERVED1	  (CL_HTON64(((uint64_t)1)<<2))
+#define IB_MFTR_COMPMASK_BLOCK		  (CL_HTON64(((uint64_t)1)<<3))
+#define IB_MFTR_COMPMASK_RESERVED2	  (CL_HTON64(((uint64_t)1)<<4))
+
+/* NodeInfo Record Masks */
+#define IB_NR_COMPMASK_LID                (CL_HTON64(((uint64_t)1)<<0))
+#define IB_NR_COMPMASK_RESERVED1          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_NR_COMPMASK_BASEVERSION        (CL_HTON64(((uint64_t)1)<<2))
+#define IB_NR_COMPMASK_CLASSVERSION       (CL_HTON64(((uint64_t)1)<<3))
+#define IB_NR_COMPMASK_NODETYPE           (CL_HTON64(((uint64_t)1)<<4))
+#define IB_NR_COMPMASK_NUMPORTS           (CL_HTON64(((uint64_t)1)<<5))
+#define IB_NR_COMPMASK_SYSIMAGEGUID       (CL_HTON64(((uint64_t)1)<<6))
+#define IB_NR_COMPMASK_NODEGUID           (CL_HTON64(((uint64_t)1)<<7))
+#define IB_NR_COMPMASK_PORTGUID           (CL_HTON64(((uint64_t)1)<<8))
+#define IB_NR_COMPMASK_PARTCAP            (CL_HTON64(((uint64_t)1)<<9))
+#define IB_NR_COMPMASK_DEVID              (CL_HTON64(((uint64_t)1)<<10))
+#define IB_NR_COMPMASK_REV                (CL_HTON64(((uint64_t)1)<<11))
+#define IB_NR_COMPMASK_PORTNUM            (CL_HTON64(((uint64_t)1)<<12))
+#define IB_NR_COMPMASK_VENDID             (CL_HTON64(((uint64_t)1)<<13))
+#define IB_NR_COMPMASK_NODEDESC           (CL_HTON64(((uint64_t)1)<<14))
+
+/* Service Record Component Masks Sec 15.2.5.14 Ver 1.1*/
+#define IB_SR_COMPMASK_SID                (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SR_COMPMASK_SGID               (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SR_COMPMASK_SPKEY              (CL_HTON64(((uint64_t)1)<<2))
+#define IB_SR_COMPMASK_RES1               (CL_HTON64(((uint64_t)1)<<3))
+#define IB_SR_COMPMASK_SLEASE             (CL_HTON64(((uint64_t)1)<<4))
+#define IB_SR_COMPMASK_SKEY               (CL_HTON64(((uint64_t)1)<<5))
+#define IB_SR_COMPMASK_SNAME              (CL_HTON64(((uint64_t)1)<<6))
+#define IB_SR_COMPMASK_SDATA8_0           (CL_HTON64(((uint64_t)1)<<7))
+#define IB_SR_COMPMASK_SDATA8_1           (CL_HTON64(((uint64_t)1)<<8))
+#define IB_SR_COMPMASK_SDATA8_2           (CL_HTON64(((uint64_t)1)<<9))
+#define IB_SR_COMPMASK_SDATA8_3           (CL_HTON64(((uint64_t)1)<<10))
+#define IB_SR_COMPMASK_SDATA8_4           (CL_HTON64(((uint64_t)1)<<11))
+#define IB_SR_COMPMASK_SDATA8_5           (CL_HTON64(((uint64_t)1)<<12))
+#define IB_SR_COMPMASK_SDATA8_6           (CL_HTON64(((uint64_t)1)<<13))
+#define IB_SR_COMPMASK_SDATA8_7           (CL_HTON64(((uint64_t)1)<<14))
+#define IB_SR_COMPMASK_SDATA8_8           (CL_HTON64(((uint64_t)1)<<15))
+#define IB_SR_COMPMASK_SDATA8_9           (CL_HTON64(((uint64_t)1)<<16))
+#define IB_SR_COMPMASK_SDATA8_10       (CL_HTON64(((uint64_t)1)<<17))
+#define IB_SR_COMPMASK_SDATA8_11       (CL_HTON64(((uint64_t)1)<<18))
+#define IB_SR_COMPMASK_SDATA8_12       (CL_HTON64(((uint64_t)1)<<19))
+#define IB_SR_COMPMASK_SDATA8_13       (CL_HTON64(((uint64_t)1)<<20))
+#define IB_SR_COMPMASK_SDATA8_14       (CL_HTON64(((uint64_t)1)<<21))
+#define IB_SR_COMPMASK_SDATA8_15       (CL_HTON64(((uint64_t)1)<<22))
+#define IB_SR_COMPMASK_SDATA16_0       (CL_HTON64(((uint64_t)1)<<23))
+#define IB_SR_COMPMASK_SDATA16_1       (CL_HTON64(((uint64_t)1)<<24))
+#define IB_SR_COMPMASK_SDATA16_2       (CL_HTON64(((uint64_t)1)<<25))
+#define IB_SR_COMPMASK_SDATA16_3       (CL_HTON64(((uint64_t)1)<<26))
+#define IB_SR_COMPMASK_SDATA16_4       (CL_HTON64(((uint64_t)1)<<27))
+#define IB_SR_COMPMASK_SDATA16_5       (CL_HTON64(((uint64_t)1)<<28))
+#define IB_SR_COMPMASK_SDATA16_6       (CL_HTON64(((uint64_t)1)<<29))
+#define IB_SR_COMPMASK_SDATA16_7       (CL_HTON64(((uint64_t)1)<<30))
+#define IB_SR_COMPMASK_SDATA32_0       (CL_HTON64(((uint64_t)1)<<31))
+#define IB_SR_COMPMASK_SDATA32_1       (CL_HTON64(((uint64_t)1)<<32))
+#define IB_SR_COMPMASK_SDATA32_2       (CL_HTON64(((uint64_t)1)<<33))
+#define IB_SR_COMPMASK_SDATA32_3       (CL_HTON64(((uint64_t)1)<<34))
+#define IB_SR_COMPMASK_SDATA64_0       (CL_HTON64(((uint64_t)1)<<35))
+#define IB_SR_COMPMASK_SDATA64_1       (CL_HTON64(((uint64_t)1)<<36))
+
+/* Port Info Record Component Masks */
+#define IB_PIR_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PIR_COMPMASK_PORTNUM          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PIR_COMPMASK_RESV1            (CL_HTON64(((uint64_t)1)<<2))
+#define IB_PIR_COMPMASK_MKEY             (CL_HTON64(((uint64_t)1)<<3))
+#define IB_PIR_COMPMASK_GIDPRE           (CL_HTON64(((uint64_t)1)<<4))
+#define IB_PIR_COMPMASK_BASELID          (CL_HTON64(((uint64_t)1)<<5))
+#define IB_PIR_COMPMASK_SMLID            (CL_HTON64(((uint64_t)1)<<6))
+#define IB_PIR_COMPMASK_CAPMASK          (CL_HTON64(((uint64_t)1)<<7))
+#define IB_PIR_COMPMASK_DIAGCODE         (CL_HTON64(((uint64_t)1)<<8))
+#define IB_PIR_COMPMASK_MKEYLEASEPRD     (CL_HTON64(((uint64_t)1)<<9))
+#define IB_PIR_COMPMASK_LOCALPORTNUM     (CL_HTON64(((uint64_t)1)<<10))
+#define IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11))
+#define IB_PIR_COMPMASK_LNKWIDTHSUPPORT  (CL_HTON64(((uint64_t)1)<<12))
+#define IB_PIR_COMPMASK_LNKWIDTHACTIVE   (CL_HTON64(((uint64_t)1)<<13))
+#define IB_PIR_COMPMASK_LNKSPEEDSUPPORT  (CL_HTON64(((uint64_t)1)<<14))
+#define IB_PIR_COMPMASK_PORTSTATE        (CL_HTON64(((uint64_t)1)<<15))
+#define IB_PIR_COMPMASK_PORTPHYSTATE     (CL_HTON64(((uint64_t)1)<<16))
+#define IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17))
+#define IB_PIR_COMPMASK_MKEYPROTBITS     (CL_HTON64(((uint64_t)1)<<18))
+#define IB_PIR_COMPMASK_RESV2            (CL_HTON64(((uint64_t)1)<<19))
+#define IB_PIR_COMPMASK_LMC              (CL_HTON64(((uint64_t)1)<<20))
+#define IB_PIR_COMPMASK_LINKSPEEDACTIVE  (CL_HTON64(((uint64_t)1)<<21))
+#define IB_PIR_COMPMASK_LINKSPEEDENABLE  (CL_HTON64(((uint64_t)1)<<22))
+#define IB_PIR_COMPMASK_NEIGHBORMTU      (CL_HTON64(((uint64_t)1)<<23))
+#define IB_PIR_COMPMASK_MASTERSMSL       (CL_HTON64(((uint64_t)1)<<24))
+#define IB_PIR_COMPMASK_VLCAP            (CL_HTON64(((uint64_t)1)<<25))
+#define IB_PIR_COMPMASK_INITTYPE         (CL_HTON64(((uint64_t)1)<<26))
+#define IB_PIR_COMPMASK_VLHIGHLIMIT      (CL_HTON64(((uint64_t)1)<<27))
+#define IB_PIR_COMPMASK_VLARBHIGHCAP     (CL_HTON64(((uint64_t)1)<<28))
+#define IB_PIR_COMPMASK_VLARBLOWCAP      (CL_HTON64(((uint64_t)1)<<29))
+#define IB_PIR_COMPMASK_INITTYPEREPLY    (CL_HTON64(((uint64_t)1)<<30))
+#define IB_PIR_COMPMASK_MTUCAP           (CL_HTON64(((uint64_t)1)<<31))
+#define IB_PIR_COMPMASK_VLSTALLCNT       (CL_HTON64(((uint64_t)1)<<32))
+#define IB_PIR_COMPMASK_HOQLIFE          (CL_HTON64(((uint64_t)1)<<33))
+#define IB_PIR_COMPMASK_OPVLS            (CL_HTON64(((uint64_t)1)<<34))
+#define IB_PIR_COMPMASK_PARENFIN         (CL_HTON64(((uint64_t)1)<<35))
+#define IB_PIR_COMPMASK_PARENFOUT        (CL_HTON64(((uint64_t)1)<<36))
+#define IB_PIR_COMPMASK_FILTERRAWIN      (CL_HTON64(((uint64_t)1)<<37))
+#define IB_PIR_COMPMASK_FILTERRAWOUT     (CL_HTON64(((uint64_t)1)<<38))
+#define IB_PIR_COMPMASK_MKEYVIO          (CL_HTON64(((uint64_t)1)<<39))
+#define IB_PIR_COMPMASK_PKEYVIO          (CL_HTON64(((uint64_t)1)<<40))
+#define IB_PIR_COMPMASK_QKEYVIO          (CL_HTON64(((uint64_t)1)<<41))
+#define IB_PIR_COMPMASK_GUIDCAP          (CL_HTON64(((uint64_t)1)<<42))
+#define IB_PIR_COMPMASK_RESV3            (CL_HTON64(((uint64_t)1)<<43))
+#define IB_PIR_COMPMASK_SUBNTO           (CL_HTON64(((uint64_t)1)<<44))
+#define IB_PIR_COMPMASK_RESV4            (CL_HTON64(((uint64_t)1)<<45))
+#define IB_PIR_COMPMASK_RESPTIME         (CL_HTON64(((uint64_t)1)<<46))
+#define IB_PIR_COMPMASK_LOCALPHYERR      (CL_HTON64(((uint64_t)1)<<47))
+#define IB_PIR_COMPMASK_OVERRUNERR       (CL_HTON64(((uint64_t)1)<<48))
+
+/* Multicast Member Record Component Masks */
+#define IB_MCR_COMPMASK_GID         (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_MGID        (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_PORT_GID    (CL_HTON64(((uint64_t)1)<<1))
+#define IB_MCR_COMPMASK_QKEY        (CL_HTON64(((uint64_t)1)<<2))
+#define IB_MCR_COMPMASK_MLID        (CL_HTON64(((uint64_t)1)<<3))
+#define IB_MCR_COMPMASK_MTU_SEL     (CL_HTON64(((uint64_t)1)<<4))
+#define IB_MCR_COMPMASK_MTU         (CL_HTON64(((uint64_t)1)<<5))
+#define IB_MCR_COMPMASK_TCLASS      (CL_HTON64(((uint64_t)1)<<6))
+#define IB_MCR_COMPMASK_PKEY        (CL_HTON64(((uint64_t)1)<<7))
+#define IB_MCR_COMPMASK_RATE_SEL    (CL_HTON64(((uint64_t)1)<<8))
+#define IB_MCR_COMPMASK_RATE        (CL_HTON64(((uint64_t)1)<<9))
+#define IB_MCR_COMPMASK_LIFE_SEL    (CL_HTON64(((uint64_t)1)<<10))
+#define IB_MCR_COMPMASK_LIFE        (CL_HTON64(((uint64_t)1)<<11))
+#define IB_MCR_COMPMASK_SL          (CL_HTON64(((uint64_t)1)<<12))
+#define IB_MCR_COMPMASK_FLOW        (CL_HTON64(((uint64_t)1)<<13))
+#define IB_MCR_COMPMASK_HOP         (CL_HTON64(((uint64_t)1)<<14))
+#define IB_MCR_COMPMASK_SCOPE       (CL_HTON64(((uint64_t)1)<<15))
+#define IB_MCR_COMPMASK_JOIN_STATE  (CL_HTON64(((uint64_t)1)<<16))
+#define IB_MCR_COMPMASK_PROXY       (CL_HTON64(((uint64_t)1)<<17))
+
+/* GUID Info Record Component Masks */
+#define IB_GIR_COMPMASK_LID		(CL_HTON64(((uint64_t)1)<<0))
+#define IB_GIR_COMPMASK_BLOCKNUM	(CL_HTON64(((uint64_t)1)<<1))
+#define IB_GIR_COMPMASK_RESV1		(CL_HTON64(((uint64_t)1)<<2))
+#define IB_GIR_COMPMASK_RESV2		(CL_HTON64(((uint64_t)1)<<3))
+#define IB_GIR_COMPMASK_GID0		(CL_HTON64(((uint64_t)1)<<4))
+#define IB_GIR_COMPMASK_GID1		(CL_HTON64(((uint64_t)1)<<5))
+#define IB_GIR_COMPMASK_GID2		(CL_HTON64(((uint64_t)1)<<6))
+#define IB_GIR_COMPMASK_GID3		(CL_HTON64(((uint64_t)1)<<7))
+#define IB_GIR_COMPMASK_GID4		(CL_HTON64(((uint64_t)1)<<8))
+#define IB_GIR_COMPMASK_GID5		(CL_HTON64(((uint64_t)1)<<9))
+#define IB_GIR_COMPMASK_GID6		(CL_HTON64(((uint64_t)1)<<10))
+#define IB_GIR_COMPMASK_GID7		(CL_HTON64(((uint64_t)1)<<11))
+
+/* MultiPath Record Component Masks */
+#define IB_MPR_COMPMASK_RAWTRAFFIC	(CL_HTON64(((uint64_t)1)<<0))
+#define IB_MPR_COMPMASK_RESV0		(CL_HTON64(((uint64_t)1)<<1))
+#define IB_MPR_COMPMASK_FLOWLABEL	(CL_HTON64(((uint64_t)1)<<2))
+#define IB_MPR_COMPMASK_HOPLIMIT	(CL_HTON64(((uint64_t)1)<<3))
+#define IB_MPR_COMPMASK_TCLASS		(CL_HTON64(((uint64_t)1)<<4))
+#define IB_MPR_COMPMASK_REVERSIBLE	(CL_HTON64(((uint64_t)1)<<5))
+#define IB_MPR_COMPMASK_NUMBPATH	(CL_HTON64(((uint64_t)1)<<6))
+#define IB_MPR_COMPMASK_PKEY		(CL_HTON64(((uint64_t)1)<<7))
+#define IB_MPR_COMPMASK_QOS_CLASS	(CL_HTON64(((uint64_t)1)<<8))
+#define IB_MPR_COMPMASK_SL		(CL_HTON64(((uint64_t)1)<<9))
+#define IB_MPR_COMPMASK_MTUSELEC	(CL_HTON64(((uint64_t)1)<<10))
+#define IB_MPR_COMPMASK_MTU		(CL_HTON64(((uint64_t)1)<<11))
+#define IB_MPR_COMPMASK_RATESELEC	(CL_HTON64(((uint64_t)1)<<12))
+#define IB_MPR_COMPMASK_RATE		(CL_HTON64(((uint64_t)1)<<13))
+#define IB_MPR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<14))
+#define IB_MPR_COMPMASK_PKTLIFETIME	(CL_HTON64(((uint64_t)1)<<15))
+#define IB_MPR_COMPMASK_SERVICEID_MSB	(CL_HTON64(((uint64_t)1)<<16))
+#define IB_MPR_COMPMASK_INDEPSELEC	(CL_HTON64(((uint64_t)1)<<17))
+#define IB_MPR_COMPMASK_RESV3		(CL_HTON64(((uint64_t)1)<<18))
+#define IB_MPR_COMPMASK_SGIDCOUNT	(CL_HTON64(((uint64_t)1)<<19))
+#define IB_MPR_COMPMASK_DGIDCOUNT	(CL_HTON64(((uint64_t)1)<<20))
+#define IB_MPR_COMPMASK_SERVICEID_LSB	(CL_HTON64(((uint64_t)1)<<21))
+
+/* SMInfo Record Component Masks */
+#define IB_SMIR_COMPMASK_LID		(CL_HTON64(((uint64_t)1)<<0))
+#define IB_SMIR_COMPMASK_RESV0		(CL_HTON64(((uint64_t)1)<<1))
+#define IB_SMIR_COMPMASK_GUID		(CL_HTON64(((uint64_t)1)<<2))
+#define IB_SMIR_COMPMASK_SMKEY		(CL_HTON64(((uint64_t)1)<<3))
+#define IB_SMIR_COMPMASK_ACTCOUNT	(CL_HTON64(((uint64_t)1)<<4))
+#define IB_SMIR_COMPMASK_PRIORITY	(CL_HTON64(((uint64_t)1)<<5))
+#define IB_SMIR_COMPMASK_SMSTATE	(CL_HTON64(((uint64_t)1)<<6))
+
+/* InformInfo Record Component Masks */
+#define IB_IIR_COMPMASK_SUBSCRIBERGID	(CL_HTON64(((uint64_t)1)<<0))
+#define IB_IIR_COMPMASK_ENUM		(CL_HTON64(((uint64_t)1)<<1))
+#define IB_IIR_COMPMASK_RESV0		(CL_HTON64(((uint64_t)1)<<2))
+#define IB_IIR_COMPMASK_GID		(CL_HTON64(((uint64_t)1)<<3))
+#define IB_IIR_COMPMASK_LIDRANGEBEGIN	(CL_HTON64(((uint64_t)1)<<4))
+#define IB_IIR_COMPMASK_LIDRANGEEND	(CL_HTON64(((uint64_t)1)<<5))
+#define IB_IIR_COMPMASK_RESV1		(CL_HTON64(((uint64_t)1)<<6))
+#define IB_IIR_COMPMASK_ISGENERIC	(CL_HTON64(((uint64_t)1)<<7))
+#define IB_IIR_COMPMASK_SUBSCRIBE	(CL_HTON64(((uint64_t)1)<<8))
+#define IB_IIR_COMPMASK_TYPE		(CL_HTON64(((uint64_t)1)<<9))
+#define IB_IIR_COMPMASK_TRAPNUMB	(CL_HTON64(((uint64_t)1)<<10))
+#define IB_IIR_COMPMASK_DEVICEID	(CL_HTON64(((uint64_t)1)<<10))
+#define IB_IIR_COMPMASK_QPN		(CL_HTON64(((uint64_t)1)<<11))
+#define IB_IIR_COMPMASK_RESV2		(CL_HTON64(((uint64_t)1)<<12))
+#define IB_IIR_COMPMASK_RESPTIME	(CL_HTON64(((uint64_t)1)<<13))
+#define IB_IIR_COMPMASK_RESV3		(CL_HTON64(((uint64_t)1)<<14))
+#define IB_IIR_COMPMASK_PRODTYPE	(CL_HTON64(((uint64_t)1)<<15))
+#define IB_IIR_COMPMASK_VENDID		(CL_HTON64(((uint64_t)1)<<15))
+
+/****f* IBA Base: Types/ib_path_rec_init_local
+* NAME
+*	ib_path_rec_init_local
+*
+* DESCRIPTION
+*	Initializes a subnet local path record.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_path_rec_init_local(IN ib_path_rec_t * const p_rec,
+		       IN ib_gid_t * const p_dgid,
+		       IN ib_gid_t * const p_sgid,
+		       IN ib_net16_t dlid,
+		       IN ib_net16_t slid,
+		       IN uint8_t num_path,
+		       IN ib_net16_t pkey,
+		       IN uint8_t sl,
+		       IN uint16_t qos_class,
+		       IN uint8_t mtu_selector,
+		       IN uint8_t mtu,
+		       IN uint8_t rate_selector,
+		       IN uint8_t rate,
+		       IN uint8_t pkt_life_selector,
+		       IN uint8_t pkt_life, IN uint8_t preference)
+{
+	p_rec->dgid = *p_dgid;
+	p_rec->sgid = *p_sgid;
+	p_rec->dlid = dlid;
+	p_rec->slid = slid;
+	p_rec->num_path = num_path;
+	p_rec->pkey = pkey;
+	p_rec->qos_class_sl = cl_hton16((sl & IB_PATH_REC_SL_MASK) |
+					(qos_class << 4));
+	p_rec->mtu = (uint8_t) ((mtu & IB_PATH_REC_BASE_MASK) |
+				(uint8_t) (mtu_selector << 6));
+	p_rec->rate = (uint8_t) ((rate & IB_PATH_REC_BASE_MASK) |
+				 (uint8_t) (rate_selector << 6));
+	p_rec->pkt_life = (uint8_t) ((pkt_life & IB_PATH_REC_BASE_MASK) |
+				     (uint8_t) (pkt_life_selector << 6));
+	p_rec->preference = preference;
+
+	/* Clear global routing fields for local path records */
+	p_rec->hop_flow_raw = 0;
+	p_rec->tclass = 0;
+	p_rec->service_id = 0;
+
+	*((uint32_t *) p_rec->resv2) = 0;
+	*((uint16_t *) p_rec->resv2 + 2) = 0;
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+*	dgid
+*		[in] GID of destination port.
+*
+*	sgid
+*		[in] GID of source port.
+*
+*	dlid
+*		[in] LID of destination port.
+*
+*	slid
+*		[in] LID of source port.
+*
+*	num_path
+*     [in] Reversible path - 1 bit to say if path is reversible.
+*		num_path [6:0] In queries, maximum number of paths to return.
+*		In responses, undefined.
+*
+*	pkey
+*		[in] Partition key (P_Key) to use on this path.
+*
+*	qos_class
+*		[in] QoS class to use on this path.  Lower 12-bits are valid.
+*
+*	sl
+*		[in] Service level to use on this path.  Lower 4-bits are valid.
+*
+*	mtu_selector
+*		[in] Encoded MTU selector value to use on this path
+*
+*	mtu
+*		[in] Encoded MTU to use on this path
+*
+*	rate_selector
+*		[in] Encoded rate selector value to use on this path.
+*
+*	rate
+*		[in] Encoded rate to use on this path.
+*
+*	pkt_life_selector
+*		[in] Encoded Packet selector value lifetime for this path.
+*
+*	pkt_life
+*		[in] Encoded Packet lifetime for this path.
+*
+*	preference
+*		[in] Indicates the relative merit of this path versus other path
+*		records returned from the SA.  Lower numbers are better.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_num_path
+* NAME
+*	ib_path_rec_num_path
+*
+* DESCRIPTION
+*	Get max number of paths to return.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_num_path(IN const ib_path_rec_t * const p_rec)
+{
+	return (p_rec->num_path & 0x7F);
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Maximum number of paths to return for each unique SGID_DGID combination.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_set_sl
+* NAME
+*	ib_path_rec_set_sl
+*
+* DESCRIPTION
+*	Set path service level.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_path_rec_set_sl(IN ib_path_rec_t * const p_rec, IN const uint8_t sl)
+{
+	p_rec->qos_class_sl =
+	    (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_QOS_CLASS_MASK)) |
+	    cl_hton16(sl & IB_PATH_REC_SL_MASK);
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+*	sl
+*		[in] Service level to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_sl
+* NAME
+*	ib_path_rec_sl
+*
+* DESCRIPTION
+*	Get path service level.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_sl(IN const ib_path_rec_t * const p_rec)
+{
+	return (uint8_t)(cl_ntoh16(p_rec->qos_class_sl) & IB_PATH_REC_SL_MASK);
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	SL.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_set_qos_class
+* NAME
+*	ib_path_rec_set_qos_class
+*
+* DESCRIPTION
+*	Set path QoS class.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_path_rec_set_qos_class(IN ib_path_rec_t * const p_rec,
+			  IN const uint16_t qos_class)
+{
+	p_rec->qos_class_sl =
+	    (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) |
+	    cl_hton16(qos_class << 4);
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+*	qos_class
+*		[in] QoS class to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_qos_class
+* NAME
+*	ib_path_rec_qos_class
+*
+* DESCRIPTION
+*	Get QoS class.
+*
+* SYNOPSIS
+*/
+static inline uint16_t OSM_API
+ib_path_rec_qos_class(IN const ib_path_rec_t * const p_rec)
+{
+	return (cl_ntoh16(p_rec->qos_class_sl) >> 4);
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	QoS class of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu
+* NAME
+*	ib_path_rec_mtu
+*
+* DESCRIPTION
+*	Get encoded path MTU.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_mtu(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->mtu & IB_PATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path MTU.
+*		1: 256
+*		2: 512
+*		3: 1024
+*		4: 2048
+*		5: 4096
+*		others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu_sel
+* NAME
+*	ib_path_rec_mtu_sel
+*
+* DESCRIPTION
+*	Get encoded path MTU selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_mtu_sel(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) ((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path MTU selector value (for queries).
+*		0: greater than MTU specified
+*		1: less than MTU specified
+*		2: exactly the MTU specified
+*		3: largest MTU available
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate
+* NAME
+*	ib_path_rec_rate
+*
+* DESCRIPTION
+*	Get encoded path rate.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_rate(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->rate & IB_PATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path rate.
+*		2: 2.5 Gb/sec.
+*		3: 10 Gb/sec.
+*		4: 30 Gb/sec.
+*		5: 5 Gb/sec.
+*		6: 20 Gb/sec.
+*		7: 40 Gb/sec.
+*		8: 60 Gb/sec.
+*		9: 80 Gb/sec.
+*		10: 120 Gb/sec.
+*		others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate_sel
+* NAME
+*	ib_path_rec_rate_sel
+*
+* DESCRIPTION
+*	Get encoded path rate selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_rate_sel(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) ((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path rate selector value (for queries).
+*		0: greater than rate specified
+*		1: less than rate specified
+*		2: exactly the rate specified
+*		3: largest rate available
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life
+* NAME
+*	ib_path_rec_pkt_life
+*
+* DESCRIPTION
+*	Get encoded path pkt_life.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_pkt_life(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->pkt_life & IB_PATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path pkt_life = 4.096 usec * 2 ** PacketLifeTime.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life_sel
+* NAME
+*	ib_path_rec_pkt_life_sel
+*
+* DESCRIPTION
+*	Get encoded path pkt_lifetime selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_pkt_life_sel(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) ((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Encoded path pkt_lifetime selector value (for queries).
+*		0: greater than rate specified
+*		1: less than rate specified
+*		2: exactly the rate specified
+*		3: smallest packet lifetime available
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_flow_lbl
+* NAME
+*	ib_path_rec_flow_lbl
+*
+* DESCRIPTION
+*	Get flow label.
+*
+* SYNOPSIS
+*/
+static inline uint32_t OSM_API
+ib_path_rec_flow_lbl(IN const ib_path_rec_t * const p_rec)
+{
+	return (((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Flow label of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_hop_limit
+* NAME
+*	ib_path_rec_hop_limit
+*
+* DESCRIPTION
+*	Get hop limit.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_rec_hop_limit(IN const ib_path_rec_t * const p_rec)
+{
+	return ((uint8_t) (cl_ntoh32(p_rec->hop_flow_raw) & 0x000000FF));
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the path record object.
+*
+* RETURN VALUES
+*	Hop limit of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_path_rec_t
+*********/
+
+/****s* IBA Base: Constants/IB_CLASS_CAP_TRAP
+* NAME
+*	IB_CLASS_CAP_TRAP
+*
+* DESCRIPTION
+*	ClassPortInfo CapabilityMask bits.  This bit will be set
+*	if the class supports Trap() MADs (13.4.8.1).
+*
+* SEE ALSO
+*	ib_class_port_info_t, IB_CLASS_CAP_GETSET
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_TRAP					0x0001
+/*********/
+
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET
+* NAME
+*	IB_CLASS_CAP_GETSET
+*
+* DESCRIPTION
+*	ClassPortInfo CapabilityMask bits.  This bit will be set
+*	if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1).
+*
+* SEE ALSO
+*	ib_class_port_info_t, IB_CLASS_CAP_TRAP
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_GETSET					0x0002
+/*********/
+
+/****s* IBA Base: Constants/IB_CLASS_RESP_TIME_MASK
+* NAME
+*	IB_CLASS_RESP_TIME_MASK
+*
+* DESCRIPTION
+*	Mask bits to extract the reponse time value from the
+*	resp_time_val field of ib_class_port_info_t.
+*
+* SEE ALSO
+*	ib_class_port_info_t
+*
+* SOURCE
+*/
+#define IB_CLASS_RESP_TIME_MASK				0x1F
+/*********/
+
+/****s* IBA Base: Types/ib_class_port_info_t
+* NAME
+*	ib_class_port_info_t
+*
+* DESCRIPTION
+*	IBA defined ClassPortInfo attribute (13.4.8.1)
+*	route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_class_port_info {
+	uint8_t base_ver;
+	uint8_t class_ver;
+	ib_net16_t cap_mask;
+	ib_net32_t cap_mask2_resp_time;
+	ib_gid_t redir_gid;
+	ib_net32_t redir_tc_sl_fl;
+	ib_net16_t redir_lid;
+	ib_net16_t redir_pkey;
+	ib_net32_t redir_qp;
+	ib_net32_t redir_qkey;
+	ib_gid_t trap_gid;
+	ib_net32_t trap_tc_sl_fl;
+	ib_net16_t trap_lid;
+	ib_net16_t trap_pkey;
+	ib_net32_t trap_hop_qp;
+	ib_net32_t trap_qkey;
+
+} PACK_SUFFIX ib_class_port_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	base_ver
+*		Maximum supported MAD Base Version.
+*
+*	class_ver
+*		Maximum supported management class version.
+*
+*	cap_mask
+*		Supported capabilities of this management class.
+*
+*	cap_mask2_resp_time
+*		Maximum expected response time and additional
+*		supported capabilities of this management class.
+*
+*	redr_gid
+*		GID to use for redirection, or zero
+*
+*	recdir_tc_sl_fl
+*		Traffic class, service level and flow label the requester
+*		should use if the service is redirected.
+*
+*	redir_lid
+*		LID used for redirection, or zero
+*
+*	redir_pkey
+*		P_Key used for redirection
+*
+*	redir_qp
+*		QP number used for redirection
+*
+*	redir_qkey
+*		Q_Key associated with the redirected QP.  This shall be the
+*		well known Q_Key value.
+*
+*	trap_gid
+*		GID value used for trap messages from this service.
+*
+*	trap_tc_sl_fl
+*		Traffic class, service level and flow label used for
+*		trap messages originated by this service.
+*
+*	trap_lid
+*		LID used for trap messages, or zero
+*
+*	trap_pkey
+*		P_Key used for trap messages
+*
+*	trap_hop_qp
+*		Hop limit (upper 8 bits) and QP number used for trap messages
+*
+*	trap_qkey
+*		Q_Key associated with the trap messages QP.
+*
+* SEE ALSO
+*	IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP
+*
+*********/
+
+/****f* IBA Base: Types/ib_class_set_resp_time_val
+* NAME
+*	ib_class_set_resp_time_val
+*
+* DESCRIPTION
+*	Set maximum expected response time.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_class_set_resp_time_val(IN ib_class_port_info_t * const p_cpi,
+			   IN const uint8_t val)
+{
+	p_cpi->cap_mask2_resp_time =
+	    (p_cpi->cap_mask2_resp_time & CL_HTON32(~IB_CLASS_RESP_TIME_MASK)) |
+	    cl_hton32(val & IB_CLASS_RESP_TIME_MASK);
+}
+
+/*
+* PARAMETERS
+*	p_cpi
+*		[in] Pointer to the class port info object.
+*
+*	val
+*		[in] Response time value to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_class_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_class_resp_time_val
+* NAME
+*	ib_class_resp_time_val
+*
+* DESCRIPTION
+*	Get response time value.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_class_resp_time_val(IN ib_class_port_info_t * const p_cpi)
+{
+	return (uint8_t)(cl_ntoh32(p_cpi->cap_mask2_resp_time) &
+			 IB_CLASS_RESP_TIME_MASK);
+}
+
+/*
+* PARAMETERS
+*	p_cpi
+*		[in] Pointer to the class port info object.
+*
+* RETURN VALUES
+*	Response time value.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_class_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_class_set_cap_mask2
+* NAME
+*	ib_class_set_cap_mask2
+*
+* DESCRIPTION
+*	Set ClassPortInfo:CapabilityMask2.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_class_set_cap_mask2(IN ib_class_port_info_t * const p_cpi,
+		       IN const uint32_t cap_mask2)
+{
+	p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time &
+		CL_HTON32(IB_CLASS_RESP_TIME_MASK)) |
+		cl_hton32(cap_mask2 << 5);
+}
+
+/*
+* PARAMETERS
+*	p_cpi
+*		[in] Pointer to the class port info object.
+*
+*	cap_mask2
+*		[in] CapabilityMask2 value to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_class_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_class_cap_mask2
+* NAME
+*	ib_class_cap_mask2
+*
+* DESCRIPTION
+*	Get ClassPortInfo:CapabilityMask2.
+*
+* SYNOPSIS
+*/
+static inline uint32_t OSM_API
+ib_class_cap_mask2(IN const ib_class_port_info_t * const p_cpi)
+{
+	return (cl_ntoh32(p_cpi->cap_mask2_resp_time) >> 5);
+}
+
+/*
+* PARAMETERS
+*	p_cpi
+*		[in] Pointer to the class port info object.
+*
+* RETURN VALUES
+*	CapabilityMask2 of the ClassPortInfo.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_class_port_info_t
+*********/
+
+/****s* IBA Base: Types/ib_sm_info_t
+* NAME
+*	ib_sm_info_t
+*
+* DESCRIPTION
+*	SMInfo structure (14.2.5.13).
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_sm_info {
+	ib_net64_t guid;
+	ib_net64_t sm_key;
+	ib_net32_t act_count;
+	uint8_t pri_state;
+
+} PACK_SUFFIX ib_sm_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	guid
+*		Port GUID for this SM.
+*
+*	sm_key
+*		SM_Key of this SM.
+*
+*	act_count
+*		Activity counter used as a heartbeat.
+*
+*	pri_state
+*		Priority and State information
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_priority
+* NAME
+*	ib_sminfo_get_priority
+*
+* DESCRIPTION
+*	Returns the priority value.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_sminfo_get_priority(IN const ib_sm_info_t * const p_smi)
+{
+	return ((uint8_t) ((p_smi->pri_state & 0xF0) >> 4));
+}
+
+/*
+* PARAMETERS
+*	p_smi
+*		[in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+*	Returns the priority value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_state
+* NAME
+*	ib_sminfo_get_state
+*
+* DESCRIPTION
+*	Returns the state value.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_sminfo_get_state(IN const ib_sm_info_t * const p_smi)
+{
+	return ((uint8_t) (p_smi->pri_state & 0x0F));
+}
+
+/*
+* PARAMETERS
+*	p_smi
+*		[in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+*	Returns the state value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_mad_t
+* NAME
+*	ib_mad_t
+*
+* DESCRIPTION
+*	IBA defined MAD header (13.4.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_mad {
+	uint8_t base_ver;
+	uint8_t mgmt_class;
+	uint8_t class_ver;
+	uint8_t method;
+	ib_net16_t status;
+	ib_net16_t class_spec;
+	ib_net64_t trans_id;
+	ib_net16_t attr_id;
+	ib_net16_t resv;
+	ib_net32_t attr_mod;
+} PACK_SUFFIX ib_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	base_ver
+*		MAD base format.
+*
+*	mgmt_class
+*		Class of operation.
+*
+*	class_ver
+*		Version of MAD class-specific format.
+*
+*	method
+*		Method to perform, including 'R' bit.
+*
+*	status
+*		Status of operation.
+*
+*	class_spec
+*		Reserved for subnet management.
+*
+*	trans_id
+*		Transaction ID.
+*
+*	attr_id
+*		Attribute ID.
+*
+*	resv
+*		Reserved field.
+*
+*	attr_mod
+*		Attribute modifier.
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_rmpp_mad_t
+* NAME
+*	ib_rmpp_mad_t
+*
+* DESCRIPTION
+*	IBA defined MAD RMPP header (13.6.2.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_rmpp_mad {
+	ib_mad_t common_hdr;
+
+	uint8_t rmpp_version;
+	uint8_t rmpp_type;
+	uint8_t rmpp_flags;
+	uint8_t rmpp_status;
+
+	ib_net32_t seg_num;
+	ib_net32_t paylen_newwin;
+
+} PACK_SUFFIX ib_rmpp_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_init_new
+* NAME
+*	ib_mad_init_new
+*
+* DESCRIPTION
+*	Initializes a MAD common header.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_mad_init_new(IN ib_mad_t * const p_mad,
+		IN const uint8_t mgmt_class,
+		IN const uint8_t class_ver,
+		IN const uint8_t method,
+		IN const ib_net64_t trans_id,
+		IN const ib_net16_t attr_id, IN const ib_net32_t attr_mod)
+{
+	CL_ASSERT(p_mad);
+	p_mad->base_ver = 1;
+	p_mad->mgmt_class = mgmt_class;
+	p_mad->class_ver = class_ver;
+	p_mad->method = method;
+	p_mad->status = 0;
+	p_mad->class_spec = 0;
+	p_mad->trans_id = trans_id;
+	p_mad->attr_id = attr_id;
+	p_mad->resv = 0;
+	p_mad->attr_mod = attr_mod;
+}
+
+/*
+* PARAMETERS
+*	p_mad
+*		[in] Pointer to the MAD common header.
+*
+*	mgmt_class
+*		[in] Class of operation.
+*
+*	class_ver
+*		[in] Version of MAD class-specific format.
+*
+*	method
+*		[in] Method to perform, including 'R' bit.
+*
+*	trans_Id
+*		[in] Transaction ID.
+*
+*	attr_id
+*		[in] Attribute ID.
+*
+*	attr_mod
+*		[in] Attribute modifier.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_init_response
+* NAME
+*	ib_mad_init_response
+*
+* DESCRIPTION
+*	Initializes a MAD common header as a response.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_mad_init_response(IN const ib_mad_t * const p_req_mad,
+		     IN ib_mad_t * const p_mad, IN const ib_net16_t status)
+{
+	CL_ASSERT(p_req_mad);
+	CL_ASSERT(p_mad);
+	*p_mad = *p_req_mad;
+	p_mad->status = status;
+	if (p_mad->method == IB_MAD_METHOD_SET)
+		p_mad->method = IB_MAD_METHOD_GET;
+	p_mad->method |= IB_MAD_METHOD_RESP_MASK;
+}
+
+/*
+* PARAMETERS
+*	p_req_mad
+*		[in] Pointer to the MAD common header in the original request MAD.
+*
+*	p_mad
+*		[in] Pointer to the MAD common header to initialize.
+*
+*	status
+*		[in] MAD Status value to return;
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*	p_req_mad and p_mad may point to the same MAD.
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_is_response
+* NAME
+*	ib_mad_is_response
+*
+* DESCRIPTION
+*	Returns TRUE if the MAD is a response ('R' bit set),
+*	FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_mad_is_response(IN const ib_mad_t * const p_mad)
+{
+	CL_ASSERT(p_mad);
+	return ((p_mad->method & IB_MAD_METHOD_RESP_MASK) ==
+		IB_MAD_METHOD_RESP_MASK);
+}
+
+/*
+* PARAMETERS
+*	p_mad
+*		[in] Pointer to the MAD.
+*
+* RETURN VALUES
+*	Returns TRUE if the MAD is a response ('R' bit set),
+*	FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+#define IB_RMPP_TYPE_DATA		1
+#define IB_RMPP_TYPE_ACK		2
+#define IB_RMPP_TYPE_STOP		3
+#define IB_RMPP_TYPE_ABORT		4
+
+#define IB_RMPP_NO_RESP_TIME		0x1F
+#define IB_RMPP_FLAG_ACTIVE		0x01
+#define IB_RMPP_FLAG_FIRST		0x02
+#define IB_RMPP_FLAG_LAST		0x04
+
+#define IB_RMPP_STATUS_SUCCESS		0
+#define IB_RMPP_STATUS_RESX		1	/* resources exhausted */
+#define IB_RMPP_STATUS_T2L		118	/* time too long */
+#define IB_RMPP_STATUS_BAD_LEN		119	/* incon. last and payload len */
+#define IB_RMPP_STATUS_BAD_SEG		120	/* incon. first and segment no */
+#define IB_RMPP_STATUS_BADT		121	/* bad rmpp type */
+#define IB_RMPP_STATUS_W2S		122	/* newwindowlast too small */
+#define IB_RMPP_STATUS_S2B		123	/* segment no too big */
+#define IB_RMPP_STATUS_BAD_STATUS	124	/* illegal status */
+#define IB_RMPP_STATUS_UNV		125	/* unsupported version */
+#define IB_RMPP_STATUS_TMR		126	/* too many retries */
+#define IB_RMPP_STATUS_UNSPEC		127	/* unspecified */
+
+/****f* IBA Base: Types/ib_rmpp_is_flag_set
+* NAME
+*	ib_rmpp_is_flag_set
+*
+* DESCRIPTION
+*	Returns TRUE if the MAD has the given RMPP flag set.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_rmpp_is_flag_set(IN const ib_rmpp_mad_t * const p_rmpp_mad,
+		    IN const uint8_t flag)
+{
+	CL_ASSERT(p_rmpp_mad);
+	return ((p_rmpp_mad->rmpp_flags & flag) == flag);
+}
+
+/*
+* PARAMETERS
+*	ib_rmpp_mad_t
+*		[in] Pointer to a MAD with an RMPP header.
+*
+*	flag
+*		[in] The RMPP flag being examined.
+*
+* RETURN VALUES
+*	Returns TRUE if the MAD has the given RMPP flag set.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_mad_t, ib_rmpp_mad_t
+*********/
+
+static inline void OSM_API
+ib_rmpp_set_resp_time(IN ib_rmpp_mad_t * const p_rmpp_mad,
+		      IN const uint8_t resp_time)
+{
+	CL_ASSERT(p_rmpp_mad);
+	p_rmpp_mad->rmpp_flags |= (resp_time << 3);
+}
+
+static inline uint8_t OSM_API
+ib_rmpp_get_resp_time(IN const ib_rmpp_mad_t * const p_rmpp_mad)
+{
+	CL_ASSERT(p_rmpp_mad);
+	return ((uint8_t) (p_rmpp_mad->rmpp_flags >> 3));
+}
+
+/****d* IBA Base: Constants/IB_SMP_DIRECTION
+* NAME
+*	IB_SMP_DIRECTION
+*
+* DESCRIPTION
+*	The Direction bit for directed route SMPs.
+*
+* SOURCE
+*/
+#define IB_SMP_DIRECTION_HO		0x8000
+#define IB_SMP_DIRECTION		(CL_HTON16(IB_SMP_DIRECTION_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMP_STATUS_MASK
+* NAME
+*	IB_SMP_STATUS_MASK
+*
+* DESCRIPTION
+*	Mask value for extracting status from a directed route SMP.
+*
+* SOURCE
+*/
+#define IB_SMP_STATUS_MASK_HO		0x7FFF
+#define IB_SMP_STATUS_MASK		(CL_HTON16(IB_SMP_STATUS_MASK_HO))
+/**********/
+
+/****s* IBA Base: Types/ib_smp_t
+* NAME
+*	ib_smp_t
+*
+* DESCRIPTION
+*	IBA defined SMP. (14.2.1.2)
+*
+* SYNOPSIS
+*/
+#define IB_SMP_DATA_SIZE 64
+#include <complib/cl_packon.h>
+typedef struct _ib_smp {
+	uint8_t base_ver;
+	uint8_t mgmt_class;
+	uint8_t class_ver;
+	uint8_t method;
+	ib_net16_t status;
+	uint8_t hop_ptr;
+	uint8_t hop_count;
+	ib_net64_t trans_id;
+	ib_net16_t attr_id;
+	ib_net16_t resv;
+	ib_net32_t attr_mod;
+	ib_net64_t m_key;
+	ib_net16_t dr_slid;
+	ib_net16_t dr_dlid;
+	uint32_t resv1[7];
+	uint8_t data[IB_SMP_DATA_SIZE];
+	uint8_t initial_path[IB_SUBNET_PATH_HOPS_MAX];
+	uint8_t return_path[IB_SUBNET_PATH_HOPS_MAX];
+
+} PACK_SUFFIX ib_smp_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	base_ver
+*		MAD base format.
+*
+*	mgmt_class
+*		Class of operation.
+*
+*	class_ver
+*		Version of MAD class-specific format.
+*
+*	method
+*		Method to perform, including 'R' bit.
+*
+*	status
+*		Status of operation.
+*
+*	hop_ptr
+*		Hop pointer for directed route MADs.
+*
+*	hop_count
+*		Hop count for directed route MADs.
+*
+*	trans_Id
+*		Transaction ID.
+*
+*	attr_id
+*		Attribute ID.
+*
+*	resv
+*		Reserved field.
+*
+*	attr_mod
+*		Attribute modifier.
+*
+*	m_key
+*		Management key value.
+*
+*	dr_slid
+*		Directed route source LID.
+*
+*	dr_dlid
+*		Directed route destination LID.
+*
+*	resv0
+*		Reserved for 64 byte alignment.
+*
+*	data
+*		MAD data payload.
+*
+*	initial_path
+*		Outbound port list.
+*
+*	return_path
+*		Inbound port list.
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_smp_get_status
+* NAME
+*	ib_smp_get_status
+*
+* DESCRIPTION
+*	Returns the SMP status value in network order.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t OSM_API
+ib_smp_get_status(IN const ib_smp_t * const p_smp)
+{
+	return ((ib_net16_t) (p_smp->status & IB_SMP_STATUS_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_smp
+*		[in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*	Returns the SMP status value in network order.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_is_response
+* NAME
+*	ib_smp_is_response
+*
+* DESCRIPTION
+*	Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_smp_is_response(IN const ib_smp_t * const p_smp)
+{
+	return (ib_mad_is_response((const ib_mad_t *)p_smp));
+}
+
+/*
+* PARAMETERS
+*	p_smp
+*		[in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*	Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_is_d
+* NAME
+*	ib_smp_is_d
+*
+* DESCRIPTION
+*	Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API ib_smp_is_d(IN const ib_smp_t * const p_smp)
+{
+	return ((p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION);
+}
+
+/*
+* PARAMETERS
+*	p_smp
+*		[in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*	Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_init_new
+* NAME
+*	ib_smp_init_new
+*
+* DESCRIPTION
+*	Initializes a MAD common header.
+*
+* TODO
+*	This is too big for inlining, but leave it here for now
+*	since there is not yet another convient spot.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_smp_init_new(IN ib_smp_t * const p_smp,
+		IN const uint8_t method,
+		IN const ib_net64_t trans_id,
+		IN const ib_net16_t attr_id,
+		IN const ib_net32_t attr_mod,
+		IN const uint8_t hop_count,
+		IN const ib_net64_t m_key,
+		IN const uint8_t * path_out,
+		IN const ib_net16_t dr_slid, IN const ib_net16_t dr_dlid)
+{
+	CL_ASSERT(p_smp);
+	CL_ASSERT(hop_count < IB_SUBNET_PATH_HOPS_MAX);
+	p_smp->base_ver = 1;
+	p_smp->mgmt_class = IB_MCLASS_SUBN_DIR;
+	p_smp->class_ver = 1;
+	p_smp->method = method;
+	p_smp->status = 0;
+	p_smp->hop_ptr = 0;
+	p_smp->hop_count = hop_count;
+	p_smp->trans_id = trans_id;
+	p_smp->attr_id = attr_id;
+	p_smp->resv = 0;
+	p_smp->attr_mod = attr_mod;
+	p_smp->m_key = m_key;
+	p_smp->dr_slid = dr_slid;
+	p_smp->dr_dlid = dr_dlid;
+
+	memset(p_smp->resv1, 0,
+	       sizeof(p_smp->resv1) +
+	       sizeof(p_smp->data) +
+	       sizeof(p_smp->initial_path) + sizeof(p_smp->return_path));
+
+	/* copy the path */
+	memcpy(&p_smp->initial_path, path_out, sizeof(p_smp->initial_path));
+}
+
+/*
+* PARAMETERS
+*	p_smp
+*		[in] Pointer to the SMP packet.
+*
+*	method
+*		[in] Method to perform, including 'R' bit.
+*
+*	trans_Id
+*		[in] Transaction ID.
+*
+*	attr_id
+*		[in] Attribute ID.
+*
+*	attr_mod
+*		[in] Attribute modifier.
+*
+*	hop_count
+*		[in] Number of hops in the path.
+*
+*	m_key
+*		[in] Management key for this SMP.
+*
+*	path_out
+*		[in] Port array for outbound path.
+*
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*	Payload area is initialized to zero.
+*
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_get_payload_ptr
+* NAME
+*	ib_smp_get_payload_ptr
+*
+* DESCRIPTION
+*	Gets a pointer to the SMP payload area.
+*
+* SYNOPSIS
+*/
+static inline void *OSM_API
+ib_smp_get_payload_ptr(IN const ib_smp_t * const p_smp)
+{
+	return ((void *)p_smp->data);
+}
+
+/*
+* PARAMETERS
+*	p_smp
+*		[in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*	Pointer to SMP payload area.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_node_info_t
+* NAME
+*	ib_node_info_t
+*
+* DESCRIPTION
+*	IBA defined NodeInfo. (14.2.5.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_node_info {
+	uint8_t base_version;
+	uint8_t class_version;
+	uint8_t node_type;
+	uint8_t num_ports;
+	ib_net64_t sys_guid;
+	ib_net64_t node_guid;
+	ib_net64_t port_guid;
+	ib_net16_t partition_cap;
+	ib_net16_t device_id;
+	ib_net32_t revision;
+	ib_net32_t port_num_vendor_id;
+
+} PACK_SUFFIX ib_node_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_sa_mad_t
+* NAME
+*	ib_sa_mad_t
+*
+* DESCRIPTION
+*	IBA defined SA MAD format. (15.2.1)
+*
+* SYNOPSIS
+*/
+#define IB_SA_DATA_SIZE 200
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sa_mad {
+	uint8_t base_ver;
+	uint8_t mgmt_class;
+	uint8_t class_ver;
+	uint8_t method;
+	ib_net16_t status;
+	ib_net16_t resv;
+	ib_net64_t trans_id;
+	ib_net16_t attr_id;
+	ib_net16_t resv1;
+	ib_net32_t attr_mod;
+
+	uint8_t rmpp_version;
+	uint8_t rmpp_type;
+	uint8_t rmpp_flags;
+	uint8_t rmpp_status;
+
+	ib_net32_t seg_num;
+	ib_net32_t paylen_newwin;
+
+	ib_net64_t sm_key;
+
+	ib_net16_t attr_offset;
+	ib_net16_t resv3;
+
+	ib_net64_t comp_mask;
+
+	uint8_t data[IB_SA_DATA_SIZE];
+} PACK_SUFFIX ib_sa_mad_t;
+#include <complib/cl_packoff.h>
+/**********/
+#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE)
+
+static inline uint32_t OSM_API ib_get_attr_size(IN const ib_net16_t attr_offset)
+{
+	return (((uint32_t) cl_ntoh16(attr_offset)) << 3);
+}
+
+static inline ib_net16_t OSM_API ib_get_attr_offset(IN const uint32_t attr_size)
+{
+	return (cl_hton16((uint16_t) (attr_size >> 3)));
+}
+
+/****f* IBA Base: Types/ib_sa_mad_get_payload_ptr
+* NAME
+*	ib_sa_mad_get_payload_ptr
+*
+* DESCRIPTION
+*	Gets a pointer to the SA MAD's payload area.
+*
+* SYNOPSIS
+*/
+static inline void *OSM_API
+ib_sa_mad_get_payload_ptr(IN const ib_sa_mad_t * const p_sa_mad)
+{
+	return ((void *)p_sa_mad->data);
+}
+
+/*
+* PARAMETERS
+*	p_sa_mad
+*		[in] Pointer to the SA MAD packet.
+*
+* RETURN VALUES
+*	Pointer to SA MAD payload area.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_mad_t
+*********/
+
+#define IB_NODE_INFO_PORT_NUM_MASK		(CL_HTON32(0xFF000000))
+#define IB_NODE_INFO_VEND_ID_MASK		(CL_HTON32(0x00FFFFFF))
+#if CPU_LE
+#define IB_NODE_INFO_PORT_NUM_SHIFT 0
+#else
+#define IB_NODE_INFO_PORT_NUM_SHIFT 24
+#endif
+
+/****f* IBA Base: Types/ib_node_info_get_local_port_num
+* NAME
+*	ib_node_info_get_local_port_num
+*
+* DESCRIPTION
+*	Gets a the local port number from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_node_info_get_local_port_num(IN const ib_node_info_t * const p_ni)
+{
+	return ((uint8_t) ((p_ni->port_num_vendor_id &
+			    IB_NODE_INFO_PORT_NUM_MASK)
+			   >> IB_NODE_INFO_PORT_NUM_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	p_ni
+*		[in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+*	Local port number that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_node_info_t
+*********/
+
+/****f* IBA Base: Types/ib_node_info_get_vendor_id
+* NAME
+*	ib_node_info_get_vendor_id
+*
+* DESCRIPTION
+*	Gets the VendorID from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_node_info_get_vendor_id(IN const ib_node_info_t * const p_ni)
+{
+	return ((ib_net32_t) (p_ni->port_num_vendor_id &
+			      IB_NODE_INFO_VEND_ID_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_ni
+*		[in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+*	VendorID that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_node_info_t
+*********/
+
+#define IB_NODE_DESCRIPTION_SIZE 64
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_desc {
+	// Node String is an array of UTF-8 character that
+	// describes the node in text format
+	// Note that this string is NOT NULL TERMINATED!
+	uint8_t description[IB_NODE_DESCRIPTION_SIZE];
+
+} PACK_SUFFIX ib_node_desc_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_record_t {
+	ib_net16_t lid;
+	ib_net16_t resv;
+	ib_node_info_t node_info;
+	ib_node_desc_t node_desc;
+	uint8_t pad[4];
+
+} PACK_SUFFIX ib_node_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_port_info_t
+* NAME
+*	ib_port_info_t
+*
+* DESCRIPTION
+*	IBA defined PortInfo. (14.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_info {
+	ib_net64_t m_key;
+	ib_net64_t subnet_prefix;
+	ib_net16_t base_lid;
+	ib_net16_t master_sm_base_lid;
+	ib_net32_t capability_mask;
+	ib_net16_t diag_code;
+	ib_net16_t m_key_lease_period;
+	uint8_t local_port_num;
+	uint8_t link_width_enabled;
+	uint8_t link_width_supported;
+	uint8_t link_width_active;
+	uint8_t state_info1;	/* LinkSpeedSupported and PortState */
+	uint8_t state_info2;	/* PortPhysState and LinkDownDefaultState */
+	uint8_t mkey_lmc;
+	uint8_t link_speed;	/* LinkSpeedEnabled and LinkSpeedActive */
+	uint8_t mtu_smsl;
+	uint8_t vl_cap;		/* VLCap and InitType */
+	uint8_t vl_high_limit;
+	uint8_t vl_arb_high_cap;
+	uint8_t vl_arb_low_cap;
+	uint8_t mtu_cap;
+	uint8_t vl_stall_life;
+	uint8_t vl_enforce;
+	ib_net16_t m_key_violations;
+	ib_net16_t p_key_violations;
+	ib_net16_t q_key_violations;
+	uint8_t guid_cap;
+	uint8_t subnet_timeout;	/* cli_rereg(1b), resrv(
+				   2b), timeout(5b) */
+	uint8_t resp_time_value;
+	uint8_t error_threshold;
+
+} PACK_SUFFIX ib_port_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_PORT_STATE_MASK			0x0F
+#define IB_PORT_LMC_MASK			0x07
+#define IB_PORT_LMC_MAX				0x07
+#define IB_PORT_MPB_MASK			0xC0
+#define IB_PORT_MPB_SHIFT			6
+#define IB_PORT_LINK_SPEED_SHIFT		4
+#define IB_PORT_LINK_SPEED_SUPPORTED_MASK	0xF0
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK		0xF0
+#define IB_PORT_LINK_SPEED_ENABLED_MASK		0x0F
+#define IB_PORT_PHYS_STATE_MASK			0xF0
+#define IB_PORT_PHYS_STATE_SHIFT		4
+#define IB_PORT_PHYS_STATE_NO_CHANGE		0
+#define IB_PORT_PHYS_STATE_SLEEP		1
+#define IB_PORT_PHYS_STATE_POLLING		2
+#define IB_PORT_PHYS_STATE_DISABLED		3
+#define IB_PORT_PHYS_STATE_PORTCONFTRAIN	4
+#define IB_PORT_PHYS_STATE_LINKUP	        5
+#define IB_PORT_PHYS_STATE_LINKERRRECOVER	6
+#define IB_PORT_PHYS_STATE_PHYTEST	        7
+#define IB_PORT_LNKDWNDFTSTATE_MASK		0x0F
+
+#define IB_PORT_CAP_RESV0         (CL_HTON32(0x00000001))
+#define IB_PORT_CAP_IS_SM         (CL_HTON32(0x00000002))
+#define IB_PORT_CAP_HAS_NOTICE    (CL_HTON32(0x00000004))
+#define IB_PORT_CAP_HAS_TRAP      (CL_HTON32(0x00000008))
+#define IB_PORT_CAP_HAS_IPD       (CL_HTON32(0x00000010))
+#define IB_PORT_CAP_HAS_AUTO_MIG  (CL_HTON32(0x00000020))
+#define IB_PORT_CAP_HAS_SL_MAP    (CL_HTON32(0x00000040))
+#define IB_PORT_CAP_HAS_NV_MKEY   (CL_HTON32(0x00000080))
+#define IB_PORT_CAP_HAS_NV_PKEY   (CL_HTON32(0x00000100))
+#define IB_PORT_CAP_HAS_LED_INFO  (CL_HTON32(0x00000200))
+#define IB_PORT_CAP_SM_DISAB      (CL_HTON32(0x00000400))
+#define IB_PORT_CAP_HAS_SYS_IMG_GUID  (CL_HTON32(0x00000800))
+#define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_HTON32(0x00001000))
+#define IB_PORT_CAP_RESV13        (CL_HTON32(0x00002000))
+#define IB_PORT_CAP_RESV14        (CL_HTON32(0x00004000))
+#define IB_PORT_CAP_RESV15        (CL_HTON32(0x00008000))
+#define IB_PORT_CAP_HAS_COM_MGT   (CL_HTON32(0x00010000))
+#define IB_PORT_CAP_HAS_SNMP      (CL_HTON32(0x00020000))
+#define IB_PORT_CAP_REINIT        (CL_HTON32(0x00040000))
+#define IB_PORT_CAP_HAS_DEV_MGT   (CL_HTON32(0x00080000))
+#define IB_PORT_CAP_HAS_VEND_CLS  (CL_HTON32(0x00100000))
+#define IB_PORT_CAP_HAS_DR_NTC    (CL_HTON32(0x00200000))
+#define IB_PORT_CAP_HAS_CAP_NTC   (CL_HTON32(0x00400000))
+#define IB_PORT_CAP_HAS_BM        (CL_HTON32(0x00800000))
+#define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_HTON32(0x01000000))
+#define IB_PORT_CAP_HAS_CLIENT_REREG (CL_HTON32(0x02000000))
+#define IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC (CL_HTON32(0x04000000))
+#define IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL (CL_HTON32(0x08000000))
+#define IB_PORT_CAP_RESV28        (CL_HTON32(0x10000000))
+#define IB_PORT_CAP_RESV29        (CL_HTON32(0x20000000))
+#define IB_PORT_CAP_RESV30        (CL_HTON32(0x40000000))
+#define IB_PORT_CAP_RESV31        (CL_HTON32(0x80000000))
+
+/****f* IBA Base: Types/ib_port_info_get_port_state
+* NAME
+*	ib_port_info_get_port_state
+*
+* DESCRIPTION
+*	Returns the port state.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_port_state(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->state_info1 & IB_PORT_STATE_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_port_state
+* NAME
+*	ib_port_info_set_port_state
+*
+* DESCRIPTION
+*	Sets the port state.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_port_state(IN ib_port_info_t * const p_pi,
+			    IN const uint8_t port_state)
+{
+	p_pi->state_info1 = (uint8_t) ((p_pi->state_info1 & 0xF0) | port_state);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	port_state
+*		[in] Port state value to set.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_vl_cap
+* NAME
+*	ib_port_info_get_vl_cap
+*
+* DESCRIPTION
+*	Gets the VL Capability of a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_vl_cap(IN const ib_port_info_t * const p_pi)
+{
+	return ((p_pi->vl_cap >> 4) & 0x0F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	VL_CAP field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_init_type
+* NAME
+*	ib_port_info_get_init_type
+*
+* DESCRIPTION
+*	Gets the init type of a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_init_type(IN const ib_port_info_t * const p_pi)
+{
+	return (uint8_t) (p_pi->vl_cap & 0x0F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	InitType field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_op_vls
+* NAME
+*	ib_port_info_get_op_vls
+*
+* DESCRIPTION
+*	Gets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_op_vls(IN const ib_port_info_t * const p_pi)
+{
+	return ((p_pi->vl_enforce >> 4) & 0x0F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	OP_VLS field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_op_vls
+* NAME
+*	ib_port_info_set_op_vls
+*
+* DESCRIPTION
+*	Sets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_op_vls(IN ib_port_info_t * const p_pi, IN const uint8_t op_vls)
+{
+	p_pi->vl_enforce =
+	    (uint8_t) ((p_pi->vl_enforce & 0x0F) | (op_vls << 4));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	op_vls
+*		[in] Encoded operation VLs value.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_state_no_change
+* NAME
+*	ib_port_info_set_state_no_change
+*
+* DESCRIPTION
+*	Sets the port state fields to the value for "no change".
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_state_no_change(IN ib_port_info_t * const p_pi)
+{
+	ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE);
+	p_pi->state_info2 = 0;
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_sup
+* NAME
+*	ib_port_info_get_link_speed_sup
+*
+* DESCRIPTION
+*	Returns the encoded value for the link speed supported.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_link_speed_sup(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) ((p_pi->state_info1 &
+			    IB_PORT_LINK_SPEED_SUPPORTED_MASK) >>
+			   IB_PORT_LINK_SPEED_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_speed_sup
+* NAME
+*	ib_port_info_set_link_speed_sup
+*
+* DESCRIPTION
+*	Given an integer of the supported link speed supported.
+*	Set the appropriate bits in state_info1
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_link_speed_sup(IN uint8_t const speed,
+				IN ib_port_info_t * p_pi)
+{
+	p_pi->state_info1 =
+	    (~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1) |
+	    (IB_PORT_LINK_SPEED_SUPPORTED_MASK &
+	     (speed << IB_PORT_LINK_SPEED_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	speed
+*		[in] Supported Speeds Code.
+*
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_port_phys_state
+* NAME
+*	ib_port_info_get_port_phys_state
+*
+* DESCRIPTION
+*	Returns the encoded value for the port physical state.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_port_phys_state(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) ((p_pi->state_info2 &
+			    IB_PORT_PHYS_STATE_MASK) >>
+			   IB_PORT_PHYS_STATE_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encoded value for the port physical state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_port_phys_state
+* NAME
+*	ib_port_info_set_port_phys_state
+*
+* DESCRIPTION
+*	Given an integer of the port physical state,
+*	Set the appropriate bits in state_info2
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_port_phys_state(IN uint8_t const phys_state,
+				 IN ib_port_info_t * p_pi)
+{
+	p_pi->state_info2 =
+	    (~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2) |
+	    (IB_PORT_PHYS_STATE_MASK &
+	     (phys_state << IB_PORT_PHYS_STATE_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	phys_state
+*		[in] port physical state.
+*
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_down_def_state
+* NAME
+*	ib_port_info_get_link_down_def_state
+*
+* DESCRIPTION
+*	Returns the link down default state.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_link_down_def_state(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	link down default state of the port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_down_def_state
+* NAME
+*	ib_port_info_set_link_down_def_state
+*
+* DESCRIPTION
+*	Sets the link down default state of the port.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_link_down_def_state(IN ib_port_info_t * const p_pi,
+				     IN const uint8_t link_dwn_state)
+{
+	p_pi->state_info2 =
+	    (uint8_t) ((p_pi->state_info2 & 0xF0) | link_dwn_state);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	link_dwn_state
+*		[in] Link down default state of the port.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active
+* NAME
+*	ib_port_info_get_link_speed_active
+*
+* DESCRIPTION
+*	Returns the Link Speed Active value assigned to this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_link_speed_active(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) ((p_pi->link_speed &
+			    IB_PORT_LINK_SPEED_ACTIVE_MASK) >>
+			   IB_PORT_LINK_SPEED_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the link speed active value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+#define IB_LINK_WIDTH_ACTIVE_1X			1
+#define IB_LINK_WIDTH_ACTIVE_4X			2
+#define IB_LINK_WIDTH_ACTIVE_8X			4
+#define IB_LINK_WIDTH_ACTIVE_12X 		8
+#define IB_LINK_SPEED_ACTIVE_2_5		1
+#define IB_LINK_SPEED_ACTIVE_5			2
+#define IB_LINK_SPEED_ACTIVE_10			4
+
+/* following v1 ver1.2 p901 */
+#define IB_PATH_RECORD_RATE_2_5_GBS		2
+#define IB_PATH_RECORD_RATE_10_GBS		3
+#define IB_PATH_RECORD_RATE_30_GBS		4
+#define IB_PATH_RECORD_RATE_5_GBS		5
+#define IB_PATH_RECORD_RATE_20_GBS		6
+#define IB_PATH_RECORD_RATE_40_GBS		7
+#define IB_PATH_RECORD_RATE_60_GBS		8
+#define IB_PATH_RECORD_RATE_80_GBS		9
+#define IB_PATH_RECORD_RATE_120_GBS		10
+
+#define IB_MIN_RATE    IB_PATH_RECORD_RATE_2_5_GBS
+#define IB_MAX_RATE    IB_PATH_RECORD_RATE_120_GBS
+
+/****f* IBA Base: Types/ib_port_info_compute_rate
+* NAME
+*	ib_port_info_compute_rate
+*
+* DESCRIPTION
+*	Returns the encoded value for the path rate.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_compute_rate(IN const ib_port_info_t * const p_pi)
+{
+	uint8_t rate = 0;
+
+	switch (ib_port_info_get_link_speed_active(p_pi)) {
+	case IB_LINK_SPEED_ACTIVE_2_5:
+		switch (p_pi->link_width_active) {
+		case IB_LINK_WIDTH_ACTIVE_1X:
+			rate = IB_PATH_RECORD_RATE_2_5_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_4X:
+			rate = IB_PATH_RECORD_RATE_10_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_8X:
+			rate = IB_PATH_RECORD_RATE_20_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_12X:
+			rate = IB_PATH_RECORD_RATE_30_GBS;
+			break;
+
+		default:
+			rate = IB_PATH_RECORD_RATE_2_5_GBS;
+			break;
+		}
+		break;
+	case IB_LINK_SPEED_ACTIVE_5:
+		switch (p_pi->link_width_active) {
+		case IB_LINK_WIDTH_ACTIVE_1X:
+			rate = IB_PATH_RECORD_RATE_5_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_4X:
+			rate = IB_PATH_RECORD_RATE_20_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_8X:
+			rate = IB_PATH_RECORD_RATE_40_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_12X:
+			rate = IB_PATH_RECORD_RATE_60_GBS;
+			break;
+
+		default:
+			rate = IB_PATH_RECORD_RATE_5_GBS;
+			break;
+		}
+		break;
+	case IB_LINK_SPEED_ACTIVE_10:
+		switch (p_pi->link_width_active) {
+		case IB_LINK_WIDTH_ACTIVE_1X:
+			rate = IB_PATH_RECORD_RATE_10_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_4X:
+			rate = IB_PATH_RECORD_RATE_40_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_8X:
+			rate = IB_PATH_RECORD_RATE_80_GBS;
+			break;
+
+		case IB_LINK_WIDTH_ACTIVE_12X:
+			rate = IB_PATH_RECORD_RATE_120_GBS;
+			break;
+
+		default:
+			rate = IB_PATH_RECORD_RATE_10_GBS;
+			break;
+		}
+		break;
+	default:
+		rate = IB_PATH_RECORD_RATE_2_5_GBS;
+		break;
+	}
+
+	return rate;
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_path_get_ipd
+* NAME
+*	ib_path_get_ipd
+*
+* DESCRIPTION
+*	Returns the encoded value for the inter packet delay.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_path_get_ipd(IN uint8_t local_link_width_supported, IN uint8_t path_rec_rate)
+{
+	uint8_t ipd = 0;
+
+	switch (local_link_width_supported) {
+		/* link_width_supported = 1: 1x */
+	case 1:
+		break;
+
+		/* link_width_supported = 3: 1x or 4x */
+	case 3:
+		switch (path_rec_rate & 0x3F) {
+		case IB_PATH_RECORD_RATE_2_5_GBS:
+			ipd = 3;
+			break;
+		default:
+			break;
+		}
+		break;
+
+		/* link_width_supported = 11: 1x or 4x or 12x */
+	case 11:
+		switch (path_rec_rate & 0x3F) {
+		case IB_PATH_RECORD_RATE_2_5_GBS:
+			ipd = 11;
+			break;
+		case IB_PATH_RECORD_RATE_10_GBS:
+			ipd = 2;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return ipd;
+}
+
+/*
+* PARAMETERS
+*	local_link_width_supported
+*		[in] link with supported for this port
+*
+*	path_rec_rate
+*		[in] rate field of the path record
+*
+* RETURN VALUES
+*	Returns the ipd
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_mtu_cap
+* NAME
+*	ib_port_info_get_mtu_cap
+*
+* DESCRIPTION
+*	Returns the encoded value for the maximum MTU supported by this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_mtu_cap(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->mtu_cap & 0x0F));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encooded value for the maximum MTU supported by this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_neighbor_mtu
+* NAME
+*	ib_port_info_get_neighbor_mtu
+*
+* DESCRIPTION
+*	Returns the encoded value for the neighbor MTU supported by this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_neighbor_mtu(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) ((p_pi->mtu_smsl & 0xF0) >> 4));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encoded value for the neighbor MTU at this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_neighbor_mtu
+* NAME
+*	ib_port_info_set_neighbor_mtu
+*
+* DESCRIPTION
+*	Sets the Neighbor MTU value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_neighbor_mtu(IN ib_port_info_t * const p_pi,
+			      IN const uint8_t mtu)
+{
+	CL_ASSERT(mtu <= 5);
+	CL_ASSERT(mtu != 0);
+	p_pi->mtu_smsl = (uint8_t) ((p_pi->mtu_smsl & 0x0F) | (mtu << 4));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	mtu
+*		[in] Encoded MTU value to set
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_master_smsl
+* NAME
+*	ib_port_info_get_master_smsl
+*
+* DESCRIPTION
+*	Returns the encoded value for the Master SMSL at this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_master_smsl(IN const ib_port_info_t * const p_pi)
+{
+	return (uint8_t) (p_pi->mtu_smsl & 0x0F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the encoded value for the Master SMSL at this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_master_smsl
+* NAME
+*	ib_port_info_set_master_smsl
+*
+* DESCRIPTION
+*	Sets the Master SMSL value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_master_smsl(IN ib_port_info_t * const p_pi,
+			     IN const uint8_t smsl)
+{
+	p_pi->mtu_smsl = (uint8_t) ((p_pi->mtu_smsl & 0xF0) | smsl);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	mtu
+*		[in] Encoded Master SMSL value to set
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_timeout
+* NAME
+*	ib_port_info_set_timeout
+*
+* DESCRIPTION
+*	Sets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_timeout(IN ib_port_info_t * const p_pi,
+			 IN const uint8_t timeout)
+{
+	CL_ASSERT(timeout <= 0x1F);
+	p_pi->subnet_timeout =
+	    (uint8_t) ((p_pi->subnet_timeout & 0x80) | (timeout & 0x1F));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	timeout
+*		[in] Encoded timeout value to set
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_client_rereg
+* NAME
+*	ib_port_info_set_client_rereg
+*
+* DESCRIPTION
+*	Sets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_client_rereg(IN ib_port_info_t * const p_pi,
+			      IN const uint8_t client_rereg)
+{
+	CL_ASSERT(client_rereg <= 0x1);
+	p_pi->subnet_timeout =
+	    (uint8_t) ((p_pi->
+			subnet_timeout & 0x1F) | ((client_rereg << 7) & 0x80));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	client_rereg
+*		[in] Client reregistration value to set (either 1 or 0).
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_timeout
+* NAME
+*	ib_port_info_get_timeout
+*
+* DESCRIPTION
+*	Gets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_timeout(IN ib_port_info_t const *p_pi)
+{
+	return (p_pi->subnet_timeout & 0x1F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	The encoded timeout value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_client_rereg
+* NAME
+*	ib_port_info_get_client_rereg
+*
+* DESCRIPTION
+*	Gets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_client_rereg(IN ib_port_info_t const *p_pi)
+{
+	return ((p_pi->subnet_timeout & 0x80) >> 7);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Client reregistration value (either 1 or 0).
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_hoq_lifetime
+* NAME
+*	ib_port_info_set_hoq_lifetime
+*
+* DESCRIPTION
+*	Sets the Head of Queue Lifetime for which a packet can live in the head
+*  of VL queue
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_hoq_lifetime(IN ib_port_info_t * const p_pi,
+			      IN const uint8_t hoq_life)
+{
+	p_pi->vl_stall_life = (uint8_t) ((hoq_life & 0x1f) |
+					 (p_pi->vl_stall_life & 0xe0));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	hoq_life
+*		[in] Encoded lifetime value to set
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_hoq_lifetime
+* NAME
+*	ib_port_info_get_hoq_lifetime
+*
+* DESCRIPTION
+*	Gets the Head of Queue Lifetime for which a packet can live in the head
+*  of VL queue
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_hoq_lifetime(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->vl_stall_life & 0x1f));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*     Encoded lifetime value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_vl_stall_count
+* NAME
+*	ib_port_info_set_vl_stall_count
+*
+* DESCRIPTION
+*	Sets the VL Stall Count which define the number of contiguous
+*  HLL (hoq) drops that will put the VL into stalled mode.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_vl_stall_count(IN ib_port_info_t * const p_pi,
+				IN const uint8_t vl_stall_count)
+{
+	p_pi->vl_stall_life = (uint8_t) ((p_pi->vl_stall_life & 0x1f) |
+					 ((vl_stall_count << 5) & 0xe0));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	vl_stall_count
+*		[in] value to set
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_vl_stall_count
+* NAME
+*	ib_port_info_get_vl_stall_count
+*
+* DESCRIPTION
+*	Gets the VL Stall Count which define the number of contiguous
+*  HLL (hoq) drops that will put the VL into stalled mode
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_vl_stall_count(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->vl_stall_life & 0xe0) >> 5);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*     vl stall count
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_lmc
+* NAME
+*	ib_port_info_get_lmc
+*
+* DESCRIPTION
+*	Returns the LMC value assigned to this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_lmc(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->mkey_lmc & IB_PORT_LMC_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_lmc
+* NAME
+*	ib_port_info_set_lmc
+*
+* DESCRIPTION
+*	Sets the LMC value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_lmc(IN ib_port_info_t * const p_pi, IN const uint8_t lmc)
+{
+	CL_ASSERT(lmc <= IB_PORT_LMC_MAX);
+	p_pi->mkey_lmc = (uint8_t) ((p_pi->mkey_lmc & 0xF8) | lmc);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	lmc
+*		[in] LMC value to set, must be less than 7.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_enabled
+* NAME
+*	ib_port_info_get_link_speed_enabled
+*
+* DESCRIPTION
+*	Returns the link speed enabled value assigned to this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_link_speed_enabled(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) (p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_speed_enabled
+* NAME
+*	ib_port_info_set_link_speed_enabled
+*
+* DESCRIPTION
+*	Sets the link speed enabled value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_link_speed_enabled(IN ib_port_info_t * const p_pi,
+				    IN const uint8_t link_speed_enabled)
+{
+	p_pi->link_speed =
+	    (uint8_t) ((p_pi->link_speed & 0xF0) | link_speed_enabled);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	link_speed_enabled
+*		[in] link speed enabled value to set.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_mpb
+* NAME
+*	ib_port_info_get_mpb
+*
+* DESCRIPTION
+*	Returns the M_Key protect bits assigned to this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_mpb(IN const ib_port_info_t * const p_pi)
+{
+	return ((uint8_t) ((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >>
+			   IB_PORT_MPB_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	p_ni
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the M_Key protect bits assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_mpb
+* NAME
+*	ib_port_info_set_mpb
+*
+* DESCRIPTION
+*	Set the M_Key protect bits of this port.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_mpb(IN ib_port_info_t * p_pi, IN uint8_t mpb)
+{
+	p_pi->mkey_lmc =
+	    (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) |
+	    (IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT));
+}
+
+/*
+* PARAMETERS
+*	mpb
+*		[in] M_Key protect bits
+*	p_ni
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_local_phy_err_thd
+* NAME
+*	ib_port_info_get_local_phy_err_thd
+*
+* DESCRIPTION
+*	Returns the Phy Link Threshold
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_local_phy_err_thd(IN const ib_port_info_t * const p_pi)
+{
+	return (uint8_t) ((p_pi->error_threshold & 0xF0) >> 4);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the Phy Link error threshold assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_overrun_err_thd
+* NAME
+*	ib_port_info_get_local_overrun_err_thd
+*
+* DESCRIPTION
+*	Returns the Credits Overrun Errors Threshold
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_port_info_get_overrun_err_thd(IN const ib_port_info_t * const p_pi)
+{
+	return (uint8_t) (p_pi->error_threshold & 0x0F);
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the Credits Overrun errors threshold assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd
+* NAME
+*	ib_port_info_set_phy_and_overrun_err_thd
+*
+* DESCRIPTION
+*	Sets the Phy Link and Credits Overrun Errors Threshold
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_port_info_set_phy_and_overrun_err_thd(IN ib_port_info_t * const p_pi,
+					 IN uint8_t phy_threshold,
+					 IN uint8_t overrun_threshold)
+{
+	p_pi->error_threshold =
+	    (uint8_t) (((phy_threshold & 0x0F) << 4) |
+		       (overrun_threshold & 0x0F));
+}
+
+/*
+* PARAMETERS
+*	p_pi
+*		[in] Pointer to a PortInfo attribute.
+*
+*	phy_threshold
+*		[in] Physical Link Errors Threshold above which Trap 129 is generated
+*
+*  overrun_threshold
+*     [in] Credits overrun Errors Threshold above which Trap 129 is generated
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+typedef uint8_t ib_svc_name_t[64];
+
+#include <complib/cl_packon.h>
+typedef struct _ib_service_record {
+	ib_net64_t service_id;
+	ib_gid_t service_gid;
+	ib_net16_t service_pkey;
+	ib_net16_t resv;
+	ib_net32_t service_lease;
+	uint8_t service_key[16];
+	ib_svc_name_t service_name;
+	uint8_t service_data8[16];
+	ib_net16_t service_data16[8];
+	ib_net32_t service_data32[4];
+	ib_net64_t service_data64[2];
+
+} PACK_SUFFIX ib_service_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_portinfo_record {
+	ib_net16_t lid;
+	uint8_t port_num;
+	uint8_t resv;
+	ib_port_info_t port_info;
+	uint8_t pad[6];
+
+} PACK_SUFFIX ib_portinfo_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_link_record {
+	ib_net16_t from_lid;
+	uint8_t from_port_num;
+	uint8_t to_port_num;
+	ib_net16_t to_lid;
+	uint8_t pad[2];
+
+} PACK_SUFFIX ib_link_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sminfo_record {
+	ib_net16_t lid;
+	uint16_t resv0;
+	ib_sm_info_t sm_info;
+	uint8_t pad[7];
+
+} PACK_SUFFIX ib_sminfo_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_lft_record_t
+* NAME
+*	ib_lft_record_t
+*
+* DESCRIPTION
+*	IBA defined LinearForwardingTableRecord (15.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_lft_record {
+	ib_net16_t lid;
+	ib_net16_t block_num;
+	uint32_t resv0;
+	uint8_t lft[64];
+} PACK_SUFFIX ib_lft_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_mft_record_t
+* NAME
+*	ib_mft_record_t
+*
+* DESCRIPTION
+*	IBA defined MulticastForwardingTableRecord (15.2.5.8)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_mft_record {
+	ib_net16_t lid;
+	ib_net16_t position_block_num;
+	uint32_t resv0;
+	ib_net16_t mft[IB_MCAST_BLOCK_SIZE];
+} PACK_SUFFIX ib_mft_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_switch_info_t
+* NAME
+*	ib_switch_info_t
+*
+* DESCRIPTION
+*	IBA defined SwitchInfo. (14.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info {
+	ib_net16_t lin_cap;
+	ib_net16_t rand_cap;
+	ib_net16_t mcast_cap;
+	ib_net16_t lin_top;
+	uint8_t def_port;
+	uint8_t def_mcast_pri_port;
+	uint8_t def_mcast_not_port;
+	uint8_t life_state;
+	ib_net16_t lids_per_port;
+	ib_net16_t enforce_cap;
+	uint8_t flags;
+
+} PACK_SUFFIX ib_switch_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info_record {
+	ib_net16_t lid;
+	uint16_t resv0;
+	ib_switch_info_t switch_info;
+	uint8_t pad[3];
+
+} PACK_SUFFIX ib_switch_info_record_t;
+#include <complib/cl_packoff.h>
+
+#define IB_SWITCH_PSC 0x04
+
+/****f* IBA Base: Types/ib_switch_info_get_state_change
+* NAME
+*	ib_switch_info_get_state_change
+*
+* DESCRIPTION
+*	Returns the value of the state change flag.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_switch_info_get_state_change(IN const ib_switch_info_t * const p_si)
+{
+	return ((p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC);
+}
+
+/*
+* PARAMETERS
+*	p_si
+*		[in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+*	Returns the value of the state change flag.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_switch_info_clear_state_change
+* NAME
+*	ib_switch_info_clear_state_change
+*
+* DESCRIPTION
+*	Clears the switch's state change bit.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_switch_info_clear_state_change(IN ib_switch_info_t * const p_si)
+{
+	p_si->life_state = (uint8_t) (p_si->life_state & 0xFB);
+}
+
+/*
+* PARAMETERS
+*	p_ni
+*		[in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*	Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_switch_info_is_enhanced_port0
+* NAME
+*	ib_switch_info_is_enhanced_port0
+*
+* DESCRIPTION
+*	Returns TRUE if the enhancedPort0 bit is on (meaning the switch
+*  port zero supports enhanced functions).
+*  Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_switch_info_is_enhanced_port0(IN const ib_switch_info_t * const p_si)
+{
+	return ((p_si->flags & 0x08) == 0x08);
+}
+
+/*
+* PARAMETERS
+*	p_si
+*		[in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+*	Returns TRUE if the switch supports enhanced port 0. FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_guid_info_t
+* NAME
+*	ib_guid_info_t
+*
+* DESCRIPTION
+*	IBA defined GuidInfo. (14.2.5.5)
+*
+* SYNOPSIS
+*/
+#define	GUID_TABLE_MAX_ENTRIES		8
+
+#include <complib/cl_packon.h>
+typedef struct _ib_guid_info {
+	ib_net64_t guid[GUID_TABLE_MAX_ENTRIES];
+
+} PACK_SUFFIX ib_guid_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_guidinfo_record {
+	ib_net16_t lid;
+	uint8_t block_num;
+	uint8_t resv;
+	uint32_t reserved;
+	ib_guid_info_t guid_info;
+} PACK_SUFFIX ib_guidinfo_record_t;
+#include <complib/cl_packoff.h>
+
+#define IB_MULTIPATH_MAX_GIDS 11	/* Support max that can fit into first MAD (for now) */
+
+#include <complib/cl_packon.h>
+typedef struct _ib_multipath_rec_t {
+	ib_net32_t hop_flow_raw;
+	uint8_t tclass;
+	uint8_t num_path;
+	ib_net16_t pkey;
+	ib_net16_t qos_class_sl;
+	uint8_t mtu;
+	uint8_t rate;
+	uint8_t pkt_life;
+	uint8_t service_id_8msb;
+	uint8_t independence;	/* formerly resv2 */
+	uint8_t sgid_count;
+	uint8_t dgid_count;
+	uint8_t service_id_56lsb[7];
+	ib_gid_t gids[IB_MULTIPATH_MAX_GIDS];
+} PACK_SUFFIX ib_multipath_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*       hop_flow_raw
+*               Global routing parameters: hop count, flow label and raw bit.
+*
+*       tclass
+*               Another global routing parameter.
+*
+*       num_path
+*     Reversible path - 1 bit to say if path is reversible.
+*               num_path [6:0] In queries, maximum number of paths to return.
+*               In responses, undefined.
+*
+*       pkey
+*               Partition key (P_Key) to use on this path.
+*
+*       qos_class_sl
+*               QoS class and service level to use on this path.
+*
+*       mtu
+*               MTU and MTU selector fields to use on this path
+*       rate
+*               Rate and rate selector fields to use on this path.
+*
+*       pkt_life
+*               Packet lifetime
+*
+*	service_id_8msb
+*		8 most significant bits of Service ID
+*
+*	service_id_56lsb
+*		56 least significant bits of Service ID
+*
+*       preference
+*               Indicates the relative merit of this path versus other path
+*               records returned from the SA.  Lower numbers are better.
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_num_path
+* NAME
+*       ib_multipath_rec_num_path
+*
+* DESCRIPTION
+*       Get max number of paths to return.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_num_path(IN const ib_multipath_rec_t * const p_rec)
+{
+	return (p_rec->num_path & 0x7F);
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Maximum number of paths to return for each unique SGID_DGID combination.
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_set_sl
+* NAME
+*	ib_multipath_rec_set_sl
+*
+* DESCRIPTION
+*	Set path service level.
+*
+* SYNOPSIS
+*/
+static inline void	OSM_API
+ib_multipath_rec_set_sl(
+	IN ib_multipath_rec_t* const p_rec,
+	IN const uint8_t sl )
+{
+	p_rec->qos_class_sl =
+		(p_rec->qos_class_sl & CL_HTON16(IB_MULTIPATH_REC_QOS_CLASS_MASK)) |
+			cl_hton16(sl & IB_MULTIPATH_REC_SL_MASK);
+}
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the MultiPath record object.
+*
+*	sl
+*		[in] Service level to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_sl
+* NAME
+*       ib_multipath_rec_sl
+*
+* DESCRIPTION
+*       Get multipath service level.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_sl(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t) ((cl_ntoh16(p_rec->qos_class_sl)) & IB_MULTIPATH_REC_SL_MASK));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*	SL.
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_set_qos_class
+* NAME
+*	ib_multipath_rec_set_qos_class
+*
+* DESCRIPTION
+*	Set path QoS class.
+*
+* SYNOPSIS
+*/
+static inline void	OSM_API
+ib_multipath_rec_set_qos_class(
+	IN ib_multipath_rec_t* const p_rec,
+	IN const uint16_t qos_class )
+{
+	p_rec->qos_class_sl =
+		(p_rec->qos_class_sl & CL_HTON16(IB_MULTIPATH_REC_SL_MASK)) |
+			cl_hton16(qos_class << 4);
+}
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the MultiPath record object.
+*
+*	qos_class
+*		[in] QoS class to set.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_qos_class
+* NAME
+*	ib_multipath_rec_qos_class
+*
+* DESCRIPTION
+*	Get QoS class.
+*
+* SYNOPSIS
+*/
+static inline uint16_t	OSM_API
+ib_multipath_rec_qos_class(
+	IN	const	ib_multipath_rec_t* const	p_rec )
+{
+	return (cl_ntoh16( p_rec->qos_class_sl ) >> 4);
+}
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the MultiPath record object.
+*
+* RETURN VALUES
+*	QoS class of the MultiPath record.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_mtu
+* NAME
+*       ib_multipath_rec_mtu
+*
+* DESCRIPTION
+*       Get encoded path MTU.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_mtu(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->mtu & IB_MULTIPATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded path MTU.
+*               1: 256
+*               2: 512
+*               3: 1024
+*               4: 2048
+*               5: 4096
+*               others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_mtu_sel
+* NAME
+*       ib_multipath_rec_mtu_sel
+*
+* DESCRIPTION
+*       Get encoded multipath MTU selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_mtu_sel(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t) ((p_rec->mtu & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded path MTU selector value (for queries).
+*               0: greater than MTU specified
+*               1: less than MTU specified
+*               2: exactly the MTU specified
+*               3: largest MTU available
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_rate
+* NAME
+*       ib_multipath_rec_rate
+*
+* DESCRIPTION
+*       Get encoded multipath rate.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_rate(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->rate & IB_MULTIPATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded multipath rate.
+*               2: 2.5 Gb/sec.
+*               3: 10 Gb/sec.
+*               4: 30 Gb/sec.
+*               others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_rate_sel
+* NAME
+*       ib_multipath_rec_rate_sel
+*
+* DESCRIPTION
+*       Get encoded multipath rate selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_rate_sel(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t)
+		((p_rec->rate & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded path rate selector value (for queries).
+*               0: greater than rate specified
+*               1: less than rate specified
+*               2: exactly the rate specified
+*               3: largest rate available
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life
+* NAME
+*       ib_multipath_rec_pkt_life
+*
+* DESCRIPTION
+*       Get encoded multipath pkt_life.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_pkt_life(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t) (p_rec->pkt_life & IB_MULTIPATH_REC_BASE_MASK));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded multipath pkt_life = 4.096 usec * 2 ** PacketLifeTime.
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life_sel
+* NAME
+*       ib_multipath_rec_pkt_life_sel
+*
+* DESCRIPTION
+*       Get encoded multipath pkt_lifetime selector.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_multipath_rec_pkt_life_sel(IN const ib_multipath_rec_t * const p_rec)
+{
+	return ((uint8_t)
+		((p_rec->pkt_life & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6));
+}
+
+/*
+* PARAMETERS
+*       p_rec
+*               [in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*       Encoded path pkt_lifetime selector value (for queries).
+*               0: greater than rate specified
+*               1: less than rate specified
+*               2: exactly the rate specified
+*               3: smallest packet lifetime available
+*
+* NOTES
+*
+* SEE ALSO
+*       ib_multipath_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_multipath_rec_service_id
+* NAME
+*	ib_multipath_rec_service_id
+*
+* DESCRIPTION
+*	Get multipath service id.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t OSM_API
+ib_multipath_rec_service_id(IN const ib_multipath_rec_t * const p_rec)
+{
+	union {
+		ib_net64_t sid;
+		uint8_t sid_arr[8];
+	} sid_union;
+	sid_union.sid_arr[0] = p_rec->service_id_8msb;
+	memcpy(&sid_union.sid_arr[1], p_rec->service_id_56lsb, 7);
+	return sid_union.sid;
+}
+
+/*
+* PARAMETERS
+*	p_rec
+*		[in] Pointer to the multipath record object.
+*
+* RETURN VALUES
+*	Service ID
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_multipath_rec_t
+*********/
+
+#define IB_NUM_PKEY_ELEMENTS_IN_BLOCK		32
+/****s* IBA Base: Types/ib_pkey_table_t
+* NAME
+*	ib_pkey_table_t
+*
+* DESCRIPTION
+*	IBA defined PKey table. (14.2.5.7)
+*
+* SYNOPSIS
+*/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table {
+	ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK];
+
+} PACK_SUFFIX ib_pkey_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_pkey_table_record_t
+* NAME
+*	ib_pkey_table_record_t
+*
+* DESCRIPTION
+*	IBA defined P_Key Table Record for SA Query. (15.2.5.11)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table_record {
+	ib_net16_t lid;		// for CA: lid of port, for switch lid of port 0
+	uint16_t block_num;
+	uint8_t port_num;	// for switch: port number, for CA: reserved
+	uint8_t reserved1;
+	uint16_t reserved2;
+	ib_pkey_table_t pkey_tbl;
+
+} PACK_SUFFIX ib_pkey_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_DROP_VL 15
+#define IB_MAX_NUM_VLS 16
+/****s* IBA Base: Types/ib_slvl_table_t
+* NAME
+*	ib_slvl_table_t
+*
+* DESCRIPTION
+*	IBA defined SL2VL Mapping Table Attribute. (14.2.5.8)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table {
+	uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS / 2];
+} PACK_SUFFIX ib_slvl_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_slvl_table_record_t
+* NAME
+*	ib_slvl_table_record_t
+*
+* DESCRIPTION
+*	IBA defined SL to VL Mapping Table Record for SA Query. (15.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table_record {
+	ib_net16_t lid;		// for CA: lid of port, for switch lid of port 0
+	uint8_t in_port_num;	// reserved for CAs
+	uint8_t out_port_num;	// reserved for CAs
+	uint32_t resv;
+	ib_slvl_table_t slvl_tbl;
+
+} PACK_SUFFIX ib_slvl_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****f* IBA Base: Types/ib_slvl_table_set
+* NAME
+*	ib_slvl_table_set
+*
+* DESCRIPTION
+*	Set slvl table entry.
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_slvl_table_set(IN ib_slvl_table_t * p_slvl_tbl,
+		  IN uint8_t sl_index, IN uint8_t vl)
+{
+	uint8_t idx = sl_index / 2;
+	CL_ASSERT(vl <= 15);
+	CL_ASSERT(sl_index <= 15);
+
+	if (sl_index % 2) {
+		/* this is an odd sl. Need to update the ls bits */
+		p_slvl_tbl->raw_vl_by_sl[idx] =
+		    (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) | vl;
+	} else {
+		/* this is an even sl. Need to update the ms bits */
+		p_slvl_tbl->raw_vl_by_sl[idx] =
+		    (vl << 4) | (p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F);
+	}
+}
+
+/*
+* PARAMETERS
+*	p_slvl_tbl
+*		[in] pointer to ib_slvl_table_t object.
+*
+*	sl_index
+*		[in] the sl index in the table to be updated.
+*
+*	vl
+*		[in] the vl value to update for that sl.
+*
+* RETURN VALUES
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_slvl_table_t
+*********/
+
+/****f* IBA Base: Types/ib_slvl_table_get
+* NAME
+*	ib_slvl_table_get
+*
+* DESCRIPTION
+*	Get slvl table entry.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_slvl_table_get(IN const ib_slvl_table_t * p_slvl_tbl, IN uint8_t sl_index)
+{
+	uint8_t idx = sl_index / 2;
+	CL_ASSERT(sl_index <= 15);
+
+	if (sl_index % 2) {
+		/* this is an odd sl. Need to return the ls bits. */
+		return (p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F);
+	} else {
+		/* this is an even sl. Need to return the ms bits. */
+		return ((p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4);
+	}
+}
+
+/*
+* PARAMETERS
+*	p_slvl_tbl
+*		[in] pointer to ib_slvl_table_t object.
+*
+*	sl_index
+*		[in] the sl index in the table whose value should be returned.
+*
+* RETURN VALUES
+*	vl for the requested sl_index.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_slvl_table_t
+*********/
+
+/****s* IBA Base: Types/ib_vl_arb_element_t
+* NAME
+*	ib_vl_arb_element_t
+*
+* DESCRIPTION
+*	IBA defined VL Arbitration Table Element. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_element {
+	uint8_t vl;
+	uint8_t weight;
+} PACK_SUFFIX ib_vl_arb_element_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
+
+/****s* IBA Base: Types/ib_vl_arb_table_t
+* NAME
+*	ib_vl_arb_table_t
+*
+* DESCRIPTION
+*	IBA defined VL Arbitration Table. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table {
+	ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
+} PACK_SUFFIX ib_vl_arb_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_vl_arb_table_record_t
+* NAME
+*	ib_vl_arb_table_record_t
+*
+* DESCRIPTION
+*	IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table_record {
+	ib_net16_t lid;		// for CA: lid of port, for switch lid of port 0
+	uint8_t port_num;
+	uint8_t block_num;
+	uint32_t reserved;
+	ib_vl_arb_table_t vl_arb_tbl;
+} PACK_SUFFIX ib_vl_arb_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/*
+ *	Global route header information received with unreliable datagram messages
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_grh {
+	ib_net32_t ver_class_flow;
+	ib_net16_t resv1;
+	uint8_t resv2;
+	uint8_t hop_limit;
+	ib_gid_t src_gid;
+	ib_gid_t dest_gid;
+} PACK_SUFFIX ib_grh_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_grh_get_ver_class_flow
+* NAME
+*	ib_grh_get_ver_class_flow
+*
+* DESCRIPTION
+*	Get encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_grh_get_ver_class_flow(IN const ib_net32_t ver_class_flow,
+			  OUT uint8_t * const p_ver,
+			  OUT uint8_t * const p_tclass,
+			  OUT uint32_t * const p_flow_lbl)
+{
+	ib_net32_t tmp_ver_class_flow;
+
+	if (p_ver)
+		*p_ver = (uint8_t) (ver_class_flow & 0x0f);
+
+	tmp_ver_class_flow = ver_class_flow >> 4;
+
+	if (p_tclass)
+		*p_tclass = (uint8_t) (tmp_ver_class_flow & 0xff);
+
+	tmp_ver_class_flow = tmp_ver_class_flow >> 8;
+
+	if (p_flow_lbl)
+		*p_flow_lbl = tmp_ver_class_flow & 0xfffff;
+}
+
+/*
+* PARAMETERS
+*	ver_class_flow
+*		[in] the version, traffic class and flow label info.
+*
+* RETURN VALUES
+*	p_ver
+*		[out] pointer to the version info.
+*
+*	p_tclass
+*		[out] pointer to the traffic class info.
+*
+*	p_flow_lbl
+*		[out] pointer to the flow label info
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_grh_t
+*********/
+
+/****f* IBA Base: Types/ib_grh_set_ver_class_flow
+* NAME
+*	ib_grh_set_ver_class_flow
+*
+* DESCRIPTION
+*	Set encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_grh_set_ver_class_flow(IN const uint8_t ver,
+			  IN const uint8_t tclass, IN const uint32_t flow_lbl)
+{
+	ib_net32_t ver_class_flow;
+
+	ver_class_flow = flow_lbl;
+	ver_class_flow = ver_class_flow << 8;
+	ver_class_flow = ver_class_flow | tclass;
+	ver_class_flow = ver_class_flow << 4;
+	ver_class_flow = ver_class_flow | ver;
+	return (ver_class_flow);
+}
+
+/*
+* PARAMETERS
+*	ver
+*		[in] the version info.
+*
+*	tclass
+*		[in] the traffic class info.
+*
+*	flow_lbl
+*		[in] the flow label info
+*
+* RETURN VALUES
+*	ver_class_flow
+*		[out] the version, traffic class and flow label info.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_grh_t
+*********/
+
+/****s* IBA Base: Types/ib_member_rec_t
+* NAME
+*	ib_member_rec_t
+*
+* DESCRIPTION
+*	Multicast member record, used to create, join, and leave multicast
+*	groups.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_member_rec {
+	ib_gid_t mgid;
+	ib_gid_t port_gid;
+	ib_net32_t qkey;
+	ib_net16_t mlid;
+	uint8_t mtu;
+	uint8_t tclass;
+	ib_net16_t pkey;
+	uint8_t rate;
+	uint8_t pkt_life;
+	ib_net32_t sl_flow_hop;
+	uint8_t scope_state;
+	uint8_t proxy_join:1;
+	uint8_t reserved[2];
+	uint8_t pad[4];
+
+} PACK_SUFFIX ib_member_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	mgid
+*		Multicast GID address for this multicast group.
+*
+*	port_gid
+*		Valid GID of the endpoint joining this multicast group.
+*
+*	qkey
+*		Q_Key to be sued by this multicast group.
+*
+*	mlid
+*		Multicast LID for this multicast group.
+*
+*	mtu
+*		MTU and MTU selector fields to use on this path
+*
+*	tclass
+*		Another global routing parameter.
+*
+*	pkey
+*		Partition key (P_Key) to use for this member.
+*
+*	rate
+*		Rate and rate selector fields to use on this path.
+*
+*	pkt_life
+*		Packet lifetime
+*
+*	sl_flow_hop
+*		Global routing parameters: service level, hop count, and flow label.
+*
+*	scope_state
+*		MGID scope and JoinState of multicast request.
+*
+*	proxy_join
+*		Enables others in the Partition to proxy add/remove from the group
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_member_get_sl_flow_hop
+* NAME
+*	ib_member_get_sl_flow_hop
+*
+* DESCRIPTION
+*	Get encoded sl, flow label, and hop limit
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_member_get_sl_flow_hop(IN const ib_net32_t sl_flow_hop,
+			  OUT uint8_t * const p_sl,
+			  OUT uint32_t * const p_flow_lbl,
+			  OUT uint8_t * const p_hop)
+{
+	uint32_t tmp;
+
+	tmp = cl_ntoh32(sl_flow_hop);
+	if (p_hop)
+		*p_hop = (uint8_t) tmp;
+	tmp >>= 8;
+
+	if (p_flow_lbl)
+		*p_flow_lbl = (uint32_t) (tmp & 0xfffff);
+	tmp >>= 20;
+
+	if (p_sl)
+		*p_sl = (uint8_t) tmp;
+}
+
+/*
+* PARAMETERS
+*	sl_flow_hop
+*		[in] the sl, flow label, and hop limit of MC Group
+*
+* RETURN VALUES
+*	p_sl
+*		[out] pointer to the service level
+*
+*	p_flow_lbl
+*		[out] pointer to the flow label info
+*
+*	p_hop
+*		[out] pointer to the hop count limit.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_sl_flow_hop
+* NAME
+*	ib_member_set_sl_flow_hop
+*
+* DESCRIPTION
+*	Set encoded sl, flow label, and hop limit
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_member_set_sl_flow_hop(IN const uint8_t sl,
+			  IN const uint32_t flow_label,
+			  IN const uint8_t hop_limit)
+{
+	uint32_t tmp;
+
+	tmp = (sl << 28) | ((flow_label & 0xfffff) << 8) | hop_limit;
+	return cl_hton32(tmp);
+}
+
+/*
+* PARAMETERS
+*	sl
+*		[in] the service level.
+*
+*	flow_lbl
+*		[in] the flow label info
+*
+*	hop_limit
+*		[in] the hop limit.
+*
+* RETURN VALUES
+*	sl_flow_hop
+*		[out] the encoded sl, flow label, and hop limit
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_get_scope_state
+* NAME
+*	ib_member_get_scope_state
+*
+* DESCRIPTION
+*	Get encoded MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_member_get_scope_state(IN const uint8_t scope_state,
+			  OUT uint8_t * const p_scope,
+			  OUT uint8_t * const p_state)
+{
+	uint8_t tmp_scope_state;
+
+	if (p_state)
+		*p_state = (uint8_t) (scope_state & 0x0f);
+
+	tmp_scope_state = scope_state >> 4;
+
+	if (p_scope)
+		*p_scope = (uint8_t) (tmp_scope_state & 0x0f);
+
+}
+
+/*
+* PARAMETERS
+*	scope_state
+*		[in] the scope and state
+*
+* RETURN VALUES
+*	p_scope
+*		[out] pointer to the MGID scope
+*
+*	p_state
+*		[out] pointer to the join state
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_scope_state
+* NAME
+*	ib_member_set_scope_state
+*
+* DESCRIPTION
+*	Set encoded version, MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_member_set_scope_state(IN const uint8_t scope, IN const uint8_t state)
+{
+	uint8_t scope_state;
+
+	scope_state = scope;
+	scope_state = scope_state << 4;
+	scope_state = scope_state | state;
+	return (scope_state);
+}
+
+/*
+* PARAMETERS
+*	scope
+*		[in] the MGID scope
+*
+*	state
+*		[in] the JoinState
+*
+* RETURN VALUES
+*	scope_state
+*		[out] the encoded one
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_join_state
+* NAME
+*	ib_member_set_join_state
+*
+* DESCRIPTION
+*	Set JoinState
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_member_set_join_state(IN OUT ib_member_rec_t * p_mc_rec,
+			 IN const uint8_t state)
+{
+	/* keep the scope as it is */
+	p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state);
+}
+
+/*
+* PARAMETERS
+*	p_mc_rec
+*		[in] pointer to the member record
+*
+*	state
+*		[in] the JoinState
+*
+* RETURN VALUES
+*	NONE
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_member_rec_t
+*********/
+
+/*
+ * Join State Codes:
+ */
+#define IB_MC_REC_STATE_FULL_MEMBER 0x01
+#define IB_MC_REC_STATE_NON_MEMBER 0x02
+#define IB_MC_REC_STATE_SEND_ONLY_NON_MEMBER 0x04
+
+/*
+ *	Generic MAD notice types
+ */
+#define IB_NOTICE_TYPE_FATAL				0x00
+#define IB_NOTICE_TYPE_URGENT				0x01
+#define IB_NOTICE_TYPE_SECURITY				0x02
+#define IB_NOTICE_TYPE_SUBN_MGMT			0x03
+#define IB_NOTICE_TYPE_INFO				0x04
+#define IB_NOTICE_TYPE_EMPTY				0x7F
+
+#include <complib/cl_packon.h>
+typedef struct _ib_mad_notice_attr	// Total Size calc  Accumulated
+{
+	uint8_t generic_type;	// 1                1
+
+	union _notice_g_or_v {
+		struct _notice_generic	// 5                6
+		{
+			uint8_t prod_type_msb;
+			ib_net16_t prod_type_lsb;
+			ib_net16_t trap_num;
+		} PACK_SUFFIX generic;
+
+		struct _notice_vend {
+			uint8_t vend_id_msb;
+			ib_net16_t vend_id_lsb;
+			ib_net16_t dev_id;
+		} PACK_SUFFIX vend;
+	} g_or_v;
+
+	ib_net16_t issuer_lid;	// 2                 8
+	ib_net16_t toggle_count;	// 2                 10
+
+	union _data_details	// 54                64
+	{
+		struct _raw_data {
+			uint8_t details[54];
+		} PACK_SUFFIX raw_data;
+
+		struct _ntc_64_67 {
+			uint8_t res[6];
+			ib_gid_t gid;	// the Node or Multicast Group that came in/out
+		} PACK_SUFFIX ntc_64_67;
+
+		struct _ntc_128 {
+			ib_net16_t sw_lid;	// the sw lid of which link state changed
+		} PACK_SUFFIX ntc_128;
+
+		struct _ntc_129_131 {
+			ib_net16_t pad;
+			ib_net16_t lid;	// lid and port number of the violation
+			uint8_t port_num;
+		} PACK_SUFFIX ntc_129_131;
+
+		struct _ntc_144 {
+			ib_net16_t pad1;
+			ib_net16_t lid;             // lid where change occured
+			uint8_t    pad2;            // reserved
+			uint8_t    local_changes;   // 7b reserved 1b local changes
+			ib_net32_t new_cap_mask;    // new capability mask
+			ib_net16_t change_flgs;     // 13b reserved 3b change flags
+		} PACK_SUFFIX ntc_144;
+
+		struct _ntc_145 {
+			ib_net16_t pad1;
+			ib_net16_t lid;	// lid where sys guid changed
+			ib_net16_t pad2;
+			ib_net64_t new_sys_guid;	// new system image guid
+		} PACK_SUFFIX ntc_145;
+
+		struct _ntc_256 {	// total: 54
+			ib_net16_t pad1;	// 2
+			ib_net16_t lid;	// 2
+			ib_net16_t dr_slid;	// 2
+			uint8_t method;	// 1
+			uint8_t pad2;	// 1
+			ib_net16_t attr_id;	// 2
+			ib_net32_t attr_mod;	// 4
+			ib_net64_t mkey;	// 8
+			uint8_t pad3;	// 1
+			uint8_t dr_trunc_hop;	// 1
+			uint8_t dr_rtn_path[30];	// 30
+		} PACK_SUFFIX ntc_256;
+
+		struct _ntc_257_258	// violation of p/q_key // 49
+		{
+			ib_net16_t pad1;	// 2
+			ib_net16_t lid1;	// 2
+			ib_net16_t lid2;	// 2
+			ib_net32_t key;	// 2
+			uint8_t sl;	// 1
+			ib_net32_t qp1;	// 4
+			ib_net32_t qp2;	// 4
+			ib_gid_t gid1;	// 16
+			ib_gid_t gid2;	// 16
+		} PACK_SUFFIX ntc_257_258;
+
+		struct _ntc_259	// pkey violation from switch 51
+		{
+			ib_net16_t data_valid;	// 2
+			ib_net16_t lid1;	// 2
+			ib_net16_t lid2;	// 2
+			ib_net16_t pkey;	// 2
+			ib_net32_t sl_qp1; // 4b sl, 4b pad, 24b qp1
+			ib_net32_t qp2; // 8b pad, 24b qp2
+			ib_gid_t gid1;	// 16
+			ib_gid_t gid2;	// 16
+			ib_net16_t sw_lid;	// 2
+			uint8_t port_no;	// 1
+		} PACK_SUFFIX ntc_259;
+
+	} data_details;
+
+	ib_gid_t issuer_gid;	// 16          80
+
+} PACK_SUFFIX ib_mad_notice_attr_t;
+#include <complib/cl_packoff.h>
+
+/**
+ * Trap 259 masks
+ */
+#define TRAP_259_MASK_SL (CL_HTON32(0xF0000000))
+#define TRAP_259_MASK_QP (CL_HTON32(0x00FFFFFF))
+
+/**
+ * Trap 144 masks
+ */
+#define TRAP_144_MASK_OTHER_LOCAL_CHANGES      0x01
+#define TRAP_144_MASK_SM_PRIORITY_CHANGE       (CL_HTON16(0x0008))
+#define TRAP_144_MASK_LINK_SPEED_ENABLE_CHANGE (CL_HTON16(0x0004))
+#define TRAP_144_MASK_LINK_WIDTH_ENABLE_CHANGE (CL_HTON16(0x0002))
+#define TRAP_144_MASK_NODE_DESCRIPTION_CHANGE  (CL_HTON16(0x0001))
+
+/****f* IBA Base: Types/ib_notice_is_generic
+* NAME
+*	ib_notice_is_generic
+*
+* DESCRIPTION
+*	Check if the notice is generic
+*
+* SYNOPSIS
+*/
+static inline boolean_t OSM_API
+ib_notice_is_generic(IN const ib_mad_notice_attr_t * p_ntc)
+{
+	return (p_ntc->generic_type & 0x80);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to  the notice MAD attribute
+*
+* RETURN VALUES
+*	TRUE if mad is generic
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_type
+* NAME
+*	ib_notice_get_type
+*
+* DESCRIPTION
+*	Get the notice type
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_notice_get_type(IN const ib_mad_notice_attr_t * p_ntc)
+{
+	return p_ntc->generic_type & 0x7f;
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to  the notice MAD attribute
+*
+* RETURN VALUES
+*	TRUE if mad is generic
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_prod_type
+* NAME
+*	ib_notice_get_prod_type
+*
+* DESCRIPTION
+*	Get the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_notice_get_prod_type(IN const ib_mad_notice_attr_t * p_ntc)
+{
+	uint32_t pt;
+
+	pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) |
+	    (p_ntc->g_or_v.generic.prod_type_msb << 16);
+	return cl_hton32(pt);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+*	The producer type
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_prod_type
+* NAME
+*	ib_notice_set_prod_type
+*
+* DESCRIPTION
+*	Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_notice_set_prod_type(IN ib_mad_notice_attr_t * p_ntc,
+			IN ib_net32_t prod_type_val)
+{
+	uint32_t ptv = cl_ntoh32(prod_type_val);
+	p_ntc->g_or_v.generic.prod_type_lsb =
+	    cl_hton16((uint16_t) (ptv & 0x0000ffff));
+	p_ntc->g_or_v.generic.prod_type_msb =
+	    (uint8_t) ((ptv & 0x00ff0000) >> 16);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+*  prod_type
+*     [in] The producer Type code
+*
+* RETURN VALUES
+*	None
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_prod_type_ho
+* NAME
+*	ib_notice_set_prod_type_ho
+*
+* DESCRIPTION
+*	Set the notice Producer Type of Generic Notice given Host Order
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_notice_set_prod_type_ho(IN ib_mad_notice_attr_t * p_ntc,
+			   IN uint32_t prod_type_val_ho)
+{
+	p_ntc->g_or_v.generic.prod_type_lsb =
+	    cl_hton16((uint16_t) (prod_type_val_ho & 0x0000ffff));
+	p_ntc->g_or_v.generic.prod_type_msb =
+	    (uint8_t) ((prod_type_val_ho & 0x00ff0000) >> 16);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+*	prod_type
+*		[in] The producer Type code in host order
+*
+* RETURN VALUES
+*	None
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_vend_id
+* NAME
+*	ib_notice_get_vend_id
+*
+* DESCRIPTION
+*	Get the Vendor Id of Vendor type Notice
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_notice_get_vend_id(IN const ib_mad_notice_attr_t * p_ntc)
+{
+	uint32_t vi;
+
+	vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) |
+	    (p_ntc->g_or_v.vend.vend_id_msb << 16);
+	return cl_hton32(vi);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+*	The Vendor Id of Vendor type Notice
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_vend_id
+* NAME
+*	ib_notice_set_vend_id
+*
+* DESCRIPTION
+*	Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_notice_set_vend_id(IN ib_mad_notice_attr_t * p_ntc, IN ib_net32_t vend_id)
+{
+	uint32_t vi = cl_ntoh32(vend_id);
+	p_ntc->g_or_v.vend.vend_id_lsb =
+	    cl_hton16((uint16_t) (vi & 0x0000ffff));
+	p_ntc->g_or_v.vend.vend_id_msb = (uint8_t) ((vi & 0x00ff0000) >> 16);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+*	vend_id
+*		[in] The producer Type code
+*
+* RETURN VALUES
+*	None
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_vend_id_ho
+* NAME
+*	ib_notice_set_vend_id_ho
+*
+* DESCRIPTION
+*	Set the notice Producer Type of Generic Notice given a host order value
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_notice_set_vend_id_ho(IN ib_mad_notice_attr_t * p_ntc,
+			 IN uint32_t vend_id_ho)
+{
+	p_ntc->g_or_v.vend.vend_id_lsb =
+	    cl_hton16((uint16_t) (vend_id_ho & 0x0000ffff));
+	p_ntc->g_or_v.vend.vend_id_msb =
+	    (uint8_t) ((vend_id_ho & 0x00ff0000) >> 16);
+}
+
+/*
+* PARAMETERS
+*	p_ntc
+*		[in] Pointer to the notice MAD attribute
+*
+*	vend_id_ho
+*		[in] The producer Type code in host order
+*
+* RETURN VALUES
+*	None
+*
+* SEE ALSO
+*	ib_mad_notice_attr_t
+*********/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info {
+	ib_gid_t gid;
+	ib_net16_t lid_range_begin;
+	ib_net16_t lid_range_end;
+	ib_net16_t reserved1;
+	uint8_t is_generic;
+	uint8_t subscribe;
+	ib_net16_t trap_type;
+	union _inform_g_or_v {
+		struct _inform_generic {
+			ib_net16_t trap_num;
+			ib_net32_t qpn_resp_time_val;
+			uint8_t reserved2;
+			uint8_t node_type_msb;
+			ib_net16_t node_type_lsb;
+		} PACK_SUFFIX generic;
+
+		struct _inform_vend {
+			ib_net16_t dev_id;
+			ib_net32_t qpn_resp_time_val;
+			uint8_t reserved2;
+			uint8_t vendor_id_msb;
+			ib_net16_t vendor_id_lsb;
+		} PACK_SUFFIX vend;
+
+	} PACK_SUFFIX g_or_v;
+
+} PACK_SUFFIX ib_inform_info_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time
+* NAME
+*	ib_inform_info_get_qpn_resp_time
+*
+* DESCRIPTION
+*	Get QPN of the inform info
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_inform_info_get_qpn_resp_time(IN const ib_net32_t qpn_resp_time_val,
+				 OUT ib_net32_t * const p_qpn,
+				 OUT uint8_t * const p_resp_time_val)
+{
+	uint32_t tmp = cl_ntoh32(qpn_resp_time_val);
+
+	if (p_qpn)
+		*p_qpn = cl_hton32((tmp & 0xffffff00) >> 8);
+
+	if (p_resp_time_val)
+		*p_resp_time_val = (uint8_t) (tmp & 0x0000001f);
+}
+
+/*
+* PARAMETERS
+*	qpn_resp_time_val
+*		[in] the  qpn and resp time val from the mad
+*
+* RETURN VALUES
+*	p_qpn
+*		[out] pointer to the qpn
+*
+*	p_state
+*		[out] pointer to the resp time val
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_set_qpn
+* NAME
+*	ib_inform_info_set_qpn
+*
+* DESCRIPTION
+*	Set the QPN of the inform info
+*
+* SYNOPSIS
+*/
+static inline void OSM_API
+ib_inform_info_set_qpn(IN ib_inform_info_t * p_ii, IN ib_net32_t const qpn)
+{
+	uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val);
+
+	p_ii->g_or_v.generic.qpn_resp_time_val =
+	    cl_hton32((tmp & 0x000000ff) | ((cl_ntoh32(qpn) << 8) & 0xffffff00)
+	    );
+}
+
+/*
+* PARAMETERS
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_prod_type
+* NAME
+*	ib_inform_info_get_prod_type
+*
+* DESCRIPTION
+*	Get Producer Type of the Inform Info
+*	13.4.8.3 InformInfo
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_inform_info_get_prod_type(IN const ib_inform_info_t * p_inf)
+{
+	uint32_t nt;
+
+	nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |
+	    (p_inf->g_or_v.generic.node_type_msb << 16);
+	return cl_hton32(nt);
+}
+
+/*
+* PARAMETERS
+*	p_inf
+*		[in] pointer to an inform info
+*
+* RETURN VALUES
+*     The producer type
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_vend_id
+* NAME
+*	ib_inform_info_get_vend_id
+*
+* DESCRIPTION
+*	Get Node Type of the Inform Info
+*
+* SYNOPSIS
+*/
+static inline ib_net32_t OSM_API
+ib_inform_info_get_vend_id(IN const ib_inform_info_t * p_inf)
+{
+	uint32_t vi;
+
+	vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) |
+	    (p_inf->g_or_v.vend.vendor_id_msb << 16);
+	return cl_hton32(vi);
+}
+
+/*
+* PARAMETERS
+*	p_inf
+*		[in] pointer to an inform info
+*
+* RETURN VALUES
+*     The node type
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_inform_info_t
+*********/
+
+/****s* IBA Base: Types/ib_inform_info_record_t
+* NAME
+*	ib_inform_info_record_t
+*
+* DESCRIPTION
+*	IBA defined InformInfo Record. (15.2.5.12)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info_record {
+	ib_gid_t subscriber_gid;
+	ib_net16_t subscriber_enum;
+	uint8_t reserved[6];
+	ib_inform_info_t inform_info;
+	uint8_t pad[4];
+} PACK_SUFFIX ib_inform_info_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_perfmgt_mad_t
+* NAME
+*	ib_perfmgt_mad_t
+*
+* DESCRIPTION
+*	IBA defined Perf Management MAD (16.3.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_perfmgt_mad {
+	ib_mad_t header;
+	uint8_t resv[40];
+
+#define	IB_PM_DATA_SIZE		192
+	uint8_t data[IB_PM_DATA_SIZE];
+
+} PACK_SUFFIX ib_perfmgt_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	header
+*		Common MAD header.
+*
+*	resv
+*		Reserved.
+*
+*	data
+*		Performance Management payload.  The structure and content of this field
+*		depends upon the method, attr_id, and attr_mod fields in the header.
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_port_counters
+* NAME
+*	ib_port_counters_t
+*
+* DESCRIPTION
+*	IBA defined PortCounters Attribute. (16.1.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_counters {
+	uint8_t reserved;
+	uint8_t port_select;
+	ib_net16_t counter_select;
+	ib_net16_t symbol_err_cnt;
+	uint8_t link_err_recover;
+	uint8_t link_downed;
+	ib_net16_t rcv_err;
+	ib_net16_t rcv_rem_phys_err;
+	ib_net16_t rcv_switch_relay_err;
+	ib_net16_t xmit_discards;
+	uint8_t xmit_constraint_err;
+	uint8_t rcv_constraint_err;
+	uint8_t res1;
+	uint8_t link_int_buffer_overrun;
+	ib_net16_t res2;
+	ib_net16_t vl15_dropped;
+	ib_net32_t xmit_data;
+	ib_net32_t rcv_data;
+	ib_net32_t xmit_pkts;
+	ib_net32_t rcv_pkts;
+} PACK_SUFFIX ib_port_counters_t;
+#include <complib/cl_packoff.h>
+
+#define PC_LINK_INT(integ_buf_over) ((integ_buf_over & 0xF0) >> 4)
+#define PC_BUF_OVERRUN(integ_buf_over) (integ_buf_over & 0x0F)
+
+/****s* IBA Base: Types/ib_port_counters_ext
+* NAME
+*	ib_port_counters_ext_t
+*
+* DESCRIPTION
+*	IBA defined PortCounters Extended Attribute. (16.1.4.11)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_counters_ext {
+	uint8_t reserved;
+	uint8_t port_select;
+	ib_net16_t counter_select;
+	ib_net32_t reserved2;
+	ib_net64_t xmit_data;
+	ib_net64_t rcv_data;
+	ib_net64_t xmit_pkts;
+	ib_net64_t rcv_pkts;
+	ib_net64_t unicast_xmit_pkts;
+	ib_net64_t unicast_rcv_pkts;
+	ib_net64_t multicast_xmit_pkts;
+	ib_net64_t multicast_rcv_pkts;
+} PACK_SUFFIX ib_port_counters_ext_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_port_samples_control
+* NAME
+*	ib_port_samples_control_t
+*
+* DESCRIPTION
+*	IBA defined PortSamplesControl Attribute. (16.1.3.2)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_samples_control {
+	uint8_t op_code;
+	uint8_t port_select;
+	uint8_t tick;
+	uint8_t counter_width;	/* 5 bits res : 3bits counter_width */
+	ib_net32_t counter_mask;	/* 2 bits res : 3 bits counter_mask : 27 bits counter_masks_1to9 */
+	ib_net16_t counter_mask_10to14;	/* 1 bits res : 15 bits counter_masks_10to14 */
+	uint8_t sample_mech;
+	uint8_t sample_status;	/* 6 bits res : 2 bits sample_status */
+	ib_net64_t option_mask;
+	ib_net64_t vendor_mask;
+	ib_net32_t sample_start;
+	ib_net32_t sample_interval;
+	ib_net16_t tag;
+	ib_net16_t counter_select0;
+	ib_net16_t counter_select1;
+	ib_net16_t counter_select2;
+	ib_net16_t counter_select3;
+	ib_net16_t counter_select4;
+	ib_net16_t counter_select5;
+	ib_net16_t counter_select6;
+	ib_net16_t counter_select7;
+	ib_net16_t counter_select8;
+	ib_net16_t counter_select9;
+	ib_net16_t counter_select10;
+	ib_net16_t counter_select11;
+	ib_net16_t counter_select12;
+	ib_net16_t counter_select13;
+	ib_net16_t counter_select14;
+} PACK_SUFFIX ib_port_samples_control_t;
+#include <complib/cl_packoff.h>
+
+/****d* IBA Base: Types/CounterSelect values
+* NAME
+*       Counter select values
+*
+* DESCRIPTION
+*	Mandatory counter select values (16.1.3.3)
+*
+* SYNOPSIS
+*/
+#define IB_CS_PORT_XMIT_DATA (CL_HTON16(0x0001))
+#define IB_CS_PORT_RCV_DATA  (CL_HTON16(0x0002))
+#define IB_CS_PORT_XMIT_PKTS (CL_HTON16(0x0003))
+#define IB_CS_PORT_RCV_PKTS  (CL_HTON16(0x0004))
+#define IB_CS_PORT_XMIT_WAIT (CL_HTON16(0x0005))
+
+/****s* IBA Base: Types/ib_port_samples_result
+* NAME
+*	ib_port_samples_result_t
+*
+* DESCRIPTION
+*	IBA defined PortSamplesControl Attribute. (16.1.3.2)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_samples_result {
+	ib_net16_t tag;
+	ib_net16_t sample_status;	/* 14 bits res : 2 bits sample_status */
+	ib_net32_t counter0;
+	ib_net32_t counter1;
+	ib_net32_t counter2;
+	ib_net32_t counter3;
+	ib_net32_t counter4;
+	ib_net32_t counter5;
+	ib_net32_t counter6;
+	ib_net32_t counter7;
+	ib_net32_t counter8;
+	ib_net32_t counter9;
+	ib_net32_t counter10;
+	ib_net32_t counter11;
+	ib_net32_t counter12;
+	ib_net32_t counter13;
+	ib_net32_t counter14;
+} PACK_SUFFIX ib_port_samples_result_t;
+#include <complib/cl_packoff.h>
+
+/****d* IBA Base: Types/DM_SVC_NAME
+* NAME
+*	DM_SVC_NAME
+*
+* DESCRIPTION
+*	IBA defined Device Management service name (16.3)
+*
+* SYNOPSIS
+*/
+#define	DM_SVC_NAME				"DeviceManager.IBTA"
+/*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_dm_mad_t
+* NAME
+*	ib_dm_mad_t
+*
+* DESCRIPTION
+*	IBA defined Device Management MAD (16.3.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_dm_mad {
+	ib_mad_t header;
+	uint8_t resv[40];
+
+#define	IB_DM_DATA_SIZE		192
+	uint8_t data[IB_DM_DATA_SIZE];
+
+} PACK_SUFFIX ib_dm_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	header
+*		Common MAD header.
+*
+*	resv
+*		Reserved.
+*
+*	data
+*		Device Management payload.  The structure and content of this field
+*		depend upon the method, attr_id, and attr_mod fields in the header.
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_iou_info_t
+* NAME
+*	ib_iou_info_t
+*
+* DESCRIPTION
+*	IBA defined IO Unit information structure (16.3.3.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_iou_info {
+	ib_net16_t change_id;
+	uint8_t max_controllers;
+	uint8_t diag_rom;
+
+#define	IB_DM_CTRL_LIST_SIZE	128
+
+	uint8_t controller_list[IB_DM_CTRL_LIST_SIZE];
+#define	IOC_NOT_INSTALLED		0x0
+#define	IOC_INSTALLED			0x1
+//              Reserved values                         0x02-0xE
+#define	SLOT_DOES_NOT_EXIST		0xF
+
+} PACK_SUFFIX ib_iou_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	change_id
+*		Value incremented, with rollover, by any change to the controller_list.
+*
+*	max_controllers
+*		Number of slots in controller_list.
+*
+*	diag_rom
+*		A byte containing two fields: DiagDeviceID and OptionROM.
+*		These fields may be read using the ib_iou_info_diag_dev_id
+*		and ib_iou_info_option_rom functions.
+*
+*	controller_list
+*		A series of 4-bit nibbles, with each nibble representing a slot
+*		in the IO Unit.  Individual nibbles may be read using the
+*		ioc_at_slot function.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_diag_dev_id
+* NAME
+*	ib_iou_info_diag_dev_id
+*
+* DESCRIPTION
+*	Returns the DiagDeviceID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_iou_info_diag_dev_id(IN const ib_iou_info_t * const p_iou_info)
+{
+	return ((uint8_t) (p_iou_info->diag_rom >> 6 & 1));
+}
+
+/*
+* PARAMETERS
+*	p_iou_info
+*		[in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*	DiagDeviceID field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_option_rom
+* NAME
+*	ib_iou_info_option_rom
+*
+* DESCRIPTION
+*	Returns the OptionROM.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ib_iou_info_option_rom(IN const ib_iou_info_t * const p_iou_info)
+{
+	return ((uint8_t) (p_iou_info->diag_rom >> 7));
+}
+
+/*
+* PARAMETERS
+*	p_iou_info
+*		[in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*	OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ioc_at_slot
+* NAME
+*	ioc_at_slot
+*
+* DESCRIPTION
+*	Returns the IOC value at the specified slot.
+*
+* SYNOPSIS
+*/
+static inline uint8_t OSM_API
+ioc_at_slot(IN const ib_iou_info_t * const p_iou_info, IN uint8_t slot)
+{
+	if (slot >= IB_DM_CTRL_LIST_SIZE)
+		return SLOT_DOES_NOT_EXIST;
+	else
+		return (int8_t)
+		    ((slot % 2) ?
+		     ((p_iou_info->controller_list[slot / 2] & 0xf0) >> 4) :
+		     (p_iou_info->controller_list[slot / 2] & 0x0f));
+}
+
+/*
+* PARAMETERS
+*	p_iou_info
+*		[in] Pointer to the IO Unit information structure.
+*
+*	slot
+*		[in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*	OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*	ib_iou_info_t
+*********/
+
+/****s* IBA Base: Types/ib_ioc_profile_t
+* NAME
+*	ib_ioc_profile_t
+*
+* DESCRIPTION
+*	IBA defined IO Controller profile structure (16.3.3.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_profile {
+	ib_net64_t ioc_guid;
+
+	ib_net32_t vend_id;
+
+	ib_net32_t dev_id;
+	ib_net16_t dev_ver;
+	ib_net16_t resv2;
+
+	ib_net32_t subsys_vend_id;
+	ib_net32_t subsys_id;
+
+	ib_net16_t io_class;
+	ib_net16_t io_subclass;
+	ib_net16_t protocol;
+	ib_net16_t protocol_ver;
+
+	ib_net32_t resv3;
+	ib_net16_t send_msg_depth;
+	uint8_t resv4;
+	uint8_t rdma_read_depth;
+	ib_net32_t send_msg_size;
+	ib_net32_t rdma_size;
+
+	uint8_t ctrl_ops_cap;
+#define	CTRL_OPS_CAP_ST		0x01
+#define	CTRL_OPS_CAP_SF		0x02
+#define	CTRL_OPS_CAP_RT		0x04
+#define	CTRL_OPS_CAP_RF		0x08
+#define	CTRL_OPS_CAP_WT		0x10
+#define	CTRL_OPS_CAP_WF		0x20
+#define	CTRL_OPS_CAP_AT		0x40
+#define	CTRL_OPS_CAP_AF		0x80
+
+	uint8_t resv5;
+
+	uint8_t num_svc_entries;
+#define	MAX_NUM_SVC_ENTRIES	0xff
+
+	uint8_t resv6[9];
+
+#define	CTRL_ID_STRING_LEN	64
+	char id_string[CTRL_ID_STRING_LEN];
+
+} PACK_SUFFIX ib_ioc_profile_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	ioc_guid
+*		An EUI-64 GUID used to uniquely identify the IO controller.
+*
+*	vend_id
+*		IO controller vendor ID, IEEE format.
+*
+*	dev_id
+*		A number assigned by the vendor to identify the type of controller.
+*
+*	dev_ver
+*		A number assigned by the vendor to identify the divice version.
+*
+*	subsys_vend_id
+*		ID of the vendor of the enclosure, if any, in which the IO controller
+*		resides in IEEE format; otherwise zero.
+*
+*	subsys_id
+*		A number identifying the subsystem where the controller resides.
+*
+*	io_class
+*		0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand
+*		Architecture.  0xffff = Vendor specific.
+*
+*	io_subclass
+*		0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+*		Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff
+*		if the io_class component is 0xffff.
+*
+*	protocol
+*		0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+*		Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff
+*		if the io_class component is 0xffff.
+*
+*	protocol_ver
+*		Protocol specific.
+*
+*	send_msg_depth
+*		Maximum depth of the send message queue.
+*
+*	rdma_read_depth
+*		Maximum depth of the per-channel RDMA read queue.
+*
+*	send_msg_size
+*		Maximum size of send messages.
+*
+*	ctrl_ops_cap
+*		Supported operation types of this IO controller.  A bit set to one
+*		for affirmation of supported capability.
+*
+*	num_svc_entries
+*		Number of entries in the service entries table.
+*
+*	id_string
+*		UTF-8 encoded string for identifying the controller to an operator.
+*
+* SEE ALSO
+* ib_dm_mad_t
+*********/
+
+static inline uint32_t OSM_API
+ib_ioc_profile_get_vend_id(IN const ib_ioc_profile_t * const p_ioc_profile)
+{
+	return (cl_ntoh32(p_ioc_profile->vend_id) >> 8);
+}
+
+static inline void OSM_API
+ib_ioc_profile_set_vend_id(IN ib_ioc_profile_t * const p_ioc_profile,
+			   IN const uint32_t vend_id)
+{
+	p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8);
+}
+
+/****s* IBA Base: Types/ib_svc_entry_t
+* NAME
+*	ib_svc_entry_t
+*
+* DESCRIPTION
+*	IBA defined IO Controller service entry structure (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entry {
+#define	MAX_SVC_ENTRY_NAME_LEN		40
+	char name[MAX_SVC_ENTRY_NAME_LEN];
+
+	ib_net64_t id;
+
+} PACK_SUFFIX ib_svc_entry_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	name
+*		UTF-8 encoded, null-terminated name of the service.
+*
+*	id
+*		An identifier of the associated Service.
+*
+* SEE ALSO
+* ib_svc_entries_t
+*********/
+
+/****s* IBA Base: Types/ib_svc_entries_t
+* NAME
+*	ib_svc_entries_t
+*
+* DESCRIPTION
+*	IBA defined IO Controller service entry array (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entries {
+#define	SVC_ENTRY_COUNT			4
+	ib_svc_entry_t service_entry[SVC_ENTRY_COUNT];
+
+} PACK_SUFFIX ib_svc_entries_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*	service_entry
+*		An array of IO controller service entries.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_svc_entry_t
+*********/
+
+static inline void OSM_API
+ib_dm_get_slot_lo_hi(IN const ib_net32_t slot_lo_hi,
+		     OUT uint8_t * const p_slot,
+		     OUT uint8_t * const p_lo, OUT uint8_t * const p_hi)
+{
+	ib_net32_t tmp_slot_lo_hi = CL_NTOH32(slot_lo_hi);
+
+	if (p_slot)
+		*p_slot = (uint8_t) ((tmp_slot_lo_hi >> 16) & 0x0f);
+
+	if (p_hi)
+		*p_hi = (uint8_t) ((tmp_slot_lo_hi >> 8) & 0xff);
+
+	if (p_lo)
+		*p_lo = (uint8_t) ((tmp_slot_lo_hi >> 0) & 0xff);
+}
+
+/*
+ *	IBA defined information describing an I/O controller
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_info {
+	ib_net64_t module_guid;
+	ib_net64_t iou_guid;
+	ib_ioc_profile_t ioc_profile;
+	ib_net64_t access_key;
+	uint16_t initiators_conf;
+	uint8_t resv[38];
+
+} PACK_SUFFIX ib_ioc_info_t;
+#include <complib/cl_packoff.h>
+
+/*
+ *	The following definitions are shared between the Access Layer and VPD
+ */
+typedef struct _ib_ca *__ptr64 ib_ca_handle_t;
+typedef struct _ib_pd *__ptr64 ib_pd_handle_t;
+typedef struct _ib_rdd *__ptr64 ib_rdd_handle_t;
+typedef struct _ib_mr *__ptr64 ib_mr_handle_t;
+typedef struct _ib_mw *__ptr64 ib_mw_handle_t;
+typedef struct _ib_qp *__ptr64 ib_qp_handle_t;
+typedef struct _ib_eec *__ptr64 ib_eec_handle_t;
+typedef struct _ib_cq *__ptr64 ib_cq_handle_t;
+typedef struct _ib_av *__ptr64 ib_av_handle_t;
+typedef struct _ib_mcast *__ptr64 ib_mcast_handle_t;
+
+/* Currently for windows branch, use the extended version of ib special verbs struct
+	in order to be compliant with Infinicon ib_types; later we'll change it to support
+	OpenSM ib_types.h */
+
+#ifndef WIN32
+/****d* Access Layer/ib_api_status_t
+* NAME
+*	ib_api_status_t
+*
+* DESCRIPTION
+*	Function return codes indicating the success or failure of an API call.
+*	Note that success is indicated by the return value IB_SUCCESS, which
+*	is always zero.
+*
+* NOTES
+*	IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call
+*	in the pre-ioctl step itself.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_api_status_t {
+	IB_SUCCESS,
+	IB_INSUFFICIENT_RESOURCES,
+	IB_INSUFFICIENT_MEMORY,
+	IB_INVALID_PARAMETER,
+	IB_INVALID_SETTING,
+	IB_NOT_FOUND,
+	IB_TIMEOUT,
+	IB_CANCELED,
+	IB_INTERRUPTED,
+	IB_INVALID_PERMISSION,
+	IB_UNSUPPORTED,
+	IB_OVERFLOW,
+	IB_MAX_MCAST_QPS_REACHED,
+	IB_INVALID_QP_STATE,
+	IB_INVALID_EEC_STATE,
+	IB_INVALID_APM_STATE,
+	IB_INVALID_PORT_STATE,
+	IB_INVALID_STATE,
+	IB_RESOURCE_BUSY,
+	IB_INVALID_PKEY,
+	IB_INVALID_LKEY,
+	IB_INVALID_RKEY,
+	IB_INVALID_MAX_WRS,
+	IB_INVALID_MAX_SGE,
+	IB_INVALID_CQ_SIZE,
+	IB_INVALID_SERVICE_TYPE,
+	IB_INVALID_GID,
+	IB_INVALID_LID,
+	IB_INVALID_GUID,
+	IB_INVALID_CA_HANDLE,
+	IB_INVALID_AV_HANDLE,
+	IB_INVALID_CQ_HANDLE,
+	IB_INVALID_EEC_HANDLE,
+	IB_INVALID_QP_HANDLE,
+	IB_INVALID_PD_HANDLE,
+	IB_INVALID_MR_HANDLE,
+	IB_INVALID_MW_HANDLE,
+	IB_INVALID_RDD_HANDLE,
+	IB_INVALID_MCAST_HANDLE,
+	IB_INVALID_CALLBACK,
+	IB_INVALID_AL_HANDLE,	/* InfiniBand Access Layer */
+	IB_INVALID_HANDLE,	/* InfiniBand Access Layer */
+	IB_ERROR,		/* InfiniBand Access Layer */
+	IB_REMOTE_ERROR,	/* Infiniband Access Layer */
+	IB_VERBS_PROCESSING_DONE,	/* See Notes above         */
+	IB_INVALID_WR_TYPE,
+	IB_QP_IN_TIMEWAIT,
+	IB_EE_IN_TIMEWAIT,
+	IB_INVALID_PORT,
+	IB_NOT_DONE,
+	IB_UNKNOWN_ERROR	/* ALWAYS LAST ENUM VALUE! */
+} ib_api_status_t;
+/*****/
+
+OSM_EXPORT const char *ib_error_str[];
+
+/****f* IBA Base: Types/ib_get_err_str
+* NAME
+*	ib_get_err_str
+*
+* DESCRIPTION
+*	Returns a string for the specified status value.
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API ib_get_err_str(IN ib_api_status_t status)
+{
+	if (status > IB_UNKNOWN_ERROR)
+		status = IB_UNKNOWN_ERROR;
+	return (ib_error_str[status]);
+}
+
+/*
+* PARAMETERS
+*	status
+*		[in] status value
+*
+* RETURN VALUES
+*	Pointer to the status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* Verbs/ib_async_event_t
+* NAME
+*	ib_async_event_t -- Async event types
+*
+* DESCRIPTION
+*	This type indicates the reason the async callback was called.
+*	The context in the ib_event_rec_t indicates the resource context
+*	that associated with the callback.  For example, for IB_AE_CQ_ERROR
+*	the context provided during the ib_create_cq is returned in the event.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_async_event_t {
+	IB_AE_SQ_ERROR = 1,
+	IB_AE_SQ_DRAINED,
+	IB_AE_RQ_ERROR,
+	IB_AE_CQ_ERROR,
+	IB_AE_QP_FATAL,
+	IB_AE_QP_COMM,
+	IB_AE_QP_APM,
+	IB_AE_EEC_FATAL,
+	IB_AE_EEC_COMM,
+	IB_AE_EEC_APM,
+	IB_AE_LOCAL_FATAL,
+	IB_AE_PKEY_TRAP,
+	IB_AE_QKEY_TRAP,
+	IB_AE_MKEY_TRAP,
+	IB_AE_PORT_TRAP,
+	IB_AE_SYSIMG_GUID_TRAP,
+	IB_AE_BUF_OVERRUN,
+	IB_AE_LINK_INTEGRITY,
+	IB_AE_FLOW_CTRL_ERROR,
+	IB_AE_BKEY_TRAP,
+	IB_AE_QP_APM_ERROR,
+	IB_AE_EEC_APM_ERROR,
+	IB_AE_WQ_REQ_ERROR,
+	IB_AE_WQ_ACCESS_ERROR,
+	IB_AE_PORT_ACTIVE,
+	IB_AE_PORT_DOWN,
+	IB_AE_UNKNOWN		/* ALWAYS LAST ENUM VALUE */
+} ib_async_event_t;
+/*
+* VALUES
+*	IB_AE_SQ_ERROR
+*		An error occurred when accessing the send queue of the QP or EEC.
+*		This event is optional.
+*
+*	IB_AE_SQ_DRAINED
+*		The send queue of the specified QP has completed the outstanding
+*		messages in progress when the state change was requested and, if
+*		applicable, has received all acknowledgements for those messages.
+*
+*	IB_AE_RQ_ERROR
+*		An error occurred when accessing the receive queue of the QP or EEC.
+*		This event is optional.
+*
+*	IB_AE_CQ_ERROR
+*		An error occurred when writing an entry to the CQ.
+*
+*	IB_AE_QP_FATAL
+*		A catastrophic error occurred while accessing or processing the
+*		work queue that prevents reporting of completions.
+*
+*	IB_AE_QP_COMM
+*		The first packet has arrived for the receive work queue where the
+*		QP is still in the RTR state.
+*
+*	IB_AE_QP_APM
+*		If alternate path migration is supported, this event indicates that
+*		the QP connection has migrated to the alternate path.
+*
+*	IB_AE_EEC_FATAL
+*		If reliable datagram service is supported, this event indicates that
+*		a catastrophic error occurred while accessing or processing the EEC
+*		that prevents reporting of completions.
+*
+*	IB_AE_EEC_COMM
+*		If reliable datagram service is supported, this event indicates that
+*		the first packet has arrived for the receive work queue where the
+*		EEC is still in the RTR state.
+*
+*	IB_AE_EEC_APM
+*		If reliable datagram service and alternate path migration is supported,
+*		this event indicates that the EEC connection has migrated to the
+*		alternate path.
+*
+*	IB_AE_LOCAL_FATAL
+*		A catastrophic HCA error occurred which cannot be attributed to any
+*		resource; behavior is indeterminate.
+*
+*	IB_AE_PKEY_TRAP
+*		A PKEY violation was detected.  This event is optional.
+*
+*	IB_AE_QKEY_TRAP
+*		A QKEY violation was detected.  This event is optional.
+*
+*	IB_AE_MKEY_TRAP
+*		An MKEY violation was detected.  This event is optional.
+*
+*	IB_AE_PORT_TRAP
+*		A port capability change was detected.  This event is optional.
+*
+*	IB_AE_SYSIMG_GUID_TRAP
+*		If the system image GUID is supported, this event indicates that the
+*		system image GUID of this HCA has been changed.  This event is
+*		optional.
+*
+*	IB_AE_BUF_OVERRUN
+*		The number of consecutive flow control update periods with at least
+*		one overrun error in each period has exceeded the threshold specified
+*		in the port info attributes.  This event is optional.
+*
+*	IB_AE_LINK_INTEGRITY
+*		The detection of excessively frequent local physical errors has
+*		exceeded the threshold specified in the port info attributes.  This
+*		event is optional.
+*
+*	IB_AE_FLOW_CTRL_ERROR
+*		An HCA watchdog timer monitoring the arrival of flow control updates
+*		has expired without receiving an update.  This event is optional.
+*
+*	IB_AE_BKEY_TRAP
+*		An BKEY violation was detected.  This event is optional.
+*
+*	IB_AE_QP_APM_ERROR
+*		If alternate path migration is supported, this event indicates that
+*		an incoming path migration request to this QP was not accepted.
+*
+*	IB_AE_EEC_APM_ERROR
+*		If reliable datagram service and alternate path migration is supported,
+*		this event indicates that an incoming path migration request to this
+*		EEC was not accepted.
+*
+*	IB_AE_WQ_REQ_ERROR
+*		An OpCode violation was detected at the responder.
+*
+*	IB_AE_WQ_ACCESS_ERROR
+*		An access violation was detected at the responder.
+*
+*	IB_AE_PORT_ACTIVE
+*		If the port active event is supported, this event is generated
+*		when the link becomes active: IB_LINK_ACTIVE.
+*
+*	IB_AE_PORT_DOWN
+*		The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,
+*		IB_LINK_DOWN.
+*
+*	IB_AE_UNKNOWN
+*		An unknown error occurred which cannot be attributed to any
+*		resource; behavior is indeterminate.
+*
+*****/
+
+OSM_EXPORT const char *ib_async_event_str[];
+
+/****f* IBA Base: Types/ib_get_async_event_str
+* NAME
+*	ib_get_async_event_str
+*
+* DESCRIPTION
+*	Returns a string for the specified asynchronous event.
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API
+ib_get_async_event_str(IN ib_async_event_t event)
+{
+	if (event > IB_AE_UNKNOWN)
+		event = IB_AE_UNKNOWN;
+	return (ib_async_event_str[event]);
+}
+
+/*
+* PARAMETERS
+*	event
+*		[in] event value
+*
+* RETURN VALUES
+*	Pointer to the asynchronous event description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* Verbs/ib_event_rec_t
+* NAME
+*	ib_event_rec_t -- Async event notification record
+*
+* DESCRIPTION
+*	When an async event callback is made, this structure is passed to indicate
+*	the type of event, the source of event that caused it, and the context
+*	associated with this event.
+*
+*	context -- Context of the resource that caused the event.
+*		-- ca_context if this is a port/adapter event.
+*		-- qp_context if the source is a QP event
+*		-- cq_context if the source is a CQ event.
+*		-- ee_context if the source is an EE event.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_event_rec {
+	void *context;
+	ib_async_event_t type;
+
+	/* HCA vendor specific event information. */
+	uint64_t vendor_specific;
+
+	/* The following structures are valid only for trap types. */
+	union _trap {
+		struct {
+			uint16_t lid;
+			ib_net64_t port_guid;
+			uint8_t port_num;
+
+			/*
+			 * The following structure is valid only for
+			 * P_KEY, Q_KEY, and M_KEY violation traps.
+			 */
+			struct {
+				uint8_t sl;
+				uint16_t src_lid;
+				uint16_t dest_lid;
+				union _key {
+					uint16_t pkey;
+					uint32_t qkey;
+					uint64_t mkey;
+				} key;
+				uint32_t src_qp;
+				uint32_t dest_qp;
+				ib_gid_t src_gid;
+				ib_gid_t dest_gid;
+
+			} violation;
+
+		} info;
+
+		ib_net64_t sysimg_guid;
+
+	} trap;
+
+} ib_event_rec_t;
+/*******/
+
+/****d* Access Layer/ib_atomic_t
+* NAME
+*	ib_atomic_t
+*
+* DESCRIPTION
+*	Indicates atomicity levels supported by an adapter.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_atomic_t {
+	IB_ATOMIC_NONE,
+	IB_ATOMIC_LOCAL,
+	IB_ATOMIC_GLOBAL
+} ib_atomic_t;
+/*
+* VALUES
+*	IB_ATOMIC_NONE
+*		Atomic operations not supported.
+*
+*	IB_ATOMIC_LOCAL
+*		Atomic operations guaranteed between QPs of a single CA.
+*
+*	IB_ATOMIC_GLOBAL
+*		Atomic operations are guaranteed between CA and any other entity
+*		in the system.
+*****/
+
+/****s* Access Layer/ib_port_cap_t
+* NAME
+*	ib_port_cap_t
+*
+* DESCRIPTION
+*	Indicates which management agents are currently available on the specified
+*	port.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_cap {
+	boolean_t cm;
+	boolean_t snmp;
+	boolean_t dev_mgmt;
+	boolean_t vend;
+	boolean_t sm;
+	boolean_t sm_disable;
+	boolean_t qkey_ctr;
+	boolean_t pkey_ctr;
+	boolean_t notice;
+	boolean_t trap;
+	boolean_t apm;
+	boolean_t slmap;
+	boolean_t pkey_nvram;
+	boolean_t mkey_nvram;
+	boolean_t sysguid;
+	boolean_t dr_notice;
+	boolean_t boot_mgmt;
+	boolean_t capm_notice;
+	boolean_t reinit;
+	boolean_t ledinfo;
+	boolean_t port_active;
+
+} ib_port_cap_t;
+/*****/
+
+/****d* Access Layer/ib_init_type_t
+* NAME
+*	ib_init_type_t
+*
+* DESCRIPTION
+*	If supported by the HCA, the type of initialization requested by
+*	this port before SM moves it to the active or armed state.  If the
+*	SM implements reinitialization, it shall set these bits to indicate
+*	the type of initialization performed prior to activating the port.
+*	Otherwise, these bits shall be set to 0.
+*
+* SYNOPSIS
+*/
+typedef uint8_t ib_init_type_t;
+#define IB_INIT_TYPE_NO_LOAD			0x01
+#define IB_INIT_TYPE_PRESERVE_CONTENT		0x02
+#define IB_INIT_TYPE_PRESERVE_PRESENCE		0x04
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE		0x08
+/*****/
+
+/****s* Access Layer/ib_port_attr_mod_t
+* NAME
+*	ib_port_attr_mod_t
+*
+* DESCRIPTION
+*	Port attributes that may be modified.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr_mod {
+	ib_port_cap_t cap;
+	uint16_t pkey_ctr;
+	uint16_t qkey_ctr;
+
+	ib_init_type_t init_type;
+	ib_net64_t system_image_guid;
+
+} ib_port_attr_mod_t;
+/*
+* SEE ALSO
+*	ib_port_cap_t
+*****/
+
+/****s* Access Layer/ib_port_attr_t
+* NAME
+*	ib_port_attr_t
+*
+* DESCRIPTION
+*	Information about a port on a given channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr {
+	ib_net64_t port_guid;
+	uint8_t port_num;
+	uint8_t mtu;
+	uint64_t max_msg_size;
+	ib_net16_t lid;
+	uint8_t lmc;
+
+	/*
+	 * LinkWidthSupported as defined in PortInfo.  Required to calculate
+	 * inter-packet delay (a.k.a. static rate).
+	 */
+	uint8_t link_width_supported;
+
+	uint16_t max_vls;
+
+	ib_net16_t sm_lid;
+	uint8_t sm_sl;
+	uint8_t link_state;
+
+	ib_init_type_t init_type_reply;	/* Optional */
+
+	/*
+	 * subnet_timeout:
+	 * The maximum expected subnet propagation delay to reach any port on
+	 * the subnet.  This value also determines the rate at which traps can
+	 * be generated from this node.
+	 *
+	 * timeout = 4.096 microseconds * 2^subnet_timeout
+	 */
+	uint8_t subnet_timeout;
+
+	ib_port_cap_t cap;
+	uint16_t pkey_ctr;
+	uint16_t qkey_ctr;
+
+	uint16_t num_gids;
+	uint16_t num_pkeys;
+	/*
+	 * Pointers at the end of the structure to allow doing a simple
+	 * memory comparison of contents up to the first pointer.
+	 */
+	ib_gid_t *p_gid_table;
+	ib_net16_t *p_pkey_table;
+
+} ib_port_attr_t;
+/*
+* SEE ALSO
+*	uint8_t, ib_port_cap_t, ib_link_states_t
+*****/
+
+/****s* Access Layer/ib_ca_attr_t
+* NAME
+*	ib_ca_attr_t
+*
+* DESCRIPTION
+*	Information about a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_attr {
+	ib_net64_t ca_guid;
+
+	uint32_t vend_id;
+	uint16_t dev_id;
+	uint16_t revision;
+	uint64_t fw_ver;
+
+	/*
+	 * Total size of the ca attributes in bytes
+	 */
+	uint32_t size;
+	uint32_t max_qps;
+	uint32_t max_wrs;
+
+	uint32_t max_sges;
+	uint32_t max_rd_sges;
+
+	uint32_t max_cqs;
+	uint32_t max_cqes;
+
+	uint32_t max_pds;
+
+	uint32_t init_regions;
+	uint64_t init_region_size;
+
+	uint32_t init_windows;
+	uint32_t max_addr_handles;
+
+	uint32_t max_partitions;
+
+	ib_atomic_t atomicity;
+
+	uint8_t max_qp_resp_res;
+	uint8_t max_eec_resp_res;
+	uint8_t max_resp_res;
+
+	uint8_t max_qp_init_depth;
+	uint8_t max_eec_init_depth;
+
+	uint32_t max_eecs;
+	uint32_t max_rdds;
+
+	uint32_t max_ipv6_qps;
+	uint32_t max_ether_qps;
+
+	uint32_t max_mcast_grps;
+	uint32_t max_mcast_qps;
+	uint32_t max_qps_per_mcast_grp;
+	uint32_t max_fmr;
+	uint32_t max_map_per_fmr;
+
+	/*
+	 * local_ack_delay:
+	 * Specifies the maximum time interval between the local CA receiving
+	 * a message and the transmission of the associated ACK or NAK.
+	 *
+	 * timeout = 4.096 microseconds * 2^local_ack_delay
+	 */
+	uint8_t local_ack_delay;
+
+	boolean_t bad_pkey_ctr_support;
+	boolean_t bad_qkey_ctr_support;
+	boolean_t raw_mcast_support;
+	boolean_t apm_support;
+	boolean_t av_port_check;
+	boolean_t change_primary_port;
+	boolean_t modify_wr_depth;
+	boolean_t current_qp_state_support;
+	boolean_t shutdown_port_capability;
+	boolean_t init_type_support;
+	boolean_t port_active_event_support;
+	boolean_t system_image_guid_support;
+	boolean_t hw_agents;
+
+	ib_net64_t system_image_guid;
+
+	uint32_t num_page_sizes;
+	uint8_t num_ports;
+
+	uint32_t *p_page_size;
+	ib_port_attr_t *p_port_attr;
+
+} ib_ca_attr_t;
+/*
+* FIELDS
+*	ca_guid
+*		GUID for this adapter.
+*
+*	vend_id
+*		IEEE vendor ID for this adapter
+*
+*	dev_id
+*		Device ID of this adapter. (typically from PCI device ID)
+*
+*	revision
+*		Revision ID of this adapter
+*
+*	fw_ver
+*		Device Firmware version.
+*
+*	size
+*		Total size in bytes for the HCA attributes.  This size includes total
+*		size required for all the variable members of the structure.  If a
+*		vendor requires to pass vendor specific fields beyond this structure,
+*		the HCA vendor can choose to report a larger size.  If a vendor is
+*		reporting extended vendor specific features, they should also provide
+*		appropriate access functions to aid with the required interpretation.
+*
+*	max_qps
+*		Maximum number of QP's supported by this HCA.
+*
+*	max_wrs
+*		Maximum number of work requests supported by this HCA.
+*
+*	max_sges
+*		Maximum number of scatter gather elements supported per work request.
+*
+*	max_rd_sges
+*		Maximum number of scatter gather elements supported for READ work
+*		requests for a Reliable Datagram QP.  This value must be zero if RD
+*		service is not supported.
+*
+*	max_cqs
+*		Maximum number of Completion Queues supported.
+*
+*	max_cqes
+*		Maximum number of CQ elements supported per CQ.
+*
+*	max_pds
+*		Maximum number of protection domains supported.
+*
+*	init_regions
+*		Initial number of memory regions supported.  These are only informative
+*		values.  HCA vendors can extended and grow these limits on demand.
+*
+*	init_region_size
+*		Initial limit on the size of the registered memory region.
+*
+*	init_windows
+*		Initial number of window entries supported.
+*
+*	max_addr_handles
+*		Maximum number of address handles supported.
+*
+*	max_partitions
+*		Maximum number of partitions supported.
+*
+*	atomicity
+*		Indicates level of atomic operations supported by this HCA.
+*
+*	max_qp_resp_res
+*	max_eec_resp_res
+*		Maximum limit on number of responder resources for incoming RDMA
+*		operations, on QPs and EEC's respectively.
+*
+*	max_resp_res
+*		Maximum number of responder resources per HCA, with this HCA used as
+*		the target.
+*
+*	max_qp_init_depth
+*	max_eec_init_depth
+*		Maximimum initiator depth per QP or EEC for initiating RDMA reads and
+*		atomic operations.
+*
+*	max_eecs
+*		Maximimum number of EEC's supported by the HCA.
+*
+*	max_rdds
+*		Maximum number of Reliable datagram domains supported.
+*
+*	max_ipv6_qps
+*	max_ether_qps
+*		Maximum number of IPV6 and raw ether QP's supported by this HCA.
+*
+*	max_mcast_grps
+*		Maximum number of multicast groups supported.
+*
+*	max_mcast_qps
+*		Maximum number of QP's that can support multicast operations.
+*
+*	max_qps_per_mcast_grp
+*		Maximum number of multicast QP's per multicast group.
+*
+*	local_ack_delay
+*		Specifies the maximum time interval between the local CA receiving
+*		a message and the transmission of the associated ACK or NAK.
+*		timeout = 4.096 microseconds * 2^local_ack_delay
+*
+*	bad_pkey_ctr_support
+*	bad_qkey_ctr_support
+*		Indicates support for the bad pkey and qkey counters.
+*
+*	raw_mcast_support
+*		Indicates support for raw packet multicast.
+*
+*	apm_support
+*		Indicates support for Automatic Path Migration.
+*
+*	av_port_check
+*		Indicates ability to check port number in address handles.
+*
+*	change_primary_port
+*		Indicates ability to change primary port for a QP or EEC during a
+*		SQD->RTS transition.
+*
+*	modify_wr_depth
+*		Indicates ability to modify QP depth during a modify QP operation.
+*		Check the verb specification for permitted states.
+*
+*	current_qp_state_support
+*		Indicates ability of the HCA to support the current QP state modifier
+*		during a modify QP operation.
+*
+*	shutdown_port_capability
+*		Shutdown port capability support indicator.
+*
+*	init_type_support
+*		Indicates init_type_reply and ability to set init_type is supported.
+*
+*	port_active_event_support
+*		Port active event support indicator.
+*
+*	system_image_guid_support
+*		System image GUID support indicator.
+*
+*	hw_agents
+*		Indicates SMA is implemented in HW.
+*
+*	system_image_guid
+*		Optional system image GUID.  This field is valid only if the
+*		system_image_guid_support flag is set.
+*
+*	num_page_sizes
+*		Indicates support for different page sizes supported by the HCA.
+*		The variable size array can be obtained from p_page_size.
+*
+*	num_ports
+*		Number of physical ports supported on this HCA.
+*
+*	p_page_size
+*		Array holding different page size supported.
+*
+*	p_port_attr
+*		Array holding port attributes.
+*
+* NOTES
+*	This structure contains the attributes of a channel adapter.  Users must
+*	call ib_copy_ca_attr to copy the contents of this structure to a new
+*	memory region.
+*
+* SEE ALSO
+*	ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr
+*****/
+
+/****f* Access layer/ib_copy_ca_attr
+* NAME
+*	ib_copy_ca_attr
+*
+* DESCRIPTION
+*	Copies CA attributes.
+*
+* SYNOPSIS
+*/
+ib_ca_attr_t *ib_copy_ca_attr(IN ib_ca_attr_t * const p_dest,
+			      IN const ib_ca_attr_t * const p_src);
+/*
+* PARAMETERS
+*	p_dest
+*		Pointer to the buffer that is the destination of the copy.
+*
+*	p_src
+*		Pointer to the CA attributes to copy.
+*
+* RETURN VALUE
+*	Pointer to the copied CA attributes.
+*
+* NOTES
+*	The buffer pointed to by the p_dest parameter must be at least the size
+*	specified in the size field of the buffer pointed to by p_src.
+*
+* SEE ALSO
+*	ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr
+*****/
+
+/****s* Access Layer/ib_av_attr_t
+* NAME
+*	ib_av_attr_t
+*
+* DESCRIPTION
+*	IBA address vector.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_av_attr {
+	uint8_t port_num;
+
+	uint8_t sl;
+	ib_net16_t dlid;
+
+	boolean_t grh_valid;
+	ib_grh_t grh;
+	uint8_t static_rate;
+	uint8_t path_bits;
+
+	struct _av_conn {
+		uint8_t path_mtu;
+		uint8_t local_ack_timeout;
+		uint8_t seq_err_retry_cnt;
+		uint8_t rnr_retry_cnt;
+
+	} conn;
+
+} ib_av_attr_t;
+/*
+* SEE ALSO
+*	ib_gid_t
+*****/
+
+/****d* Access Layer/ib_qp_type_t
+* NAME
+*	ib_qp_type_t
+*
+* DESCRIPTION
+*	Indicates the type of queue pair being created.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_qp_type {
+	IB_QPT_RELIABLE_CONN = 0,	/* Matches CM REQ transport type */
+	IB_QPT_UNRELIABLE_CONN = 1,	/* Matches CM REQ transport type */
+	IB_QPT_RELIABLE_DGRM = 2,	/* Matches CM REQ transport type */
+	IB_QPT_UNRELIABLE_DGRM,
+	IB_QPT_QP0,
+	IB_QPT_QP1,
+	IB_QPT_RAW_IPV6,
+	IB_QPT_RAW_ETHER,
+	IB_QPT_MAD,		/* InfiniBand Access Layer */
+	IB_QPT_QP0_ALIAS,	/* InfiniBand Access Layer */
+	IB_QPT_QP1_ALIAS	/* InfiniBand Access Layer */
+} ib_qp_type_t;
+/*
+* VALUES
+*	IB_QPT_RELIABLE_CONN
+*		Reliable, connected queue pair.
+*
+*	IB_QPT_UNRELIABLE_CONN
+*		Unreliable, connected queue pair.
+*
+*	IB_QPT_RELIABLE_DGRM
+*		Reliable, datagram queue pair.
+*
+*	IB_QPT_UNRELIABLE_DGRM
+*		Unreliable, datagram queue pair.
+*
+*	IB_QPT_QP0
+*		Queue pair 0.
+*
+*	IB_QPT_QP1
+*		Queue pair 1.
+*
+*	IB_QPT_RAW_DGRM
+*		Raw datagram queue pair.
+*
+*	IB_QPT_RAW_IPV6
+*		Raw IP version 6 queue pair.
+*
+*	IB_QPT_RAW_ETHER
+*		Raw Ethernet queue pair.
+*
+*	IB_QPT_MAD
+*		Unreliable, datagram queue pair that will send and receive management
+*		datagrams with assistance from the access layer.
+*
+*	IB_QPT_QP0_ALIAS
+*		Alias to queue pair 0.  Aliased QPs can only be created on an aliased
+*		protection domain.
+*
+*	IB_QPT_QP1_ALIAS
+*		Alias to queue pair 1.  Aliased QPs can only be created on an aliased
+*		protection domain.
+*****/
+
+/****d* Access Layer/ib_access_t
+* NAME
+*	ib_access_t
+*
+* DESCRIPTION
+*	Indicates the type of access is permitted on resources such as QPs,
+*	memory regions and memory windows.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_access_t;
+#define IB_AC_RDMA_READ				0x00000001
+#define IB_AC_RDMA_WRITE			0x00000002
+#define IB_AC_ATOMIC				0x00000004
+#define IB_AC_LOCAL_WRITE			0x00000008
+#define IB_AC_MW_BIND				0x00000010
+/*
+* NOTES
+*	Users may combine access rights using a bit-wise or operation to specify
+*	additional access.  For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants
+*	RDMA read and write access.
+*****/
+
+/****d* Access Layer/ib_qp_state_t
+* NAME
+*	ib_qp_state_t
+*
+* DESCRIPTION
+*	Indicates or sets the state of a queue pair.  The current state of a queue
+*	pair is returned through the ib_qp_query call and set via the
+*	ib_qp_modify call.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_state_t;
+#define IB_QPS_RESET				0x00000001
+#define IB_QPS_INIT				0x00000002
+#define IB_QPS_RTR				0x00000004
+#define IB_QPS_RTS				0x00000008
+#define IB_QPS_SQD				0x00000010
+#define IB_QPS_SQD_DRAINING			0x00000030
+#define IB_QPS_SQD_DRAINED			0x00000050
+#define IB_QPS_SQERR				0x00000080
+#define IB_QPS_ERROR				0x00000100
+#define IB_QPS_TIME_WAIT			0xDEAD0000	/* InfiniBand Access Layer */
+/*****/
+
+/****d* Access Layer/ib_apm_state_t
+* NAME
+*	ib_apm_state_t
+*
+* DESCRIPTION
+*	The current automatic path migration state of a queue pair
+*
+* SYNOPSIS
+*/
+typedef enum _ib_apm_state {
+	IB_APM_MIGRATED = 1,
+	IB_APM_REARM,
+	IB_APM_ARMED
+} ib_apm_state_t;
+/*****/
+
+/****s* Access Layer/ib_qp_create_t
+* NAME
+*	ib_qp_create_t
+*
+* DESCRIPTION
+*	Attributes used to initialize a queue pair at creation time.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_create {
+	ib_qp_type_t qp_type;
+
+	ib_rdd_handle_t h_rdd;
+
+	uint32_t sq_depth;
+	uint32_t rq_depth;
+	uint32_t sq_sge;
+	uint32_t rq_sge;
+
+	ib_cq_handle_t h_sq_cq;
+	ib_cq_handle_t h_rq_cq;
+
+	boolean_t sq_signaled;
+
+} ib_qp_create_t;
+/*
+* FIELDS
+*	type
+*		Specifies the type of queue pair to create.
+*
+*	h_rdd
+*		A handle to a reliable datagram domain to associate with the queue
+*		pair.  This field is ignored if the queue pair is not a reliable
+*		datagram type queue pair.
+*
+*	sq_depth
+*		Indicates the requested maximum number of work requests that may be
+*		outstanding on the queue pair's send queue.  This value must be less
+*		than or equal to the maximum reported by the channel adapter associated
+*		with the queue pair.
+*
+*	rq_depth
+*		Indicates the requested maximum number of work requests that may be
+*		outstanding on the queue pair's receive queue.  This value must be less
+*		than or equal to the maximum reported by the channel adapter associated
+*		with the queue pair.
+*
+*	sq_sge
+*		Indicates the maximum number scatter-gather elements that may be
+*		given in a send work request.  This value must be less
+*		than or equal to the maximum reported by the channel adapter associated
+*		with the queue pair.
+*
+*	rq_sge
+*		Indicates the maximum number scatter-gather elements that may be
+*		given in a receive work request.  This value must be less
+*		than or equal to the maximum reported by the channel adapter associated
+*		with the queue pair.
+*
+*	h_sq_cq
+*		A handle to the completion queue that will be used to report send work
+*		request completions.  This handle must be NULL if the type is
+*		IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*	h_rq_cq
+*		A handle to the completion queue that will be used to report receive
+*		work request completions.  This handle must be NULL if the type is
+*		IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*	sq_signaled
+*		A flag that is used to indicate whether the queue pair will signal
+*		an event upon completion of a send work request.  If set to
+*		TRUE, send work requests will always generate a completion
+*		event.  If set to FALSE, a completion event will only be
+*		generated if the send_opt field of the send work request has the
+*		IB_SEND_OPT_SIGNALED flag set.
+*
+* SEE ALSO
+*	ib_qp_type_t, ib_qp_attr_t
+*****/
+
+/****s* Access Layer/ib_qp_attr_t
+* NAME
+*	ib_qp_attr_t
+*
+* DESCRIPTION
+*	Queue pair attributes returned through ib_query_qp.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_attr {
+	ib_pd_handle_t h_pd;
+	ib_qp_type_t qp_type;
+	ib_access_t access_ctrl;
+	uint16_t pkey_index;
+
+	uint32_t sq_depth;
+	uint32_t rq_depth;
+	uint32_t sq_sge;
+	uint32_t rq_sge;
+	uint8_t init_depth;
+	uint8_t resp_res;
+
+	ib_cq_handle_t h_sq_cq;
+	ib_cq_handle_t h_rq_cq;
+	ib_rdd_handle_t h_rdd;
+
+	boolean_t sq_signaled;
+
+	ib_qp_state_t state;
+	ib_net32_t num;
+	ib_net32_t dest_num;
+	ib_net32_t qkey;
+
+	ib_net32_t sq_psn;
+	ib_net32_t rq_psn;
+
+	uint8_t primary_port;
+	uint8_t alternate_port;
+	ib_av_attr_t primary_av;
+	ib_av_attr_t alternate_av;
+	ib_apm_state_t apm_state;
+
+} ib_qp_attr_t;
+/*
+* FIELDS
+*	h_pd
+*		This is a handle to a protection domain associated with the queue
+*		pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM.
+*
+* NOTES
+*	Other fields are defined by the Infiniband specification.
+*
+* SEE ALSO
+*	ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+/****d* Access Layer/ib_qp_opts_t
+* NAME
+*	ib_qp_opts_t
+*
+* DESCRIPTION
+*	Optional fields supplied in the modify QP operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_qp_opts_t;
+#define IB_MOD_QP_ALTERNATE_AV			0x00000001
+#define IB_MOD_QP_PKEY				0x00000002
+#define IB_MOD_QP_APM_STATE			0x00000004
+#define IB_MOD_QP_PRIMARY_AV			0x00000008
+#define IB_MOD_QP_RNR_NAK_TIMEOUT		0x00000010
+#define IB_MOD_QP_RESP_RES			0x00000020
+#define IB_MOD_QP_INIT_DEPTH			0x00000040
+#define IB_MOD_QP_PRIMARY_PORT			0x00000080
+#define IB_MOD_QP_ACCESS_CTRL			0x00000100
+#define IB_MOD_QP_QKEY				0x00000200
+#define IB_MOD_QP_SQ_DEPTH			0x00000400
+#define IB_MOD_QP_RQ_DEPTH			0x00000800
+#define IB_MOD_QP_CURRENT_STATE			0x00001000
+#define IB_MOD_QP_RETRY_CNT			0x00002000
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT		0x00004000
+#define IB_MOD_QP_RNR_RETRY_CNT			0x00008000
+/*
+* SEE ALSO
+*	ib_qp_mod_t
+*****/
+
+/****s* Access Layer/ib_qp_mod_t
+* NAME
+*	ib_qp_mod_t
+*
+* DESCRIPTION
+*	Information needed to change the state of a queue pair through the
+*	ib_modify_qp call.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_mod {
+	ib_qp_state_t req_state;
+
+	union _qp_state {
+		struct _qp_reset {
+			/*
+			 * Time, in milliseconds, that the QP needs to spend in
+			 * the time wait state before being reused.
+			 */
+			uint32_t timewait;
+
+		} reset;
+
+		struct _qp_init {
+			ib_qp_opts_t opts;
+			uint8_t primary_port;
+			ib_net32_t qkey;
+			uint16_t pkey_index;
+			ib_access_t access_ctrl;
+
+		} init;
+
+		struct _qp_rtr {
+			ib_net32_t rq_psn;
+			ib_net32_t dest_qp;
+			ib_av_attr_t primary_av;
+			uint8_t resp_res;
+
+			ib_qp_opts_t opts;
+			ib_av_attr_t alternate_av;
+			ib_net32_t qkey;
+			uint16_t pkey_index;
+			ib_access_t access_ctrl;
+			uint32_t sq_depth;
+			uint32_t rq_depth;
+			uint8_t rnr_nak_timeout;
+
+		} rtr;
+
+		struct _qp_rts {
+			ib_net32_t sq_psn;
+			uint8_t retry_cnt;
+			uint8_t rnr_retry_cnt;
+			uint8_t rnr_nak_timeout;
+			uint8_t local_ack_timeout;
+			uint8_t init_depth;
+
+			ib_qp_opts_t opts;
+			ib_qp_state_t current_state;
+			ib_net32_t qkey;
+			ib_access_t access_ctrl;
+			uint8_t resp_res;
+
+			ib_av_attr_t primary_av;
+			ib_av_attr_t alternate_av;
+
+			uint32_t sq_depth;
+			uint32_t rq_depth;
+
+			ib_apm_state_t apm_state;
+			uint8_t primary_port;
+			uint16_t pkey_index;
+
+		} rts;
+
+		struct _qp_sqd {
+			boolean_t sqd_event;
+
+		} sqd;
+
+	} state;
+
+} ib_qp_mod_t;
+/*
+* SEE ALSO
+*	ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+/****s* Access Layer/ib_eec_attr_t
+* NAME
+*	ib_eec_attr_t
+*
+* DESCRIPTION
+*	Information about an end-to-end context.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_attr {
+	ib_qp_state_t state;
+	ib_rdd_handle_t h_rdd;
+	ib_net32_t local_eecn;
+
+	ib_net32_t sq_psn;
+	ib_net32_t rq_psn;
+	uint8_t primary_port;
+	uint16_t pkey_index;
+	uint32_t resp_res;
+	ib_net32_t remote_eecn;
+	uint32_t init_depth;
+	uint32_t dest_num;	// ??? What is this?
+	ib_av_attr_t primary_av;
+	ib_av_attr_t alternate_av;
+	ib_apm_state_t apm_state;
+
+} ib_eec_attr_t;
+/*
+* SEE ALSO
+*	ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+/****d* Access Layer/ib_eec_opts_t
+* NAME
+*	ib_eec_opts_t
+*
+* DESCRIPTION
+*	Optional fields supplied in the modify EEC operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_eec_opts_t;
+#define IB_MOD_EEC_ALTERNATE_AV			0x00000001
+#define IB_MOD_EEC_PKEY				0x00000002
+#define IB_MOD_EEC_APM_STATE			0x00000004
+#define IB_MOD_EEC_PRIMARY_AV			0x00000008
+#define IB_MOD_EEC_RNR				0x00000010
+#define IB_MOD_EEC_RESP_RES			0x00000020
+#define IB_MOD_EEC_OUTSTANDING			0x00000040
+#define IB_MOD_EEC_PRIMARY_PORT			0x00000080
+/*
+* NOTES
+*
+*
+*****/
+
+/****s* Access Layer/ib_eec_mod_t
+* NAME
+*	ib_eec_mod_t
+*
+* DESCRIPTION
+*	Information needed to change the state of an end-to-end context through
+*	the ib_modify_eec function.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_mod {
+	ib_qp_state_t req_state;
+
+	union _eec_state {
+		struct _eec_init {
+			uint8_t primary_port;
+			uint16_t pkey_index;
+
+		} init;
+
+		struct _eec_rtr {
+			ib_net32_t rq_psn;
+			ib_net32_t remote_eecn;
+			ib_av_attr_t primary_av;
+			uint8_t resp_res;
+
+			ib_eec_opts_t opts;
+			ib_av_attr_t alternate_av;
+			uint16_t pkey_index;
+
+		} rtr;
+
+		struct _eec_rts {
+			ib_net32_t sq_psn;
+			uint8_t retry_cnt;
+			uint8_t rnr_retry_cnt;
+			uint8_t local_ack_timeout;
+			uint8_t init_depth;
+
+			ib_eec_opts_t opts;
+			ib_av_attr_t alternate_av;
+			ib_apm_state_t apm_state;
+
+			ib_av_attr_t primary_av;
+			uint16_t pkey_index;
+			uint8_t primary_port;
+
+		} rts;
+
+		struct _eec_sqd {
+			boolean_t sqd_event;
+
+		} sqd;
+
+	} state;
+
+} ib_eec_mod_t;
+/*
+* SEE ALSO
+*	ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+/****d* Access Layer/ib_wr_type_t
+* NAME
+*	ib_wr_type_t
+*
+* DESCRIPTION
+*	Identifies the type of work request posted to a queue pair.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wr_type_t {
+	WR_SEND = 1,
+	WR_RDMA_WRITE,
+	WR_RDMA_READ,
+	WR_COMPARE_SWAP,
+	WR_FETCH_ADD
+} ib_wr_type_t;
+/*****/
+
+/****s* Access Layer/ib_local_ds_t
+* NAME
+*	ib_local_ds_t
+*
+* DESCRIPTION
+*	Local data segment information referenced by send and receive work
+*	requests.  This is used to specify local data buffers used as part of a
+*	work request.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_local_ds {
+	void *vaddr;
+	uint32_t length;
+	uint32_t lkey;
+
+} ib_local_ds_t;
+/*****/
+
+/****d* Access Layer/ib_send_opt_t
+* NAME
+*	ib_send_opt_t
+*
+* DESCRIPTION
+*	Optional flags used when posting send work requests.  These flags
+*	indicate specific processing for the send operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_send_opt_t;
+#define IB_SEND_OPT_IMMEDIATE		0x00000001
+#define IB_SEND_OPT_FENCE		0x00000002
+#define IB_SEND_OPT_SIGNALED		0x00000004
+#define IB_SEND_OPT_SOLICITED		0x00000008
+#define IB_SEND_OPT_INLINE		0x00000010
+#define IB_SEND_OPT_LOCAL		0x00000020
+#define IB_SEND_OPT_VEND_MASK		0xFFFF0000
+/*
+* VALUES
+*	The following flags determine the behavior of a work request when
+*	posted to the send side.
+*
+*	IB_SEND_OPT_IMMEDIATE
+*		Send immediate data with the given request.
+*
+*	IB_SEND_OPT_FENCE
+*		The operation is fenced.  Complete all pending send operations
+*		before processing this request.
+*
+*	IB_SEND_OPT_SIGNALED
+*		If the queue pair is configured for signaled completion, then
+*		generate a completion queue entry when this request completes.
+*
+*	IB_SEND_OPT_SOLICITED
+*		Set the solicited bit on the last packet of this request.
+*
+*	IB_SEND_OPT_INLINE
+*		Indicates that the requested send data should be copied into a VPD
+*		owned data buffer.  This flag permits the user to issue send operations
+*		without first needing to register the buffer(s) associated with the
+*		send operation.  Verb providers that support this operation may place
+*		vendor specific restrictions on the size of send operation that may
+*		be performed as inline.
+*
+*
+*  IB_SEND_OPT_LOCAL
+*     Indicates that a sent MAD request should be given to the local VPD for
+*     processing.  MADs sent using this option are not placed on the wire.
+*     This send option is only valid for MAD send operations.
+*
+*
+*	IB_SEND_OPT_VEND_MASK
+*		This mask indicates bits reserved in the send options that may be used
+*		by the verbs provider to indicate vendor specific options.  Bits set
+*		in this area of the send options are ignored by the Access Layer, but
+*		may have specific meaning to the underlying VPD.
+*
+*****/
+
+/****s* Access Layer/ib_send_wr_t
+* NAME
+*	ib_send_wr_t
+*
+* DESCRIPTION
+*	Information used to submit a work request to the send queue of a queue
+*	pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_send_wr {
+	struct _ib_send_wr *p_next;
+	uint64_t wr_id;
+	ib_wr_type_t wr_type;
+	ib_send_opt_t send_opt;
+	uint32_t num_ds;
+	ib_local_ds_t *ds_array;
+	ib_net32_t immediate_data;
+
+	union _send_dgrm {
+		struct _send_ud {
+			ib_net32_t remote_qp;
+			ib_net32_t remote_qkey;
+			ib_av_handle_t h_av;
+
+		} ud;
+
+		struct _send_rd {
+			ib_net32_t remote_qp;
+			ib_net32_t remote_qkey;
+			ib_net32_t eecn;
+
+		} rd;
+
+		struct _send_raw_ether {
+			ib_net16_t dest_lid;
+			uint8_t path_bits;
+			uint8_t sl;
+			uint8_t max_static_rate;
+			ib_net16_t ether_type;
+
+		} raw_ether;
+
+		struct _send_raw_ipv6 {
+			ib_net16_t dest_lid;
+			uint8_t path_bits;
+			uint8_t sl;
+			uint8_t max_static_rate;
+
+		} raw_ipv6;
+
+	} dgrm;
+
+	struct _send_remote_ops {
+		uint64_t vaddr;
+		uint32_t rkey;
+
+		ib_net64_t atomic1;
+		ib_net64_t atomic2;
+
+	} remote_ops;
+
+} ib_send_wr_t;
+/*
+* FIELDS
+*	p_next
+*		A pointer used to chain work requests together.  This permits multiple
+*		work requests to be posted to a queue pair through a single function
+*		call.  This value is set to NULL to mark the end of the chain.
+*
+*	wr_id
+*		A 64-bit work request identifier that is returned to the consumer
+*		as part of the work completion.
+*
+*	wr_type
+*		The type of work request being submitted to the send queue.
+*
+*	send_opt
+*		Optional send control parameters.
+*
+*	num_ds
+*		Number of local data segments specified by this work request.
+*
+*	ds_array
+*		A reference to an array of local data segments used by the send
+*		operation.
+*
+*	immediate_data
+*		32-bit field sent as part of a message send or RDMA write operation.
+*		This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE
+*		has been set.
+*
+*	dgrm.ud.remote_qp
+*		Identifies the destination queue pair of an unreliable datagram send
+*		operation.
+*
+*	dgrm.ud.remote_qkey
+*		The qkey for the destination queue pair.
+*
+*	dgrm.ud.h_av
+*		An address vector that specifies the path information used to route
+*		the outbound datagram to the destination queue pair.
+*
+*	dgrm.rd.remote_qp
+*		Identifies the destination queue pair of a reliable datagram send
+*		operation.
+*
+*	dgrm.rd.remote_qkey
+*		The qkey for the destination queue pair.
+*
+*	dgrm.rd.eecn
+*		The local end-to-end context number to use with the reliable datagram
+*		send operation.
+*
+*	dgrm.raw_ether.dest_lid
+*		The destination LID that will receive this raw ether send.
+*
+*	dgrm.raw_ether.path_bits
+*		path bits...
+*
+*	dgrm.raw_ether.sl
+*		service level...
+*
+*	dgrm.raw_ether.max_static_rate
+*		static rate...
+*
+*	dgrm.raw_ether.ether_type
+*		ether type...
+*
+*	dgrm.raw_ipv6.dest_lid
+*		The destination LID that will receive this raw ether send.
+*
+*	dgrm.raw_ipv6.path_bits
+*		path bits...
+*
+*	dgrm.raw_ipv6.sl
+*		service level...
+*
+*	dgrm.raw_ipv6.max_static_rate
+*		static rate...
+*
+*	remote_ops.vaddr
+*		The registered virtual memory address of the remote memory to access
+*		with an RDMA or atomic operation.
+*
+*	remote_ops.rkey
+*		The rkey associated with the specified remote vaddr. This data must
+*		be presented exactly as obtained from the remote node. No swapping
+*		of data must be performed.
+*
+*	atomic1
+*		The first operand for an atomic operation.
+*
+*	atomic2
+*		The second operand for an atomic operation.
+*
+* NOTES
+*	The format of data sent over the fabric is user-defined and is considered
+*	opaque to the access layer.  The sole exception to this are MADs posted
+*	to a MAD QP service.  MADs are expected to match the format defined by
+*	the Infiniband specification and must be in network-byte order when posted
+*	to the MAD QP service.
+*
+* SEE ALSO
+*	ib_wr_type_t, ib_local_ds_t, ib_send_opt_t
+*****/
+
+/****s* Access Layer/ib_recv_wr_t
+* NAME
+*	ib_recv_wr_t
+*
+* DESCRIPTION
+*	Information used to submit a work request to the receive queue of a queue
+*	pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_recv_wr {
+	struct _ib_recv_wr *p_next;
+	uint64_t wr_id;
+	uint32_t num_ds;
+	ib_local_ds_t *ds_array;
+} ib_recv_wr_t;
+/*
+* FIELDS
+*	p_next
+*		A pointer used to chain work requests together.  This permits multiple
+*		work requests to be posted to a queue pair through a single function
+*		call.  This value is set to NULL to mark the end of the chain.
+*
+*	wr_id
+*		A 64-bit work request identifier that is returned to the consumer
+*		as part of the work completion.
+*
+*	num_ds
+*		Number of local data segments specified by this work request.
+*
+*	ds_array
+*		A reference to an array of local data segments used by the send
+*		operation.
+*
+* SEE ALSO
+*	ib_local_ds_t
+*****/
+
+/****s* Access Layer/ib_bind_wr_t
+* NAME
+*	ib_bind_wr_t
+*
+* DESCRIPTION
+*	Information used to submit a memory window bind work request to the send
+*	queue of a queue pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_bind_wr {
+	uint64_t wr_id;
+	ib_send_opt_t send_opt;
+
+	ib_mr_handle_t h_mr;
+	ib_access_t access_ctrl;
+	uint32_t current_rkey;
+
+	ib_local_ds_t local_ds;
+
+} ib_bind_wr_t;
+/*
+* FIELDS
+*	wr_id
+*		A 64-bit work request identifier that is returned to the consumer
+*		as part of the work completion.
+*
+*	send_opt
+*		Optional send control parameters.
+*
+*	h_mr
+*		Handle to the memory region to which this window is being bound.
+*
+*	access_ctrl
+*		Access rights for this memory window.
+*
+*	current_rkey
+*		The current rkey assigned to this window for remote access.
+*
+*	local_ds
+*		A reference to a local data segment used by the bind operation.
+*
+* SEE ALSO
+*	ib_send_opt_t, ib_access_t, ib_local_ds_t
+*****/
+
+/****d* Access Layer/ib_wc_status_t
+* NAME
+*	ib_wc_status_t
+*
+* DESCRIPTION
+*	Indicates the status of a completed work request.  These VALUES are
+*	returned to the user when retrieving completions.  Note that success is
+*	identified as IB_WCS_SUCCESS, which is always zero.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_status_t {
+	IB_WCS_SUCCESS,
+	IB_WCS_LOCAL_LEN_ERR,
+	IB_WCS_LOCAL_OP_ERR,
+	IB_WCS_LOCAL_EEC_OP_ERR,
+	IB_WCS_LOCAL_PROTECTION_ERR,
+	IB_WCS_WR_FLUSHED_ERR,
+	IB_WCS_MEM_WINDOW_BIND_ERR,
+	IB_WCS_REM_ACCESS_ERR,
+	IB_WCS_REM_OP_ERR,
+	IB_WCS_RNR_RETRY_ERR,
+	IB_WCS_TIMEOUT_RETRY_ERR,
+	IB_WCS_REM_INVALID_REQ_ERR,
+	IB_WCS_REM_INVALID_RD_REQ_ERR,
+	IB_WCS_INVALID_EECN,
+	IB_WCS_INVALID_EEC_STATE,
+	IB_WCS_UNMATCHED_RESPONSE,	/* InfiniBand Access Layer */
+	IB_WCS_CANCELED,	/* InfiniBand Access Layer */
+	IB_WCS_UNKNOWN		/* Must be last. */
+} ib_wc_status_t;
+/*
+* VALUES
+*	IB_WCS_SUCCESS
+*		Work request completed successfully.
+*
+*	IB_WCS_MAD
+*		The completed work request was associated with a managmenet datagram
+*		that requires post processing.  The MAD will be returned to the user
+*		through a callback once all post processing has completed.
+*
+*	IB_WCS_LOCAL_LEN_ERR
+*		Generated for a work request posted to the send queue when the
+*		total of the data segment lengths exceeds the message length of the
+*		channel.  Generated for a work request posted to the receive queue when
+*		the total of the data segment lengths is too small for a
+*		valid incoming message.
+*
+*	IB_WCS_LOCAL_OP_ERR
+*		An internal QP consistency error was generated while processing this
+*		work request.  This may indicate that the QP was in an incorrect state
+*		for the requested operation.
+*
+*	IB_WCS_LOCAL_EEC_OP_ERR
+*		An internal EEC consistency error was generated while processing
+*		this work request.  This may indicate that the EEC was in an incorrect
+*		state for the requested operation.
+*
+*	IB_WCS_LOCAL_PROTECTION_ERR
+*		The data segments of the locally posted work request did not refer to
+*		a valid memory region.  The memory may not have been properly
+*		registered for the requested operation.
+*
+*	IB_WCS_WR_FLUSHED_ERR
+*		The work request was flushed from the QP before being completed.
+*
+*	IB_WCS_MEM_WINDOW_BIND_ERR
+*		A memory window bind operation failed due to insufficient access
+*		rights.
+*
+*	IB_WCS_REM_ACCESS_ERR,
+*		A protection error was detected at the remote node for a RDMA or atomic
+*		operation.
+*
+*	IB_WCS_REM_OP_ERR,
+*		The operation could not be successfully completed at the remote node.
+*		This may indicate that the remote QP was in an invalid state or
+*		contained an invalid work request.
+*
+*	IB_WCS_RNR_RETRY_ERR,
+*		The RNR retry count was exceeded while trying to send this message.
+*
+*	IB_WCS_TIMEOUT_RETRY_ERR
+*		The local transport timeout counter expired while trying to send this
+*		message.
+*
+*	IB_WCS_REM_INVALID_REQ_ERR,
+*		The remote node detected an invalid message on the channel.  This error
+*		is usually a result of one of the following:
+*			- The operation was not supported on receive queue.
+*			- There was insufficient buffers to receive a new RDMA request.
+*			- There was insufficient buffers to receive a new atomic operation.
+*			- An RDMA request was larger than 2^31 bytes.
+*
+*	IB_WCS_REM_INVALID_RD_REQ_ERR,
+*		Responder detected an invalid RD message.  This may be the result of an
+*		invalid qkey or an RDD mismatch.
+*
+*	IB_WCS_INVALID_EECN
+*		An invalid EE context number was detected.
+*
+*	IB_WCS_INVALID_EEC_STATE
+*		The EEC was in an invalid state for the specified request.
+*
+*	IB_WCS_UNMATCHED_RESPONSE
+*		A response MAD was received for which there was no matching send.  The
+*		send operation may have been canceled by the user or may have timed
+*		out.
+*
+*	IB_WCS_CANCELED
+*		The completed work request was canceled by the user.
+*****/
+
+OSM_EXPORT const char *ib_wc_status_str[];
+
+/****f* IBA Base: Types/ib_get_wc_status_str
+* NAME
+*	ib_get_wc_status_str
+*
+* DESCRIPTION
+*	Returns a string for the specified work completion status.
+*
+* SYNOPSIS
+*/
+static inline const char *OSM_API
+ib_get_wc_status_str(IN ib_wc_status_t wc_status)
+{
+	if (wc_status > IB_WCS_UNKNOWN)
+		wc_status = IB_WCS_UNKNOWN;
+	return (ib_wc_status_str[wc_status]);
+}
+
+/*
+* PARAMETERS
+*	wc_status
+*		[in] work completion status value
+*
+* RETURN VALUES
+*	Pointer to the work completion status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* Access Layer/ib_wc_type_t
+* NAME
+*	ib_wc_type_t
+*
+* DESCRIPTION
+*	Indicates the type of work completion.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_type_t {
+	IB_WC_SEND,
+	IB_WC_RDMA_WRITE,
+	IB_WC_RECV,
+	IB_WC_RDMA_READ,
+	IB_WC_MW_BIND,
+	IB_WC_FETCH_ADD,
+	IB_WC_COMPARE_SWAP,
+	IB_WC_RECV_RDMA_WRITE
+} ib_wc_type_t;
+/*****/
+
+/****d* Access Layer/ib_recv_opt_t
+* NAME
+*	ib_recv_opt_t
+*
+* DESCRIPTION
+*	Indicates optional fields valid in a receive work completion.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_recv_opt_t;
+#define	IB_RECV_OPT_IMMEDIATE		0x00000001
+#define IB_RECV_OPT_FORWARD		0x00000002
+#define IB_RECV_OPT_GRH_VALID		0x00000004
+#define IB_RECV_OPT_VEND_MASK		0xFFFF0000
+/*
+* VALUES
+*	IB_RECV_OPT_IMMEDIATE
+*		Indicates that immediate data is valid for this work completion.
+*
+*	IB_RECV_OPT_FORWARD
+*		Indicates that the received trap should be forwarded to the SM.
+*
+*	IB_RECV_OPT_GRH_VALID
+*		Indicates presence of the global route header. When set, the
+*		first 40 bytes received are the GRH.
+*
+*	IB_RECV_OPT_VEND_MASK
+*		This mask indicates bits reserved in the receive options that may be
+*		used by the verbs provider to indicate vendor specific options.  Bits
+*		set in this area of the receive options are ignored by the Access Layer,
+*		but may have specific meaning to the underlying VPD.
+*****/
+
+/****s* Access Layer/ib_wc_t
+* NAME
+*	ib_wc_t
+*
+* DESCRIPTION
+*	Work completion information.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_wc {
+	struct _ib_wc *p_next;
+	uint64_t wr_id;
+	ib_wc_type_t wc_type;
+
+	uint32_t length;
+	ib_wc_status_t status;
+	uint64_t vendor_specific;
+
+	union _wc_recv {
+		struct _wc_conn {
+			ib_recv_opt_t recv_opt;
+			ib_net32_t immediate_data;
+
+		} conn;
+
+		struct _wc_ud {
+			ib_recv_opt_t recv_opt;
+			ib_net32_t immediate_data;
+			ib_net32_t remote_qp;
+			uint16_t pkey_index;
+			ib_net16_t remote_lid;
+			uint8_t remote_sl;
+			uint8_t path_bits;
+
+		} ud;
+
+		struct _wc_rd {
+			ib_net32_t remote_eecn;
+			ib_net32_t remote_qp;
+			ib_net16_t remote_lid;
+			uint8_t remote_sl;
+			uint32_t free_cnt;
+
+		} rd;
+
+		struct _wc_raw_ipv6 {
+			ib_net16_t remote_lid;
+			uint8_t remote_sl;
+			uint8_t path_bits;
+
+		} raw_ipv6;
+
+		struct _wc_raw_ether {
+			ib_net16_t remote_lid;
+			uint8_t remote_sl;
+			uint8_t path_bits;
+			ib_net16_t ether_type;
+
+		} raw_ether;
+
+	} recv;
+
+} ib_wc_t;
+/*
+* FIELDS
+*	p_next
+*		A pointer used to chain work completions.  This permits multiple
+*		work completions to be retrieved from a completion queue through a
+*		single function call.  This value is set to NULL to mark the end of
+*		the chain.
+*
+*	wr_id
+*		The 64-bit work request identifier that was specified when posting the
+*		work request.
+*
+*	wc_type
+*		Indicates the type of work completion.
+*
+*
+*	length
+*		The total length of the data sent or received with the work request.
+*
+*	status
+*		The result of the work request.
+*
+*	vendor_specific
+*		HCA vendor specific information returned as part of the completion.
+*
+*	recv.conn.recv_opt
+*		Indicates optional fields valid as part of a work request that
+*		completed on a connected (reliable or unreliable) queue pair.
+*
+*	recv.conn.immediate_data
+*		32-bit field received as part of an inbound message on a connected
+*		queue pair.  This field is only valid if the recv_opt flag
+*		IB_RECV_OPT_IMMEDIATE has been set.
+*
+*	recv.ud.recv_opt
+*		Indicates optional fields valid as part of a work request that
+*		completed on an unreliable datagram queue pair.
+*
+*	recv.ud.immediate_data
+*		32-bit field received as part of an inbound message on a unreliable
+*		datagram queue pair.  This field is only valid if the recv_opt flag
+*		IB_RECV_OPT_IMMEDIATE has been set.
+*
+*	recv.ud.remote_qp
+*		Identifies the source queue pair of a received datagram.
+*
+*	recv.ud.pkey_index
+*		The pkey index for the source queue pair. This is valid only for
+*		GSI type QP's.
+*
+*	recv.ud.remote_lid
+*		The source LID of the received datagram.
+*
+*	recv.ud.remote_sl
+*		The service level used by the source of the received datagram.
+*
+*	recv.ud.path_bits
+*		path bits...
+*
+*	recv.rd.remote_eecn
+*		The remote end-to-end context number that sent the received message.
+*
+*	recv.rd.remote_qp
+*		Identifies the source queue pair of a received message.
+*
+*	recv.rd.remote_lid
+*		The source LID of the received message.
+*
+*	recv.rd.remote_sl
+*		The service level used by the source of the received message.
+*
+*	recv.rd.free_cnt
+*		The number of available entries in the completion queue.  Reliable
+*		datagrams may complete out of order, so this field may be used to
+*		determine the number of additional completions that may occur.
+*
+*	recv.raw_ipv6.remote_lid
+*		The source LID of the received message.
+*
+*	recv.raw_ipv6.remote_sl
+*		The service level used by the source of the received message.
+*
+*	recv.raw_ipv6.path_bits
+*		path bits...
+*
+*	recv.raw_ether.remote_lid
+*		The source LID of the received message.
+*
+*	recv.raw_ether.remote_sl
+*		The service level used by the source of the received message.
+*
+*	recv.raw_ether.path_bits
+*		path bits...
+*
+*	recv.raw_ether.ether_type
+*		ether type...
+* NOTES
+*	When the work request completes with error, the only values that the
+*	consumer can depend on are the wr_id field, and the status of the
+*	operation.
+*
+*	If the consumer is using the same CQ for completions from more than
+*	one type of QP (i.e Reliable Connected, Datagram etc), then the consumer
+*	must have additional information to decide what fields of the union are
+*	valid.
+* SEE ALSO
+*	ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t
+*****/
+
+/****s* Access Layer/ib_mr_create_t
+* NAME
+*	ib_mr_create_t
+*
+* DESCRIPTION
+*	Information required to create a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_create {
+	void *vaddr;
+	uint64_t length;
+	ib_access_t access_ctrl;
+} ib_mr_create_t;
+/*
+* FIELDS
+*	vaddr
+*		Starting virtual address of the region being registered.
+*
+*	length
+*		Length of the buffer to register.
+*
+*	access_ctrl
+*		Access rights of the registered region.
+*
+* SEE ALSO
+*	ib_access_t
+*****/
+
+/****s* Access Layer/ib_phys_create_t
+* NAME
+*	ib_phys_create_t
+*
+* DESCRIPTION
+*	Information required to create a physical memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_create {
+	uint64_t length;
+	uint32_t num_bufs;
+	uint64_t *buf_array;
+	uint32_t buf_offset;
+	uint32_t page_size;
+	ib_access_t access_ctrl;
+} ib_phys_create_t;
+/*
+*	length
+*		The length of the memory region in bytes.
+*
+*	num_bufs
+*		Number of buffers listed in the specified buffer array.
+*
+*	buf_array
+*		An array of physical buffers to be registered as a single memory
+*		region.
+*
+*	buf_offset
+*		The offset into the first physical page of the specified memory
+*		region to start the virtual address.
+*
+*	page_size
+*		The physical page size of the memory being registered.
+*
+*	access_ctrl
+*		Access rights of the registered region.
+*
+* SEE ALSO
+*	ib_access_t
+*****/
+
+/****s* Access Layer/ib_mr_attr_t
+* NAME
+*	ib_mr_attr_t
+*
+* DESCRIPTION
+*	Attributes of a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_attr {
+	ib_pd_handle_t h_pd;
+	void *local_lb;
+	void *local_ub;
+	void *remote_lb;
+	void *remote_ub;
+	ib_access_t access_ctrl;
+	uint32_t lkey;
+	uint32_t rkey;
+} ib_mr_attr_t;
+/*
+* DESCRIPTION
+*	h_pd
+*		Handle to the protection domain for this memory region.
+*
+*	local_lb
+*		The virtual address of the lower bound of protection for local
+*		memory access.
+*
+*	local_ub
+*		The virtual address of the upper bound of protection for local
+*		memory access.
+*
+*	remote_lb
+*		The virtual address of the lower bound of protection for remote
+*		memory access.
+*
+*	remote_ub
+*		The virtual address of the upper bound of protection for remote
+*		memory access.
+*
+*	access_ctrl
+*		Access rights for the specified memory region.
+*
+*	lkey
+*		The lkey associated with this memory region.
+*
+*	rkey
+*		The rkey associated with this memory region.
+*
+* NOTES
+*	The remote_lb, remote_ub, and rkey are only valid if remote memory access
+*	is enabled for this memory region.
+*
+* SEE ALSO
+*	ib_access_t
+*****/
+
+/****d* Access Layer/ib_ca_mod_t
+* NAME
+*	ib_ca_mod_t -- Modify port attributes and error counters
+*
+* DESCRIPTION
+*	Specifies modifications to the port attributes of a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_ca_mod_t;
+#define IB_CA_MOD_IS_CM_SUPPORTED		0x00000001
+#define IB_CA_MOD_IS_SNMP_SUPPORTED		0x00000002
+#define	IB_CA_MOD_IS_DEV_MGMT_SUPPORTED		0x00000004
+#define	IB_CA_MOD_IS_VEND_SUPPORTED		0x00000008
+#define	IB_CA_MOD_IS_SM				0x00000010
+#define IB_CA_MOD_IS_SM_DISABLED		0x00000020
+#define IB_CA_MOD_QKEY_CTR			0x00000040
+#define IB_CA_MOD_PKEY_CTR			0x00000080
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED		0x00000100
+#define IB_CA_MOD_IS_TRAP_SUPPORTED		0x00000200
+#define IB_CA_MOD_IS_APM_SUPPORTED		0x00000400
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED		0x00000800
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED	0x00001000
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED	0x00002000
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED		0x00004000
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED	0x00008000
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED	0x00010000
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED	0x00020000
+#define IB_CA_MOD_IS_REINIT_SUPORTED		0x00040000
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED		0x00080000
+#define IB_CA_MOD_SHUTDOWN_PORT			0x00100000
+#define IB_CA_MOD_INIT_TYPE_VALUE		0x00200000
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID		0x00400000
+/*
+* VALUES
+*	IB_CA_MOD_IS_CM_SUPPORTED
+*		Indicates if there is a communication manager accessible through
+*		the port.
+*
+*	IB_CA_MOD_IS_SNMP_SUPPORTED
+*		Indicates if there is an SNMP agent accessible through the port.
+*
+*	IB_CA_MOD_IS_DEV_MGMT_SUPPORTED
+*		Indicates if there is a device management agent accessible
+*		through the port.
+*
+*	IB_CA_MOD_IS_VEND_SUPPORTED
+*		Indicates if there is a vendor supported agent accessible
+*		through the port.
+*
+*	IB_CA_MOD_IS_SM
+*		Indicates if there is a subnet manager accessible through
+*		the port.
+*
+*	IB_CA_MOD_IS_SM_DISABLED
+*		Indicates if the port has been disabled for configuration by the
+*		subnet manager.
+*
+*	IB_CA_MOD_QKEY_CTR
+*		Used to reset the qkey violation counter associated with the
+*		port.
+*
+*	IB_CA_MOD_PKEY_CTR
+*		Used to reset the pkey violation counter associated with the
+*		port.
+*
+*	IB_CA_MOD_IS_NOTICE_SUPPORTED
+*		Indicates that this CA supports ability to generate Notices for
+*		Port State changes. (only applicable to switches)
+*
+*	IB_CA_MOD_IS_TRAP_SUPPORTED
+*		Indicates that this management port supports ability to generate
+*		trap messages. (only applicable to switches)
+*
+*	IB_CA_MOD_IS_APM_SUPPORTED
+*		Indicates that this port is capable of performing Automatic
+*		Path Migration.
+*
+*	IB_CA_MOD_IS_SLMAP_SUPPORTED
+*		Indicates this port supports SLMAP capability.
+*
+*	IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED
+*		Indicates that PKEY is supported in NVRAM
+*
+*	IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED
+*		Indicates that MKEY is supported in NVRAM
+*
+*	IB_CA_MOD_IS_SYSGUID_SUPPORTED
+*		Indicates System Image GUID support.
+*
+*	IB_CA_MOD_IS_DR_NOTICE_SUPPORTED
+*		Indicate support for generating Direct Routed Notices
+*
+*	IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED
+*		Indicates support for Boot Management
+*
+*	IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED
+*		Indicates capability to generate notices for changes to CAPMASK
+*
+*	IB_CA_MOD_IS_REINIT_SUPORTED
+*		Indicates type of node init supported. Refer to Chapter 14 for
+*		Initialization actions.
+*
+*	IB_CA_MOD_IS_LEDINFO_SUPPORTED
+*		Indicates support for LED info.
+*
+*	IB_CA_MOD_SHUTDOWN_PORT
+*		Used to modify the port active indicator.
+*
+*	IB_CA_MOD_INIT_TYPE_VALUE
+*		Used to modify the init_type value for the port.
+*
+*	IB_CA_MOD_SYSTEM_IMAGE_GUID
+*		Used to modify the system image GUID for the port.
+*****/
+
+/****d* Access Layer/ib_mr_mod_t
+* NAME
+*	ib_mr_mod_t
+*
+* DESCRIPTION
+*	Mask used to specify which attributes of a registered memory region are
+*	being modified.
+*
+* SYNOPSIS
+*/
+typedef uint32_t ib_mr_mod_t;
+#define IB_MR_MOD_ADDR					0x00000001
+#define IB_MR_MOD_PD					0x00000002
+#define IB_MR_MOD_ACCESS				0x00000004
+/*
+* PARAMETERS
+*	IB_MEM_MOD_ADDR
+*		The address of the memory region is being modified.
+*
+*	IB_MEM_MOD_PD
+*		The protection domain associated with the memory region is being
+*		modified.
+*
+*	IB_MEM_MOD_ACCESS
+*		The access rights the memory region are being modified.
+*****/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER
+* NAME
+*	IB_SMINFO_ATTR_MOD_HANDOVER
+*
+* DESCRIPTION
+*	Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_HANDOVER		(CL_HTON32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+* NAME
+*	IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+*
+* DESCRIPTION
+*	Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE		(CL_HTON32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE
+* NAME
+*	IB_SMINFO_ATTR_MOD_DISABLE
+*
+* DESCRIPTION
+*	Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISABLE			(CL_HTON32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY
+* NAME
+*	IB_SMINFO_ATTR_MOD_STANDBY
+*
+* DESCRIPTION
+*	Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_STANDBY			(CL_HTON32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER
+* NAME
+*	IB_SMINFO_ATTR_MOD_DISCOVER
+*
+* DESCRIPTION
+*	Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISCOVER			(CL_HTON32(0x000005))
+/**********/
+
+/****s* Access Layer/ib_ci_op_t
+* NAME
+*	ib_ci_op_t
+*
+* DESCRIPTION
+*	A structure used for vendor specific CA interface communication.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ci_op {
+	IN uint32_t command;
+	IN OUT void *p_buf OPTIONAL;
+	IN uint32_t buf_size;
+	IN OUT uint32_t num_bytes_ret;
+	IN OUT int32_t status;
+
+} ib_ci_op_t;
+/*
+* FIELDS
+*	command
+*		A command code that is understood by the verbs provider.
+*
+*	p_buf
+*		A reference to a buffer containing vendor specific data.  The verbs
+*		provider must not access pointers in the p_buf between user-mode and
+*		kernel-mode.  Any pointers embedded in the p_buf are invalidated by
+*		the user-mode/kernel-mode transition.
+*
+*	buf_size
+*		The size of the buffer in bytes.
+*
+*	num_bytes_ret
+*		The size in bytes of the vendor specific data returned in the buffer.
+*		This field is set by the verbs provider.  The verbs provider should
+*		verify that the buffer size is sufficient to hold the data being
+*		returned.
+*
+*	status
+*		The completion status from the verbs provider.  This field should be
+*		initialize to indicate an error to allow detection and cleanup in
+*		case a communication error occurs between user-mode and kernel-mode.
+*
+* NOTES
+*	This structure is provided to allow the exchange of vendor specific
+*	data between the originator and the verbs provider.  Users of this
+*	structure are expected to know the format of data in the p_buf based
+*	on the structure command field or the usage context.
+*****/
+
+END_C_DECLS
+#endif				/* ndef WIN32 */
+#if defined( __WIN__ )
+#include <iba/ib_types_extended.h>
+#endif
+#endif				/* __IB_TYPES_H__ */
diff --git a/include/opensm/osm_attrib_req.h b/include/opensm/osm_attrib_req.h
new file mode 100644
index 0000000..e79073b
--- /dev/null
+++ b/include/opensm/osm_attrib_req.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_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.
+ */
+/****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_ */
diff --git a/include/opensm/osm_base.h b/include/opensm/osm_base.h
new file mode 100644
index 0000000..54df41e
--- /dev/null
+++ b/include/opensm/osm_base.h
@@ -0,0 +1,898 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Basic OpenSM definitions and structures.
+ *	This object represents an OpenSM "base class".
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_BASE_H_
+#define _OSM_BASE_H_
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#ifdef __WIN__
+#include <vendor/winosm_common.h>
+#define OSM_CDECL __cdecl
+#else
+#define OSM_CDECL
+#endif
+
+#include <complib/cl_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* OpenSM/Constants
+* NAME
+*	Constants
+*
+* DESCRIPTION
+*	The following constants are used throughout the OpenSM.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****h* OpenSM/Base
+* NAME
+*	Base
+*
+* DESCRIPTION
+*	The Base object encapsulates basic information needed by the
+*	OpenSM to manage objects.  Each OpenSM object includes the
+*	Base object as the first member.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY
+* NAME
+*	OSM_DEFAULT_M_KEY
+*
+* DESCRIPTION
+*	Managment key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_M_KEY 0
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY
+* NAME
+*	OSM_DEFAULT_SM_KEY
+*
+* DESCRIPTION
+*	Subnet Manager key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_KEY CL_HTON64(1)
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_SA_KEY
+* NAME
+*	OSM_DEFAULT_SA_KEY
+*
+* DESCRIPTION
+*	Subnet Adminstration key value.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SA_KEY OSM_DEFAULT_SM_KEY
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_LMC
+* NAME
+*	OSM_DEFAULT_LMC
+*
+* DESCRIPTION
+*	Default LMC value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LMC 0
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS
+* NAME
+*	OSM_DEFAULT_MAX_OP_VLS
+*
+* DESCRIPTION
+*	Default Maximal Operational VLs to be initialized on
+*  the link ports PortInfo by the OpenSM.
+*  Default value provides backward compatibility.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MAX_OP_VLS 5
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_SL
+* NAME
+*	OSM_DEFAULT_SL
+*
+* DESCRIPTION
+*	Default SL value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SL 0
+/********/
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY
+* NAME
+*	OSM_DEFAULT_SM_PRIORITY
+*
+* DESCRIPTION
+*	Default SM priority value used by the OpenSM,
+*	as defined in the SMInfo attribute.  0 is the lowest priority.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_PRIORITY 0
+/********/
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR
+* NAME
+*	OSM_DEFAULT_TMP_DIR
+*
+* DESCRIPTION
+*	Specifies the default temporary directory for the log file,
+*  osm-subnet.lst, and other log files.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_TMP_DIR GetOsmTempPath()
+#else
+#define OSM_DEFAULT_TMP_DIR "/var/log/"
+#endif
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR
+* NAME
+*	OSM_DEFAULT_CACHE_DIR
+*
+* DESCRIPTION
+*	Specifies the default cache directory for the db files.
+*	Note that the directory must appear with "/" ("\\" for windows) at the end.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CACHE_DIR GetOsmCachePath()
+#else
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/opensm/"
+#endif
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE
+* NAME
+*	OSM_DEFAULT_LOG_FILE
+*
+* DESCRIPTION
+*	Specifies the default log file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_LOG_FILE strcat(GetOsmTempPath(), "osm.log")
+#else
+#define OSM_DEFAULT_LOG_FILE "/var/log/opensm.log"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_CONFIG_FILE
+* NAME
+*	OSM_DEFAULT_CONFIG_FILE
+*
+* DESCRIPTION
+*	Specifies the default OpenSM config file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CONFIG_FILE strcat(GetOsmCachePath(), "opensm.conf")
+#elif defined(HAVE_DEFAULT_OPENSM_CONFIG_FILE)
+#define OSM_DEFAULT_CONFIG_FILE HAVE_DEFAULT_OPENSM_CONFIG_FILE
+#elif defined (OPENSM_CONFIG_DIR)
+#define OSM_DEFAULT_CONFIG_FILE OPENSM_CONFIG_DIR "/opensm.conf"
+#else
+#define OSM_DEFAULT_CONFIG_FILE "/etc/opensm/opensm.conf"
+#endif /* __WIN__ */
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE
+* NAME
+*	OSM_DEFAULT_PARTITION_CONFIG_FILE
+*
+* DESCRIPTION
+*	Specifies the default partition config file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE strcat(GetOsmCachePath(), "osm-partitions.conf")
+#elif defined(HAVE_DEFAULT_PARTITION_CONFIG_FILE)
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE HAVE_DEFAULT_PARTITION_CONFIG_FILE
+#elif defined(OPENSM_CONFIG_DIR)
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE OPENSM_CONFIG_DIR "/partitions.conf"
+#else
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/opensm/partitions.conf"
+#endif /* __WIN__ */
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_POLICY_FILE
+* NAME
+*	OSM_DEFAULT_QOS_POLICY_FILE
+*
+* DESCRIPTION
+*	Specifies the default QoS policy file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_QOS_POLICY_FILE strcat(GetOsmCachePath(), "osm-qos-policy.conf")
+#elif defined(HAVE_DEFAULT_QOS_POLICY_FILE)
+#define OSM_DEFAULT_QOS_POLICY_FILE HAVE_DEFAULT_QOS_POLICY_FILE
+#elif defined(OPENSM_CONFIG_DIR)
+#define OSM_DEFAULT_QOS_POLICY_FILE OPENSM_CONFIG_DIR "/qos-policy.conf"
+#else
+#define OSM_DEFAULT_QOS_POLICY_FILE "/etc/opensm/qos-policy.conf"
+#endif /* __WIN__ */
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_PREFIX_ROUTES_FILE
+* NAME
+*	OSM_DEFAULT_PREFIX_ROUTES_FILE
+*
+* DESCRIPTION
+*	Specifies the default prefix routes file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_PREFIX_ROUTES_FILE strcat(GetOsmCachePath(), "osm-prefix-routes.conf")
+#elif defined(HAVE_DEFAULT_PREFIX_ROUTES_FILE)
+#define OSM_DEFAULT_PREFIX_ROUTES_FILE HAVE_DEFAULT_PREFIX_ROUTES_FILE
+#elif defined(OPENSM_CONFIG_DIR)
+#define OSM_DEFAULT_PREFIX_ROUTES_FILE OPENSM_CONFIG_DIR "/prefix-routes.conf"
+#else
+#define OSM_DEFAULT_PREFIX_ROUTES_FILE "/etc/opensm/prefix-routes.conf"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
+* NAME
+*	OSM_DEFAULT_SWEEP_INTERVAL_SECS
+*
+* DESCRIPTION
+*	Specifies the default number of seconds between subnet sweeps.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+* NAME
+*	OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+*
+* DESCRIPTION
+*	Specifies the default transaction timeout in milliseconds.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 200
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT
+* NAME
+*	OSM_DEFAULT_SUBNET_TIMEOUT
+*
+* DESCRIPTION
+*	Specifies the default subnet timeout.
+*	timeout time = 4us * 2^timeout.
+*  We use here ~1sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE
+* NAME
+*	OSM_DEFAULT_SWITCH_PACKET_LIFE
+*
+* DESCRIPTION
+*	Specifies the default max life time for a pcket on the switch.
+*	timeout time = 4us * 2^timeout.
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+* NAME
+*	OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*	Sets the time a packet can live in the head of the VL Queue
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+* NAME
+*	OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*	Sets the time a packet can live in the head of the VL Queue
+*  of a port that drives a CA port.
+*  We use here the value of ~256msec
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0x10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_VL_STALL_COUNT
+* NAME
+*	OSM_DEFAULT_LEAF_VL_COUNT
+*
+* DESCRIPTION
+*	Sets the number of consecutive head of queue life time drops that
+*  puts the VL into stalled state. In stalled state, the port is supposed
+*  to drop everything for 8*(head of queue lifetime)
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_VL_STALL_COUNT 0x7
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT
+* NAME
+*	OSM_DEFAULT_LEAF_VL_STALL_COUNT
+*
+* DESCRIPTION
+*	Sets the number of consecutive head of queue life time drops that
+*  puts the VL into stalled state. In stalled state, the port is supposed
+*  to drop everything for 8*(head of queue lifetime). This value is for
+*  switch ports driving a CA port.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x7
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+* NAME
+*	OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+*
+* DESCRIPTION
+*	Specifies the default timeout for ignoring same trap.
+*	timeout time = 5000000us
+*  We use here ~5sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT
+* NAME
+*	OSM_DEFAULT_UNHEALTHY_TIMEOUT
+*
+* DESCRIPTION
+*	Specifies the default timeout for setting port as unhealthy.
+*	timeout time = 60000000us
+*  We use here ~60sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD
+* NAME
+*	OSM_DEFAULT_ERROR_THRESHOLD
+*
+* DESCRIPTION
+*	Specifies default link error threshold to be set by SubnSet(PortInfo).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE
+* NAME
+*	OSM_DEFAULT_SMP_MAX_ON_WIRE
+*
+* DESCRIPTION
+*	Specifies the default number of VL15 SMP MADs allowed on
+*	the wire at any one time.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 4
+/***********/
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
+* NAME
+*	OSM_SM_DEFAULT_QP0_RCV_SIZE
+*
+* DESCRIPTION
+*	Specifies the default size (in MADs) of the QP0 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256
+/***********/
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE
+* NAME
+*	OSM_SM_DEFAULT_QP0_SEND_SIZE
+*
+* DESCRIPTION
+*	Specifies the default size (in MADs) of the QP0 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256
+/***********/
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256
+/****d* OpenSM: Base/OSM_PM_DEFAULT_QP1_RCV_SIZE
+* NAME
+*   OSM_PM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_PM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+/****d* OpenSM: Base/OSM_PM_DEFAULT_QP1_SEND_SIZE
+* NAME
+*   OSM_PM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_PM_DEFAULT_QP1_SEND_SIZE 256
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+* NAME
+*   OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+*
+* DESCRIPTION
+*   Specifies the polling timeout (in miliseconds) - the timeout
+*   between one poll to another.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000
+/**********/
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+* NAME
+*   OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+*
+* DESCRIPTION
+*   Specifies the number of polling retries before the SM goes back
+*   to DISCOVERY stage. So the default total time for handoff is 40 sec.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 4
+/**********/
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_MTU
+* Name
+*	OSM_DEFAULT_MGRP_MTU
+*
+* DESCRIPTION
+*	Default MTU used for new MGRP creation (2048 bytes)
+*  Note it includes the MTUSelector which is set to "Greater Than"
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_MTU 0x04
+/***********/
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_RATE
+* Name
+*	OSM_DEFAULT_MGRP_RATE
+*
+* DESCRIPTION
+*	Default RATE used for new MGRP creation (10Gb/sec)
+*  Note it includes the RateSelector which is set to "Greater Than"
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_RATE 0x03
+/***********/
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_SCOPE
+* Name
+*	OSM_DEFAULT_MGRP_SCOPE
+*
+* DESCRIPTION
+*	Default SCOPE used for new MGRP creation (link local)
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_SCOPE IB_MC_SCOPE_LINK_LOCAL
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_MAX_VLS
+ * Name
+ *       OSM_DEFAULT_QOS_MAX_VLS
+ *
+ * DESCRIPTION
+ *       Default Maximum VLs used by the OpenSM.
+ *
+ * SYNOPSIS
+ */
+#define OSM_DEFAULT_QOS_MAX_VLS 15
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_HIGH_LIMIT
+ * Name
+ *       OSM_DEFAULT_QOS_HIGH_LIMIT
+ *
+ * DESCRIPTION
+ *       Default Limit of High Priority in VL Arbitration used by OpenSM.
+ *
+ * SYNOPSIS
+ */
+#define OSM_DEFAULT_QOS_HIGH_LIMIT 0
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_VLARB_HIGH
+ * Name
+ *       OSM_DEFAULT_QOS_VLARB_HIGH
+ *
+ * DESCRIPTION
+ *       Default High Priority VL Arbitration table used by the OpenSM.
+ *
+ * SYNOPSIS
+ */
+#define OSM_DEFAULT_QOS_VLARB_HIGH "0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0"
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_VLARB_LOW
+ * Name
+ *       OSM_DEFAULT_QOS_VLARB_LOW
+ *
+ * DESCRIPTION
+ *       Default Low Priority VL Arbitration table used by the OpenSM.
+ *
+ * SYNOPSIS
+ */
+#define OSM_DEFAULT_QOS_VLARB_LOW "0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4"
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_QOS_SL2VL
+ * Name
+ *       OSM_DEFAULT_QOS_SL2VL
+ *
+ * DESCRIPTION
+ *       Default QoS SL2VL Mapping Table used by the OpenSM.
+ *
+ * SYNOPSIS
+ */
+#define OSM_DEFAULT_QOS_SL2VL "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7"
+/***********/
+/****d* OpenSM: Base/OSM_NO_PATH
+* NAME
+*	OSM_NO_PATH
+*
+* DESCRIPTION
+*	Value indicating there is no path to the given LID.
+*
+* SYNOPSIS
+*/
+#define OSM_NO_PATH			0xFF
+/**********/
+/****d* OpenSM: Base/OSM_NODE_DESC_UNKNOWN
+* NAME
+*	OSM_NODE_DESC_UNKNOWN
+*
+* DESCRIPTION
+*	Value indicating the Node Description is not set and is "unknown"
+*
+* SYNOPSIS
+*/
+#define OSM_NODE_DESC_UNKNOWN "<unknown>"
+/**********/
+/****d* OpenSM: Base/osm_thread_state_t
+* NAME
+*	osm_thread_state_t
+*
+* DESCRIPTION
+*	Enumerates the possible states of worker threads, such
+*	as the subnet sweeper.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_thread_state {
+	OSM_THREAD_STATE_NONE = 0,
+	OSM_THREAD_STATE_INIT,
+	OSM_THREAD_STATE_RUN,
+	OSM_THREAD_STATE_EXIT
+} osm_thread_state_t;
+/***********/
+
+/*
+ * OSM_CAP are from Table 117 and C15-0.1.7 Table 186
+ */
+
+/****d* OpenSM: Base/OSM_CAP_IS_TRAP_SUP
+* Name
+*	OSM_CAP_IS_SUBN_TRAP_SUP
+*
+* DESCRIPTION
+*	Management class generates Trap() MADs
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_TRAP_SUP (1 << 0)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_GET_SET_NOTICE_SUP
+* Name
+*	OSM_CAP_IS_GET_SET_NOTICE_SUP
+*
+* DESCRIPTION
+*       Management class supports Get/Set(Notice)
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP (1 << 1)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP
+* Name
+*	OSM_CAP_IS_SUBN_OPT_RECS_SUP
+*
+* DESCRIPTION
+*	Support all optional attributes except:
+*  MCMemberRecord, TraceRecord, MultiPathRecord
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP
+* Name
+*	OSM_CAP_IS_UD_MCAST_SUP
+*
+* DESCRIPTION
+*	Multicast is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_MULTIPATH_SUP
+* Name
+*	OSM_CAP_IS_MULTIPATH_SUP
+*
+* DESCRIPTION
+*	MultiPathRecord and TraceRecord are supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_MULTIPATH_SUP (1 << 10)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP
+* Name
+*	OSM_CAP_IS_REINIT_SUP
+*
+* DESCRIPTION
+*	SM/SA supports re-initialization supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_REINIT_SUP (1 << 11)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED
+* Name
+*	OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED
+*
+* DESCRIPTION
+*	SM/SA supports enhanced SA PortInfoRecord searches per 1.2 Errata:
+*  ClassPortInfo:CapabilityMask.IsPortInfoCapMaskMatchSupported is 1,
+*  then the AttributeModifier of the SubnAdmGet() and SubnAdmGetTable()
+*  methods affects the matching behavior on the PortInfo:CapabilityMask
+*  component. If the high-order bit (bit 31) of the AttributeModifier
+*  is set to 1, matching on the CapabilityMask component will not be an
+*  exact bitwise match as described in <ref to 15.4.4>.  Instead,
+*  matching will only be performed on those bits which are set to 1 in
+*  the PortInfo:CapabilityMask embedded in the query.
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED (1 << 13)
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP2_IS_QOS_SUPPORTED
+* Name
+*	OSM_CAP2_IS_QOS_SUPPORTED
+*
+* DESCRIPTION
+*	QoS is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP2_IS_QOS_SUPPORTED (1 << 1)
+/***********/
+
+/****d* OpenSM: Base/osm_signal_t
+* NAME
+*	osm_signal_t
+*
+* DESCRIPTION
+*	Enumerates the possible signal codes used by the OSM managers
+*	This cannot be an enum type, since conversion to and from
+*	integral types is necessary when passing signals through
+*	the dispatcher.
+*
+* SYNOPSIS
+*/
+#define OSM_SIGNAL_NONE				0
+#define OSM_SIGNAL_SWEEP			1
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST	2
+#define OSM_SIGNAL_PERFMGR_SWEEP		3
+#define OSM_SIGNAL_MAX				3
+
+/* status values for sweep managers - can be removed later */
+#define OSM_SIGNAL_DONE		16
+#define OSM_SIGNAL_DONE_PENDING	17
+
+typedef unsigned int osm_signal_t;
+/***********/
+
+/****d* OpenSM: Base/osm_sm_signal_t
+* NAME
+*	osm_sm_signal_t
+*
+* DESCRIPTION
+*	Enumerates the possible signals used by the OSM_SM_MGR
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_signal {
+	OSM_SM_SIGNAL_NONE = 0,
+	OSM_SM_SIGNAL_DISCOVERY_COMPLETED,
+	OSM_SM_SIGNAL_POLLING_TIMEOUT,
+	OSM_SM_SIGNAL_DISCOVER,
+	OSM_SM_SIGNAL_DISABLE,
+	OSM_SM_SIGNAL_HANDOVER,
+	OSM_SM_SIGNAL_HANDOVER_SENT,
+	OSM_SM_SIGNAL_ACKNOWLEDGE,
+	OSM_SM_SIGNAL_STANDBY,
+	OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,
+	OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,
+	OSM_SM_SIGNAL_MAX
+} osm_sm_signal_t;
+/***********/
+
+/****d* OpenSM/osm_mcast_req_type_t
+* NAME
+*	osm_mcast_req_type_t
+*
+* DESCRIPTION
+*	Enumerates the possible signals used by the OSM_MCAST_REQUEST
+*
+* SYNOPSIS
+*/
+typedef enum _osm_mcast_req_type {
+	OSM_MCAST_REQ_TYPE_CREATE,
+	OSM_MCAST_REQ_TYPE_JOIN,
+	OSM_MCAST_REQ_TYPE_LEAVE,
+	OSM_MCAST_REQ_TYPE_SUBNET_CHANGE
+} osm_mcast_req_type_t;
+/***********/
+
+/****s* OpenSM: Base/MAX_GUID_FILE_LINE_LENGTH
+* NAME
+*	MAX_GUID_FILE_LINE_LENGTH
+*
+* DESCRIPTION
+*	The maximum line number when reading guid file
+*
+* SYNOPSIS
+*/
+#define MAX_GUID_FILE_LINE_LENGTH 120
+/**********/
+
+/****s* OpenSM: Base/VendorOUIs
+* NAME
+*	VendorOUIs
+*
+* DESCRIPTION
+*	Known device vendor ID and GUID OUIs
+*
+* SYNOPSIS
+*/
+#define OSM_VENDOR_ID_INTEL         0x00D0B7
+#define OSM_VENDOR_ID_MELLANOX      0x0002C9
+#define OSM_VENDOR_ID_REDSWITCH     0x000617
+#define OSM_VENDOR_ID_SILVERSTORM   0x00066A
+#define OSM_VENDOR_ID_TOPSPIN       0x0005AD
+#define OSM_VENDOR_ID_FUJITSU       0x00E000
+#define OSM_VENDOR_ID_FUJITSU2      0x000B5D
+#define OSM_VENDOR_ID_VOLTAIRE      0x0008F1
+#define OSM_VENDOR_ID_YOTTAYOTTA    0x000453
+#define OSM_VENDOR_ID_PATHSCALE     0x001175
+#define OSM_VENDOR_ID_IBM           0x000255
+#define OSM_VENDOR_ID_DIVERGENET    0x00084E
+#define OSM_VENDOR_ID_FLEXTRONICS   0x000B8C
+#define OSM_VENDOR_ID_AGILENT       0x0030D3
+#define OSM_VENDOR_ID_OBSIDIAN      0x001777
+#define OSM_VENDOR_ID_BAYMICRO      0x000BC1
+#define OSM_VENDOR_ID_LSILOGIC      0x00A0B8
+#define OSM_VENDOR_ID_DDN           0x0001FF
+#define OSM_VENDOR_ID_PANTA         0x001393
+#define OSM_VENDOR_ID_HP            0x001708
+#define OSM_VENDOR_ID_RIOWORKS      0x005045
+#define OSM_VENDOR_ID_SUN           0x0003BA
+#define OSM_VENDOR_ID_3LEAFNTWKS    0x0016A1
+#define OSM_VENDOR_ID_XSIGO         0x001397
+#define OSM_VENDOR_ID_HP2           0x0018FE
+
+/**********/
+
+END_C_DECLS
+#endif				/* _OSM_BASE_H_ */
diff --git a/include/opensm/osm_config.h.in b/include/opensm/osm_config.h.in
new file mode 100644
index 0000000..b12006f
--- /dev/null
+++ b/include/opensm/osm_config.h.in
@@ -0,0 +1,64 @@
+/* include/osm_config.h.in
+ *
+ * Defines various OpenSM configuration parameters to be used by various
+ * plugins and third party tools.
+ *
+ * NOTE: Defines used in header files MUST be included here to ensure plugin
+ * compatibility.
+ */
+
+#ifndef _OSM_CONFIG_H_
+#define _OSM_CONFIG_H_
+
+/* define 1 if OpenSM build is in a debug mode */
+#undef OSM_DEBUG
+
+/* Define as 1 if you want Dual Sided RMPP Support */
+#undef DUAL_SIDED_RMPP
+
+/* Define as 1 if you want to enable a console on a socket connection */
+#undef ENABLE_OSM_CONSOLE_SOCKET
+
+/* Define as 1 if you want to enable the event plugin */
+#undef ENABLE_OSM_DEFAULT_EVENT_PLUGIN
+
+/* Define as 1 if you want to enable the performance manager */
+#undef ENABLE_OSM_PERF_MGR
+
+/* Define as 1 if you want to enable the performance manager profiling code */
+#undef ENABLE_OSM_PERF_MGR_PROFILE
+
+/* Define a default node name map file */
+#undef HAVE_DEFAULT_NODENAME_MAP
+
+/* Define a default OpenSM config file */
+#undef HAVE_DEFAULT_OPENSM_CONFIG_FILE
+
+/* Define a Partition config file */
+#undef HAVE_DEFAULT_PARTITION_CONFIG_FILE
+
+/* Define a Prefix Routes config file */
+#undef HAVE_DEFAULT_PREFIX_ROUTES_FILE
+
+/* Define a QOS policy config file */
+#undef HAVE_DEFAULT_QOS_POLICY_FILE
+
+/* Define OpenSM config directory */
+#undef OPENSM_CONFIG_DIR
+
+/* Define as 1 for vapi vendor */
+#undef OSM_VENDOR_INTF_MTL
+
+/* Define as 1 for OpenIB vendor */
+#undef OSM_VENDOR_INTF_OPENIB
+
+/* Define as 1 for sim vendor */
+#undef OSM_VENDOR_INTF_SIM
+
+/* Define as 1 for ts vendor */
+#undef OSM_VENDOR_INTF_TS
+
+/* Define as 1 if you want Vendor RMPP Support */
+#undef VENDOR_RMPP_SUPPORT
+
+#endif /* _OSM_CONFIG_H_ */
diff --git a/include/opensm/osm_console.h b/include/opensm/osm_console.h
new file mode 100644
index 0000000..3ea8fa5
--- /dev/null
+++ b/include/opensm/osm_console.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005-2007 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_CONSOLE_H_
+#define _OSM_CONSOLE_H_
+
+#include <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
+// TODO replace p_osm
+void osm_console(osm_opensm_t * p_osm);
+END_C_DECLS
+#endif				/* _OSM_CONSOLE_H_ */
diff --git a/include/opensm/osm_console_io.h b/include/opensm/osm_console_io.h
new file mode 100644
index 0000000..5fe233d
--- /dev/null
+++ b/include/opensm/osm_console_io.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005-2007 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+/*
+ * Abstract:
+ * 	Declaration of osm_console_t.
+ *	This object represents the OpenSM Console object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_CONSOLE_IO_H_
+#define _OSM_CONSOLE_IO_H_
+
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#define OSM_DISABLE_CONSOLE      "off"
+#define OSM_LOCAL_CONSOLE        "local"
+#define OSM_REMOTE_CONSOLE       "socket"
+#define OSM_LOOPBACK_CONSOLE     "loopback"
+#define OSM_CONSOLE_NAME         "OSM Console"
+
+#define OSM_DEFAULT_CONSOLE      OSM_DISABLE_CONSOLE
+#define OSM_DEFAULT_CONSOLE_PORT 10000
+#define OSM_DAEMON_NAME          "opensm"
+
+#define OSM_COMMAND_PROMPT	 "$ "
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+typedef struct osm_console {
+	int socket;
+	int in_fd;
+	int out_fd;
+	int authorized;
+	FILE *in;
+	FILE *out;
+	char client_type[32];
+	char client_ip[64];
+	char client_hn[128];
+} osm_console_t;
+
+void osm_console_prompt(FILE * out);
+int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log);
+void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log);
+int is_console_enabled(osm_subn_opt_t *p_opt);
+
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log);
+int is_authorized(osm_console_t * p_oct);
+#endif
+
+END_C_DECLS
+#endif				/* _OSM_CONSOLE_IO_H_ */
diff --git a/include/opensm/osm_db.h b/include/opensm/osm_db.h
new file mode 100644
index 0000000..56bae31
--- /dev/null
+++ b/include/opensm/osm_db.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_DB_H_
+#define _OSM_DB_H_
+
+/*
+ * Abstract:
+ * Declaration of the DB interface.
+ */
+
+#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 persistent
+*  data, query, modify, delete and eventually commit it back to the
+*  persistent media.
+*
+*  The interface is defined such that it can is not "data dependent":
+*  All keys and data items are texts.
+*
+*	The DB implementation should be thread safe, thus callers do not need to
+*  provide serialization.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+/****s* OpenSM: Database/osm_db_domain_t
+* NAME
+*	osm_db_domain_t
+*
+* DESCRIPTION
+*	A domain of the database. Can be viewed as a database table.
+*
+*	The osm_db_domain_t object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_db_domain {
+	struct osm_db *p_db;
+	void *p_domain_imp;
+} osm_db_domain_t;
+/*
+* FIELDS
+*	p_db
+*		Pointer to the parent database object.
+*
+*	p_domain_imp
+*		Pointer to the db implementation object
+*
+* SEE ALSO
+* osm_db_t
+*********/
+
+/****s* OpenSM: Database/osm_db_t
+* NAME
+*	osm_db_t
+*
+* DESCRIPTION
+*	The main database object.
+*
+*	The osm_db_t object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_db {
+	void *p_db_imp;
+	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 construct
+*
+* RETURN VALUES
+*	NONE
+*
+* SEE ALSO
+*	Database, osm_db_init, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_destroy
+* NAME
+*	osm_db_destroy
+*
+* DESCRIPTION
+*	Destroys the osm_db_t structure.
+*
+* SYNOPSIS
+*/
+void osm_db_destroy(IN osm_db_t * 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_ */
diff --git a/include/opensm/osm_db_pack.h b/include/opensm/osm_db_pack.h
new file mode 100644
index 0000000..83861a6
--- /dev/null
+++ b/include/opensm/osm_db_pack.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/****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_ */
diff --git a/include/opensm/osm_errors.h b/include/opensm/osm_errors.h
new file mode 100644
index 0000000..aff4300
--- /dev/null
+++ b/include/opensm/osm_errors.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of error code ranges for the various OpenSM modules.
+ */
+
+#ifndef _OSM_ERRORS_H_
+#define _OSM_ERRORS_H_
+
+/*
+	Generic Request Controller
+	0100 - 01FF
+
+	Node Info Receive Controller
+	0200 - 02FF
+
+	Generic Requester
+	0300 - 03FF
+
+	Node Info Receiver
+	0400 - 04FF
+
+	Node Description Receiver
+	0500 - 05FF
+
+	Node Description Receive Controller
+	0600 - 06FF
+
+	Port Info Receiver
+	0700 - 07FF
+
+	Port Info Receive Controller
+	0800 - 08FF
+
+	Mad Pool
+	0900 - 09FF
+
+	SM
+	1000 - 10FF
+
+	SM MAD Controller
+	1100 - 11FF
+
+	VL15 Interface
+	1200 - 12FF
+
+	Switch Info Receive Controller
+	1300 - 13FF
+
+	Switch Info Receiver
+	1400 - 14FF
+
+	State Manager
+	1500 - 15FF
+
+	State Manager Controller
+	1600 - 16FF
+
+	LID Manager
+	1700 - 17FF
+
+	Link Manager
+	1800 - 18FF
+
+	Drop Manager
+	1900 - 19FF
+
+	Linear Forwarding Receive Controller
+	2000 - 20FF
+
+	Linear Forwarding Receiver
+	2100 - 21FF
+
+	Vendor Specific
+	2200 - 22FF
+
+	SMInfo Receive Controller
+	2300 - 23FF
+
+	SMInfo Info Receiver
+	2400 - 24FF
+
+	Generic Responder
+	2500 - 25FF
+
+	Linear Forwarding Receive Controller
+	2600 - 26FF
+
+	Linear Forwarding Receiver
+	2700 - 27FF
+
+	SA MAD controller
+	2800 - 28FF
+
+	Node Record Controller
+	2900 - 29FF
+
+	PortInfo Record Controller
+	3000 - 30FF
+
+	Link Record Controller
+	3100 - 31FF
+
+	Path Record Controller
+	3200 - 32FF
+
+	SMInfo Record Controller
+	3300 - 33FF
+
+	Multicast Record Controller
+	3400 - 34FF
+
+	Unicast Manager
+	3500 - 35FF
+
+	Multicast Manager
+	3600 - 36FF
+
+	SA Response
+	3700 - 37FF
+
+	Link Record Receiver
+	3800 - 38FF
+
+	Multicast Forwarding Receive Controller
+	3900 - 39FF
+
+	Multicast Forwarding Receiver
+	4000 - 40FF
+
+	SMInfo Record Receiver
+	4100 - 41FF
+
+	PortInfo Record Receiver
+	4200 - 42FF
+
+	Service Record Receiver
+	4300 - 43FF
+
+*/
+
+#endif				/* _OSM_ERRORS_H_ */
diff --git a/include/opensm/osm_event_plugin.h b/include/opensm/osm_event_plugin.h
new file mode 100644
index 0000000..0922c65
--- /dev/null
+++ b/include/opensm/osm_event_plugin.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 The Regents of the University of California.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_EVENT_PLUGIN_H_
+#define _OSM_EVENT_PLUGIN_H_
+
+#include <time.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_config.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 Event plugin interface
+* DESCRIPTION
+*       Database interface to record subnet events
+*
+*       Implementations of this object _MUST_ be thread safe.
+*
+* AUTHOR
+*	Ira Weiny, LLNL
+*
+*********/
+
+#define OSM_EPI_NODE_NAME_LEN (128)
+
+struct osm_opensm;
+/** =========================================================================
+ * Event types
+ */
+typedef enum {
+	OSM_EVENT_ID_PORT_ERRORS = 0,
+	OSM_EVENT_ID_PORT_DATA_COUNTERS,
+	OSM_EVENT_ID_PORT_SELECT,
+	OSM_EVENT_ID_TRAP,
+	OSM_EVENT_ID_SUBNET_UP,
+	OSM_EVENT_ID_MAX
+} osm_epi_event_id_t;
+
+typedef struct osm_epi_port_id {
+	uint64_t node_guid;
+	uint8_t port_num;
+	char node_name[OSM_EPI_NODE_NAME_LEN];
+} osm_epi_port_id_t;
+
+/** =========================================================================
+ * Port error event
+ * OSM_EVENT_ID_PORT_COUNTER
+ * This is a difference from the last reading.  NOT an absolute reading.
+ */
+typedef struct osm_epi_pe_event {
+	osm_epi_port_id_t port_id;
+	uint64_t symbol_err_cnt;
+	uint64_t link_err_recover;
+	uint64_t link_downed;
+	uint64_t rcv_err;
+	uint64_t rcv_rem_phys_err;
+	uint64_t rcv_switch_relay_err;
+	uint64_t xmit_discards;
+	uint64_t xmit_constraint_err;
+	uint64_t rcv_constraint_err;
+	uint64_t link_integrity;
+	uint64_t buffer_overrun;
+	uint64_t vl15_dropped;
+	time_t time_diff_s;
+} osm_epi_pe_event_t;
+
+/** =========================================================================
+ * Port data counter event
+ * This is a difference from the last reading.  NOT an absolute reading.
+ */
+typedef struct osm_epi_dc_event {
+	osm_epi_port_id_t port_id;
+	uint64_t xmit_data;
+	uint64_t rcv_data;
+	uint64_t xmit_pkts;
+	uint64_t rcv_pkts;
+	uint64_t unicast_xmit_pkts;
+	uint64_t unicast_rcv_pkts;
+	uint64_t multicast_xmit_pkts;
+	uint64_t multicast_rcv_pkts;
+	time_t time_diff_s;
+} osm_epi_dc_event_t;
+
+/** =========================================================================
+ * Port select event
+ * This is a difference from the last reading.  NOT an absolute reading.
+ */
+typedef struct osm_api_ps_event {
+	osm_epi_port_id_t port_id;
+	uint64_t xmit_wait;
+	time_t time_diff_s;
+} osm_epi_ps_event_t;
+
+/** =========================================================================
+ * Trap events
+ */
+typedef struct osm_epi_trap_event {
+	osm_epi_port_id_t port_id;
+	uint8_t type;
+	uint32_t prod_type;
+	uint16_t trap_num;
+	uint16_t issuer_lid;
+	time_t time;
+} osm_epi_trap_event_t;
+
+/** =========================================================================
+ * Plugin creators should allocate an object of this type
+ *    (named OSM_EVENT_PLUGIN_IMPL_NAME)
+ * The version should be set to OSM_EVENT_PLUGIN_INTERFACE_VER
+ */
+#define OSM_EVENT_PLUGIN_IMPL_NAME "osm_event_plugin"
+#define OSM_ORIG_EVENT_PLUGIN_INTERFACE_VER 1
+#define OSM_EVENT_PLUGIN_INTERFACE_VER 2
+typedef struct osm_event_plugin {
+	const char *osm_version;
+	void *(*create) (struct osm_opensm *osm);
+	void (*delete) (void *plugin_data);
+	void (*report) (void *plugin_data,
+			osm_epi_event_id_t event_id, void *event_data);
+} osm_event_plugin_t;
+
+/** =========================================================================
+ * The plugin structure should be considered opaque
+ */
+typedef struct osm_epi_plugin {
+	cl_list_item_t list;
+	void *handle;
+	osm_event_plugin_t *impl;
+	void *plugin_data;
+	char *plugin_name;
+} osm_epi_plugin_t;
+
+/**
+ * functions
+ */
+osm_epi_plugin_t *osm_epi_construct(struct osm_opensm *osm, char *plugin_name);
+void osm_epi_destroy(osm_epi_plugin_t * plugin);
+
+/** =========================================================================
+ * Helper functions
+ */
+static inline void
+osm_epi_create_port_id(osm_epi_port_id_t * port_id, uint64_t node_guid,
+		       uint8_t port_num, char *node_name)
+{
+	port_id->node_guid = node_guid;
+	port_id->port_num = port_num;
+	strncpy(port_id->node_name, node_name, OSM_EPI_NODE_NAME_LEN);
+	port_id->node_name[OSM_EPI_NODE_NAME_LEN - 1] = '\0';
+}
+
+END_C_DECLS
+#endif				/* _OSM_EVENT_PLUGIN_H_ */
diff --git a/include/opensm/osm_helper.h b/include/opensm/osm_helper.h
new file mode 100644
index 0000000..9222853
--- /dev/null
+++ b/include/opensm/osm_helper.h
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_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.
+ */
+/****f* OpenSM: Helper/ib_get_sa_method_str
+ * NAME
+ *	ib_get_sa_method_str
+ *
+ * DESCRIPTION
+ *	Returns a string for the specified SA Method value.
+ *
+ * SYNOPSIS
+ */
+const char *ib_get_sa_method_str(IN uint8_t method);
+/*
+ * PARAMETERS
+ *	method
+ *		[in] Network order METHOD ID value.
+ *
+ * RETURN VALUES
+ *	Pointer to the method string.
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Helper/ib_get_sm_method_str
+* NAME
+*	ib_get_sm_method_str
+*
+* DESCRIPTION
+*	Returns a string for the specified SM Method value.
+*
+* SYNOPSIS
+*/
+const char *ib_get_sm_method_str(IN uint8_t method);
+/*
+* PARAMETERS
+*	method
+*		[in] Network order METHOD ID value.
+*
+* RETURN VALUES
+*	Pointer to the method string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sm_attr_str
+* NAME
+*	ib_get_sm_attr_str
+*
+* DESCRIPTION
+*	Returns a string for the specified SM attribute value.
+*
+* SYNOPSIS
+*/
+const char *ib_get_sm_attr_str(IN ib_net16_t attr);
+/*
+* PARAMETERS
+*	attr
+*		[in] Network order attribute ID value.
+*
+* RETURN VALUES
+*	Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sa_attr_str
+* NAME
+*	ib_get_sa_attr_str
+*
+* DESCRIPTION
+*	Returns a string for the specified SA attribute value.
+*
+* SYNOPSIS
+*/
+const char *ib_get_sa_attr_str(IN ib_net16_t attr);
+/*
+* PARAMETERS
+*	attr
+*		[in] Network order attribute ID value.
+*
+* RETURN VALUES
+*	Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_trap_str
+* NAME
+*	ib_get_trap_str
+*
+* DESCRIPTION
+*	Returns a name for the specified trap.
+*
+* SYNOPSIS
+*/
+const char *ib_get_trap_str(uint16_t trap_num);
+/*
+* PARAMETERS
+*	trap_num
+*		[in] Network order trap number.
+*
+* RETURN VALUES
+*	Name of the trap.
+*
+*********/
+
+/****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_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 uint8_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_ */
diff --git a/include/opensm/osm_inform.h b/include/opensm/osm_inform.h
new file mode 100644
index 0000000..1528642
--- /dev/null
+++ b/include/opensm/osm_inform.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_inform_rec_t.
+ *	This object represents an IBA Inform Record.
+ *	This object is part of the OpenSM family of objects.
+ *
+ * Author:
+ *    Eitan Zahavi, Mellanox
+ */
+
+#ifndef _OSM_INFR_H_
+#define _OSM_INFR_H_
+
+#include <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.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 {
+	cl_list_item_t list_item;
+	osm_bind_handle_t h_bind;
+	osm_sa_t *sa;
+	osm_mad_addr_t report_addr;
+	ib_inform_info_record_t inform_record;
+} osm_infr_t;
+/*
+* FIELDS
+*	list_item
+*		List Item for qlist linkage.  Must be first element!!
+*
+*	h_bind
+*		A handle of lower level mad srvc
+*
+*	sa
+*		A pointer to osm_sa object
+*
+*	report_addr
+*		Report address
+*
+*	inform_record
+*		The Inform Info Record
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_new
+* NAME
+*	osm_infr_new
+*
+* DESCRIPTION
+*	Allocates and initializes a Inform Record for use.
+*
+* SYNOPSIS
+*/
+osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec);
+/*
+* PARAMETERS
+*	p_inf_rec
+*		[in] Pointer to IB Inform Record
+*
+* RETURN VALUES
+*	pointer to osm_infr_t structure.
+*
+* NOTES
+*	Allows calling other inform record methods.
+*
+* SEE ALSO
+*	Inform Record, osm_infr_delete
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_delete
+* NAME
+*	osm_infr_delete
+*
+* DESCRIPTION
+*	Destroys and deallocates the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void osm_infr_delete(IN osm_infr_t * const p_infr);
+/*
+* PARAMETERS
+*	p_infr
+*		[in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+*	Inform Record, osm_infr_new
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_get_by_rec
+* NAME
+*	osm_infr_get_by_rec
+*
+* DESCRIPTION
+*	Find a matching osm_infr_t in the subnet DB by inform_info_record
+*
+* SYNOPSIS
+*/
+osm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn,
+				IN osm_log_t * p_log,
+				IN osm_infr_t * 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_new, osm_infr_delete
+*********/
+
+void
+osm_infr_insert_to_db(IN osm_subn_t * p_subn,
+		      IN osm_log_t * p_log, IN osm_infr_t * p_infr);
+
+void
+osm_infr_remove_from_db(IN osm_subn_t * p_subn,
+			IN osm_log_t * p_log, IN osm_infr_t * p_infr);
+
+/****f* OpenSM: Inform Record/osm_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_ */
diff --git a/include/opensm/osm_lid_mgr.h b/include/opensm/osm_lid_mgr.h
new file mode 100644
index 0000000..714ba41
--- /dev/null
+++ b/include/opensm/osm_lid_mgr.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_lid_mgr_t.
+ *	This object represents the LID Manager object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_LID_MGR_H_
+#define _OSM_LID_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.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
+*
+*********/
+struct osm_sm;
+/****s* OpenSM: LID Manager/osm_lid_mgr_t
+* NAME
+*	osm_lid_mgr_t
+*
+* DESCRIPTION
+*	LID Manager structure.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_lid_mgr {
+	struct osm_sm *sm;
+	osm_subn_t *p_subn;
+	osm_db_t *p_db;
+	osm_log_t *p_log;
+	cl_plock_t *p_lock;
+	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
+*	sm
+*		Pointer to the SM object.
+*
+*	p_subn
+*		Pointer to the Subnet object for this subnet.
+*
+*	p_db
+*		Pointer to the database (persistency) object
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	p_lock
+*		Pointer to the serializing lock.
+*
+*	send_set_reqs
+*		Boolean to indicate whether any set requests sent.
+*
+*	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 struct osm_sm * sm);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to an osm_lid_mgr_t object to initialize.
+*
+*	sm
+*		[in] Pointer to the SM object for this subnet.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the LID Manager object was initialized
+*	successfully.
+*
+* NOTES
+*	Allows calling other LID Manager methods.
+*
+* SEE ALSO
+*	LID Manager object, osm_lid_mgr_construct,
+*	osm_lid_mgr_destroy
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_process_sm
+* NAME
+*	osm_lid_mgr_process_sm
+*
+* DESCRIPTION
+*	Configures the SM's port with its designated LID values.
+*
+* SYNOPSIS
+*/
+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_ */
diff --git a/include/opensm/osm_log.h b/include/opensm/osm_log.h
new file mode 100644
index 0000000..20999d9
--- /dev/null
+++ b/include/opensm/osm_log.h
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_log_t.
+ *	This object represents the log file.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_LOG_H_
+#define _OSM_LOG_H_
+
+#ifndef __WIN__
+#include <syslog.h>
+#endif
+#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 ) \
+	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_ALL	0x7f
+#define OSM_LOG_SYS	0x80
+
+/*
+	DEFAULT - turn on ERROR and INFO only
+*/
+#define OSM_LOG_DEFAULT_LEVEL		OSM_LOG_ERROR | OSM_LOG_INFO
+
+/****s* OpenSM: 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;
+	boolean_t accum_log_file;
+	boolean_t daemon;
+	char *log_file_name;
+} 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_reopen_file
+* NAME
+*	osm_log_reopen_file
+*
+* DESCRIPTION
+*	The osm_log_reopen_file function reopens the log file
+*
+* SYNOPSIS
+*/
+int osm_log_reopen_file(osm_log_t * p_log);
+/*
+* PARAMETERS
+*	p_log
+*		[in] Pointer to the log object.
+*
+* RETURN VALUES
+*	0 on success or nonzero value otherwise.
+*********/
+
+/****f* OpenSM: Log/osm_log_init
+* NAME
+*	osm_log_init
+*
+* DESCRIPTION
+*	The osm_log_init function initializes a
+*	Log object for use. It is a wrapper for osm_log_init_v2().
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_log_init(IN osm_log_t * 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
+ */
+
+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;
+
+/****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;
+	osm_log(p_log, OSM_LOG_ALL, "Setting log level to: 0x%02x\n", level);
+}
+
+/*
+* PARAMETERS
+*	p_log
+*		[in] Pointer to the log object.
+*
+*	level
+*		[in] New level to set.
+*
+* RETURN VALUES
+*	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 void osm_log_msg_box(osm_log_t *log, osm_log_level_t level,
+			    const char *func_name, const char *msg);
+extern void osm_log_raw(IN osm_log_t * const p_log,
+	    IN const osm_log_level_t verbosity, IN const char *p_buf);
+
+#define OSM_LOG(log, level, fmt, arg...) do { \
+		if (osm_log_is_active(log, (level))) \
+			osm_log(log, level, "%s: " fmt, __func__, ##arg); \
+	} while (0)
+
+#define OSM_LOG_MSG_BOX(log, level, msg) \
+		osm_log_msg_box(log, level, __func__, msg)
+
+#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_ */
diff --git a/include/opensm/osm_mad_pool.h b/include/opensm/osm_mad_pool.h
new file mode 100644
index 0000000..0aa5b46
--- /dev/null
+++ b/include/opensm/osm_mad_pool.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mad_pool_t.
+ *	This object represents a pool of management datagram (MAD) objects.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MAD_POOL_H_
+#define _OSM_MAD_POOL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_atomic.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.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
+/****h* OpenSM/MAD Pool
+* NAME
+*	MAD Pool
+*
+* DESCRIPTION
+*	The MAD Pool encapsulates the information needed by the
+*	OpenSM to manage a pool of MAD objects.  The OpenSM allocates
+*	one MAD Pool per IBA subnet.
+*
+*	The MAD Pool is thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: MAD Pool/osm_mad_pool_t
+* NAME
+*	osm_mad_pool_t
+*
+* DESCRIPTION
+*	MAD Pool structure.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_mad_pool {
+	atomic32_t mads_out;
+} osm_mad_pool_t;
+/*
+* FIELDS
+*	mads_out
+*		Running total of the number of MADs outstanding.
+*
+* SEE ALSO
+*	MAD Pool
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_construct
+* NAME
+*	osm_mad_pool_construct
+*
+* DESCRIPTION
+*	This function constructs a MAD Pool.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_construct(IN osm_mad_pool_t * 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);
+/*
+* PARAMETERS
+*	p_pool
+*		[in] Pointer to an osm_mad_pool_t object to initialize.
+*
+* RETURN VALUES
+*	CL_SUCCESS if the MAD Pool was initialized successfully.
+*
+* NOTES
+*	Allows calling other MAD Pool methods.
+*
+* SEE ALSO
+*	MAD Pool, osm_mad_pool_construct, osm_mad_pool_destroy
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get
+* NAME
+*	osm_mad_pool_get
+*
+* DESCRIPTION
+*	Gets a MAD wrapper and wire MAD from the pool.
+*
+* SYNOPSIS
+*/
+osm_madw_t *osm_mad_pool_get(IN osm_mad_pool_t * 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_ */
diff --git a/include/opensm/osm_madw.h b/include/opensm/osm_madw.h
new file mode 100644
index 0000000..f47142d
--- /dev/null
+++ b/include/opensm/osm_madw.h
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mad_wrapper_t.
+ *	This object represents the context wrapper for OpenSM MAD processing.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MADW_H_
+#define _OSM_MADW_H_
+
+#include <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
+*
+*	mad_class
+*		Mgmt Class ID
+*
+*	class_version
+*		Mgmt Class version
+*
+*	is_responder
+*		True if this is a GSI Agent
+*
+*	is_trap_processor
+*		True if GSI Trap msgs are handled
+*
+*	is_report_processor
+*		True if GSI Report msgs are handled
+*
+*	send_q_size
+*		SendQueueSize
+*
+*	recv_q_size
+*		Receive Queue Size
+*
+* SEE ALSO
+*********/
+
+/****h* OpenSM/MAD Wrapper
+* NAME
+*	MAD Wrapper
+*
+* DESCRIPTION
+*	The MAD Wrapper object encapsulates the information needed by the
+*	OpenSM to manage individual MADs.  The OpenSM allocates one MAD Wrapper
+*	per MAD.
+*
+*	The MAD Wrapper is not thread safe, thus callers must provide
+*	serialization.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_ni_context_t
+* NAME
+*	osm_ni_context_t
+*
+* DESCRIPTION
+*	Context needed by recipient of NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct osm_ni_context {
+	ib_net64_t node_guid;
+	uint8_t port_num;
+	ib_net64_t dup_node_guid;
+	uint8_t dup_port_num;
+	unsigned dup_count;
+} osm_ni_context_t;
+/*
+* FIELDS
+*	p_node
+*		Pointer to the node thru which we got to this node.
+*
+*	p_sw
+*		Pointer to the switch object (if any) of the switch
+*		thru which we got to this node.
+*
+*	port_num
+*		Port number on the node or switch thru which we got
+*		to this node.
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_pi_context_t
+* NAME
+*	osm_pi_context_t
+*
+* DESCRIPTION
+*	Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct osm_pi_context {
+	ib_net64_t node_guid;
+	ib_net64_t port_guid;
+	boolean_t set_method;
+	boolean_t light_sweep;
+	boolean_t active_transition;
+} 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;
+	boolean_t light_sweep;
+} osm_smi_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_pkey_context_t
+* NAME
+*	osm_pkey_context_t
+*
+* DESCRIPTION
+*	Context needed by recipient of P_Key attribute.
+*
+* SYNOPSIS
+*/
+typedef struct osm_pkey_context {
+	ib_net64_t node_guid;
+	ib_net64_t port_guid;
+	boolean_t set_method;
+} osm_pkey_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_slvl_context_t
+* NAME
+*	osm_slvl_context_t
+*
+* DESCRIPTION
+*	Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct osm_slvl_context {
+	ib_net64_t node_guid;
+	ib_net64_t port_guid;
+	boolean_t set_method;
+} osm_slvl_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_vla_context_t
+* NAME
+*	osm_vla_context_t
+*
+* DESCRIPTION
+*	Context needed by recipient of VL Arb attribute.
+*
+* SYNOPSIS
+*/
+typedef struct osm_vla_context {
+	ib_net64_t node_guid;
+	ib_net64_t port_guid;
+	boolean_t set_method;
+} osm_vla_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_perfmgr_context_t
+* DESCRIPTION
+*	Context for Performance manager queries
+*/
+typedef struct osm_perfmgr_context {
+	uint64_t node_guid;
+	uint16_t port;
+	uint8_t mad_method;	/* was this a get or a set */
+#if ENABLE_OSM_PERF_MGR_PROFILE
+	struct timeval query_start;
+#endif
+} osm_perfmgr_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;
+	osm_perfmgr_context_t perfmgr_context;
+#ifndef OSM_VENDOR_INTF_OPENIB
+	osm_arbitrary_context_t arb_context;
+#endif
+} osm_madw_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_mad_addr_t
+* NAME
+*   osm_mad_addr_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct osm_mad_addr {
+	ib_net16_t dest_lid;
+	uint8_t path_bits;
+	uint8_t static_rate;
+	union addr_type {
+		struct _smi {
+			ib_net16_t source_lid;
+			uint8_t port_num;
+		} smi;
+
+		struct _gsi {
+			ib_net32_t remote_qp;
+			ib_net32_t remote_qkey;
+			uint16_t pkey_ix;
+			uint8_t service_level;
+			boolean_t global_route;
+			ib_grh_t grh_info;
+		} gsi;
+	} addr_type;
+} osm_mad_addr_t;
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_madw_t
+* NAME
+*	osm_madw_t
+*
+* DESCRIPTION
+*	Context needed for processing individual MADs
+*
+* SYNOPSIS
+*/
+typedef struct osm_madw {
+	cl_list_item_t list_item;
+	osm_bind_handle_t h_bind;
+	osm_vend_wrap_t vend_wrap;
+	osm_mad_addr_t mad_addr;
+	osm_bind_info_t bind_info;
+	osm_madw_context_t context;
+	uint32_t mad_size;
+	ib_api_status_t status;
+	cl_disp_msgid_t fail_msg;
+	boolean_t resp_expected;
+	const ib_mad_t *p_mad;
+} osm_madw_t;
+/*
+* FIELDS
+*	list_item
+*		List linkage for lists.  MUST BE FIRST MEMBER!
+*
+*	h_bind
+*		Bind handle for the port on which this MAD will be sent
+*		or was received.
+*
+*	vend_wrap
+*		Transport vendor specific context.  This structure is not
+*		used outside MAD transport vendor specific code.
+*
+*	context
+*		Union of controller specific contexts needed for this MAD.
+*		This structure allows controllers to indirectly communicate
+*		with each other through the dispatcher.
+*
+*	mad_size
+*		Size of this MAD in bytes.
+*
+*	status
+*		Status of completed operation on the MAD.
+*		CL_SUCCESS if the operation was successful.
+*
+*	fail_msg
+*		Dispatcher message with which to post this MAD on failure.
+*		This value is set by the originator of the MAD.
+*		If an operation on this MAD fails, for example due to a timeout,
+*		then the transport layer will dispose of the MAD by sending
+*		it through the Dispatcher with this message type.  Presumably,
+*		there is a controller listening for the failure message that can
+*		properly clean up.
+*
+*	resp_expected
+*		TRUE if a response is expected to this MAD.
+*		FALSE otherwise.
+*
+*	p_mad
+*		Pointer to the wire MAD.  The MAD itself cannot be part of the
+*		wrapper, since wire MADs typically reside in special memory
+*		registered with the local HCA.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_init
+* NAME
+*	osm_madw_init
+*
+* DESCRIPTION
+*	Initializes a MAD Wrapper object for use.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_init(IN osm_madw_t * 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)
+{
+	memset(p_madw, 0, sizeof(*p_madw));
+	p_madw->h_bind = h_bind;
+	p_madw->fail_msg = CL_DISP_MSGID_NONE;
+	p_madw->mad_size = mad_size;
+	if (p_mad_addr)
+		p_madw->mad_addr = *p_mad_addr;
+	p_madw->resp_expected = FALSE;
+}
+
+/*
+* PARAMETERS
+*	p_madw
+*		[in] Pointer to an osm_madw_t object to initialize.
+*
+*	h_bind
+*		[in] Pointer to the wire MAD.
+*
+*	p_mad_addr
+*		[in] Pointer to the MAD address structure.  This parameter may
+*		be NULL for directed route MADs.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_smp_ptr
+* NAME
+*	osm_madw_get_smp_ptr
+*
+* DESCRIPTION
+*	Gets a pointer to the SMP in this MAD.
+*
+* SYNOPSIS
+*/
+static inline ib_smp_t *osm_madw_get_smp_ptr(IN const osm_madw_t * 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
+*********/
+
+/****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.
+*
+* RETURN VALUES
+*	Pointer to the start of the SA MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*	MAD Wrapper object
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_perfmgt_mad_ptr
+* DESCRIPTION
+*	Gets a pointer to the PerfMgt MAD in this MAD wrapper.
+*
+* SYNOPSIS
+*/
+static inline ib_perfmgt_mad_t *osm_madw_get_perfmgt_mad_ptr(IN const osm_madw_t
+							     * const p_madw)
+{
+	return ((ib_perfmgt_mad_t *) p_madw->p_mad);
+}
+
+/*
+* PARAMETERS
+*	p_madw
+*		[in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*	Pointer to the start of the PerfMgt MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*	MAD Wrapper object
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_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_ */
diff --git a/include/opensm/osm_mcast_tbl.h b/include/opensm/osm_mcast_tbl.h
new file mode 100644
index 0000000..15b95cf
--- /dev/null
+++ b/include/opensm/osm_mcast_tbl.h
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mcast_tbl_t.
+ *	This object represents a multicast forwarding table.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MCAST_TBL_H_
+#define _OSM_MCAST_TBL_H_
+
+#include <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_fwdbl {
+	uint8_t num_ports;
+	uint8_t max_position;
+	uint16_t max_block;
+	int16_t max_block_in_use;
+	uint16_t num_entries;
+	uint16_t max_mlid_ho;
+	uint16_t(*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_ */
diff --git a/include/opensm/osm_mcm_info.h b/include/opensm/osm_mcm_info.h
new file mode 100644
index 0000000..dec607f
--- /dev/null
+++ b/include/opensm/osm_mcm_info.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mcm_info_t.
+ *	This object represents a Multicast Forwarding Information object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#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 node's 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_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_ */
diff --git a/include/opensm/osm_mcm_port.h b/include/opensm/osm_mcm_port.h
new file mode 100644
index 0000000..c2b18de
--- /dev/null
+++ b/include/opensm/osm_mcm_port.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mcm_port_t.
+ *	This object represents the membership of a port in a multicast group.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MCM_PORT_H_
+#define _OSM_MCM_PORT_H_
+
+#include <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_new
+* NAME
+*	osm_mcm_port_new
+*
+* DESCRIPTION
+*	The osm_mcm_port_new function allocates and initializes a
+*	MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t *osm_mcm_port_new(IN 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_delete,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_delete
+* NAME
+*	osm_mcm_port_delete
+*
+* DESCRIPTION
+*	The osm_mcm_port_delete function destroys and dellallocates an
+*	MCM Port Object, releasing all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcm_port_delete(IN osm_mcm_port_t * 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_new
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_MCM_PORT_H_ */
diff --git a/include/opensm/osm_msgdef.h b/include/opensm/osm_msgdef.h
new file mode 100644
index 0000000..dbf3e53
--- /dev/null
+++ b/include/opensm/osm_msgdef.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of Dispatcher message values.
+ */
+
+#ifndef _OSM_MSGDEF_H_
+#define _OSM_MSGDEF_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* OpenSM/Dispatcher Messages
+* NAME
+*	Dispatcher Messages
+*
+* DESCRIPTION
+*	These constants define the messages sent between OpenSM controllers
+*	attached to the Dispatcher.
+*
+*	Each message description contains the following information:
+*	Sent by: which controller(s) send this message
+*	Received by: which controller receives this message
+*	Delivery notice: Indicates if the sender requires confirmation
+*		that the message has been delivered.  Typically a "yes" here
+*		means that some resources associated with sending the
+*		message must be freed.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_INFO
+* NAME
+*	OSM_MSG_MAD_NODE_INFO
+*
+* DESCRIPTION
+*	Message for received NodeInfo MADs.
+*
+* NOTES
+*	Sent by:			osm_mad_ctrl_t
+*	Received by:			osm_ni_rcv_ctrl_t
+*	Delivery notice:		yes
+*
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_PORT_INFO
+* NAME
+*	OSM_MSG_MAD_PORT_INFO
+*
+* DESCRIPTION
+*	Message for received PortInfo MADs.
+*
+* NOTES
+*	Sent by:			osm_mad_ctrl_t
+*	Received by:			osm_pi_rcv_ctrl_t
+*	Delivery notice:		yes
+*
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_SWITCH_INFO
+* NAME
+*	OSM_MSG_MAD_SWITCH_INFO
+*
+* DESCRIPTION
+*	Message for received SwitchInfo MADs.
+*
+* NOTES
+*	Sent by:			osm_mad_ctrl_t
+*	Received by:			osm_si_rcv_ctrl_t
+*	Delivery notice:		yes
+*
+***********/
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_DESC
+* NAME
+*	OSM_MSG_MAD_NODE_DESC
+*
+* DESCRIPTION
+*	Message for received NodeDescription MADs.
+*
+* NOTES
+*	Sent by:			osm_mad_ctrl_t
+*	Received by:			osm_nd_rcv_ctrl_t
+*	Delivery notice:		yes
+*
+* SOURCE
+***********/
+enum {
+	OSM_MSG_NONE = 0,
+	OSM_MSG_MAD_NODE_INFO,
+	OSM_MSG_MAD_PORT_INFO,
+	OSM_MSG_MAD_SWITCH_INFO,
+	OSM_MSG_MAD_NODE_DESC,
+	OSM_MSG_MAD_NODE_RECORD,
+	OSM_MSG_MAD_PORTINFO_RECORD,
+	OSM_MSG_MAD_SERVICE_RECORD,
+	OSM_MSG_MAD_PATH_RECORD,
+	OSM_MSG_MAD_MCMEMBER_RECORD,
+	OSM_MSG_MAD_LINK_RECORD,
+	OSM_MSG_MAD_SMINFO_RECORD,
+	OSM_MSG_MAD_CLASS_PORT_INFO,
+	OSM_MSG_MAD_INFORM_INFO,
+	OSM_MSG_MAD_LFT_RECORD,
+	OSM_MSG_MAD_LFT,
+	OSM_MSG_MAD_SM_INFO,
+	OSM_MSG_MAD_NOTICE,
+	OSM_MSG_LIGHT_SWEEP_FAIL,
+	OSM_MSG_MAD_MFT,
+	OSM_MSG_MAD_PKEY_TBL_RECORD,
+	OSM_MSG_MAD_VL_ARB_RECORD,
+	OSM_MSG_MAD_SLVL_TBL_RECORD,
+	OSM_MSG_MAD_PKEY,
+	OSM_MSG_MAD_VL_ARB,
+	OSM_MSG_MAD_SLVL,
+	OSM_MSG_MAD_GUIDINFO_RECORD,
+	OSM_MSG_MAD_INFORM_INFO_RECORD,
+	OSM_MSG_MAD_SWITCH_INFO_RECORD,
+	OSM_MSG_MAD_MFT_RECORD,
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	OSM_MSG_MAD_MULTIPATH_RECORD,
+#endif
+	OSM_MSG_MAD_PORT_COUNTERS,
+	OSM_MSG_MAX
+};
+
+END_C_DECLS
+#endif				/* _OSM_MSGDEF_H_ */
diff --git a/include/opensm/osm_mtree.h b/include/opensm/osm_mtree.h
new file mode 100644
index 0000000..ef696da
--- /dev/null
+++ b/include/opensm/osm_mtree.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mtree_t.
+ *	This object represents multicast spanning tree.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MTREE_H_
+#define _OSM_MTREE_H_
+
+#include <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_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_ */
diff --git a/include/opensm/osm_multicast.h b/include/opensm/osm_multicast.h
new file mode 100644
index 0000000..bd219d1
--- /dev/null
+++ b/include/opensm/osm_multicast.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mgrp_t.
+ *	This object represents an IBA Multicast Group.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_MULTICAST_H_
+#define _OSM_MULTICAST_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_qlist.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
+*
+*********/
+/****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 {
+	cl_list_item_t list_item;
+	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;
+	unsigned full_members;
+} 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
+*		Holds the parameters of the Multicast Group.
+*
+*	well_known
+*		Indicates that this is the wellknown multicast group which
+*		is created during the initialization of SM/SA and will be
+*		present even if there are no ports for this group
+*
+*	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_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_delete
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_delete
+* NAME
+*	osm_mgrp_delete
+*
+* DESCRIPTION
+*	Destroys and deallocates 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_new
+*********/
+
+/****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(osm_subn_t *subn, osm_log_t *log,
+				  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_delete_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
+*********/
+
+int osm_mgrp_remove_port(osm_subn_t *subn, osm_log_t *log, osm_mgrp_t *mgrp,
+			 osm_mcm_port_t *mcm, uint8_t join_state);
+
+/****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
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_MULTICAST_H_ */
diff --git a/include/opensm/osm_node.h b/include/opensm/osm_node.h
new file mode 100644
index 0000000..50b3598
--- /dev/null
+++ b/include/opensm/osm_node.h
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_node_t.
+ *	This object represents an IBA node.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_NODE_H_
+#define _OSM_NODE_H_
+
+#include <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;
+	char *print_desc;
+	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.
+*
+*	print_desc
+*		A printable version of the node description.
+*
+*	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_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_get_physp_ptr
+* NAME
+*	osm_node_get_physp_ptr
+*
+* DESCRIPTION
+*	Returns a pointer to the physical port object at the
+*	specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t *osm_node_get_physp_ptr(IN osm_node_t * const p_node,
+						  IN const uint32_t port_num)
+{
+
+	CL_ASSERT(port_num < p_node->physp_tbl_size);
+	return osm_physp_is_valid(&p_node->physp_table[port_num]) ?
+		&p_node->physp_table[port_num] : NULL;
+}
+
+/*
+* PARAMETERS
+*	p_node
+*		[in] Pointer to an osm_node_t object.
+*
+*	port_num
+*		[in] Local port number.
+*
+* RETURN VALUES
+*	Returns a pointer to the physical port object at the
+*	specified local port number.
+*	A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+*	Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_type
+* NAME
+*	osm_node_get_type
+*
+* DESCRIPTION
+*	Returns the type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t osm_node_get_type(IN const osm_node_t * 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 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 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_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_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_ */
diff --git a/include/opensm/osm_opensm.h b/include/opensm/osm_opensm.h
new file mode 100644
index 0000000..c121be4
--- /dev/null
+++ b/include/opensm/osm_opensm.h
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_opensm_t.
+ *	This object represents the OpenSM super object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_OPENSM_H_
+#define _OSM_OPENSM_H_
+
+#include <stdio.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_atomic.h>
+#include <complib/cl_nodenamemap.h>
+#include <opensm/osm_console_io.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_event_plugin.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
+*
+*********/
+/****d* OpenSM: OpenSM/osm_routing_engine_type_t
+* NAME
+*       osm_routing_engine_type_t
+*
+* DESCRIPTION
+*       Enumerates the possible routing engines that
+*       could be used to route a subnet.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_routing_engine_type {
+	OSM_ROUTING_ENGINE_TYPE_NONE = 0,
+	OSM_ROUTING_ENGINE_TYPE_MINHOP,
+	OSM_ROUTING_ENGINE_TYPE_UPDN,
+	OSM_ROUTING_ENGINE_TYPE_FILE,
+	OSM_ROUTING_ENGINE_TYPE_FTREE,
+	OSM_ROUTING_ENGINE_TYPE_LASH,
+	OSM_ROUTING_ENGINE_TYPE_DOR,
+	OSM_ROUTING_ENGINE_TYPE_UNKNOWN
+} osm_routing_engine_type_t;
+/***********/
+
+/****s* OpenSM: OpenSM/osm_routing_engine
+* NAME
+*	struct osm_routing_engine
+*
+* DESCRIPTION
+*	OpenSM routing engine module definition.
+* NOTES
+*	routing engine structure - multicast callbacks may be
+*	added later.
+*/
+struct osm_routing_engine {
+	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);
+	struct osm_routing_engine *next;
+};
+/*
+* FIELDS
+*	name
+*		The routing engine name (will be used in logs).
+*
+*	context
+*		The routing engine context. Will be passed as parameter
+*		to the callback functions.
+*
+*	build_lid_matrices
+*		The callback for lid matrices generation.
+*
+*	ucast_build_fwd_tables
+*		The callback for unicast forwarding table generation.
+*
+*	ucast_dump_tables
+*		The callback for dumping unicast routing tables.
+*
+*	delete
+*		The delete method, may be used for routing engine
+*		internals cleanup.
+*
+*	next
+*		Pointer to next routing engine in the list.
+*/
+
+/****s* OpenSM: OpenSM/osm_opensm_t
+* NAME
+*	osm_opensm_t
+*
+* DESCRIPTION
+*	OpenSM structure.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_opensm {
+	const char *osm_version;
+	osm_subn_t subn;
+	osm_sm_t sm;
+	osm_sa_t sa;
+#ifdef ENABLE_OSM_PERF_MGR
+	osm_perfmgr_t perfmgr;
+#endif				/* ENABLE_OSM_PERF_MGR */
+	cl_qlist_t plugin_list;
+	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_list;
+	osm_routing_engine_type_t routing_engine_used;
+	osm_stats_t stats;
+	osm_console_t console;
+	nn_map_t *node_name_map;
+} osm_opensm_t;
+/*
+* FIELDS
+* 	osm_version
+* 		OpenSM version (as generated in osm_version.h)
+*
+*	subn
+*		Subnet object for this subnet.
+*
+*	sm
+*		The Subnet Manager (SM) object for this subnet.
+*
+*	sa
+*		The Subnet Administration (SA) object for this subnet.
+*
+*	db
+*		Persistant storage of some data required between sessions.
+*
+*	mad_pool
+*		Pool of Management Datagram (MAD) objects.
+*
+*	p_vendor
+*		Pointer to the Vendor specific adapter for various
+*		transport interfaces, such as UMADT, AL, etc.  The
+*		particular interface is set at compile time.
+*
+*	vl15
+*		The VL15 interface.
+*
+*	log
+*		Log facility used by all OpenSM components.
+*
+*	disp
+*		Central dispatcher containing the OpenSM worker threads.
+*
+*	lock
+*		Shared lock guarding most OpenSM structures.
+*
+*	routing_engine_list
+*		List of routing engines that should be tried for use.
+*
+*	routing_engine_used
+*		Indicates which routing engine was used to route a subnet.
+*
+*	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
+*********/
+
+/****f* OpenSM: OpenSM/osm_routing_engine_type_str
+* NAME
+*	osm_routing_engine_type_str
+*
+* DESCRIPTION
+*	Returns a string for the specified routing engine type.
+*
+* SYNOPSIS
+*/
+const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type);
+/*
+* PARAMETERS
+*	type
+*		[in] routing engine type.
+*
+* RETURN VALUES
+*	Pointer to routing engine name.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_routing_engine_type
+* NAME
+*	osm_routing_engine_type
+*
+* DESCRIPTION
+*	Returns a routing engine type specified routing engine name string.
+*
+* SYNOPSIS
+*/
+osm_routing_engine_type_t osm_routing_engine_type(IN const char *str);
+/*
+* PARAMETERS
+*	str
+*		[in] routing engine name string.
+*
+* RETURN VALUES
+*	Routing engine type.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id,
+			     void *event_data);
+
+/* dump helpers */
+void osm_dump_mcast_routes(osm_opensm_t * osm);
+void osm_dump_all(osm_opensm_t * osm);
+void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name,
+			   cl_qmap_t * map,
+			   void (*func) (cl_map_item_t *, FILE *, void *),
+			   void *cxt);
+
+/****v* OpenSM/osm_exit_flag
+*/
+extern volatile unsigned int osm_exit_flag;
+/*
+* DESCRIPTION
+*  Set to one to cause all threads to leave
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_OPENSM_H_ */
diff --git a/include/opensm/osm_partition.h b/include/opensm/osm_partition.h
new file mode 100644
index 0000000..38acdc9
--- /dev/null
+++ b/include/opensm/osm_partition.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_prtn_t.
+ *	This object represents an IBA Partition.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_PARTITION_H_
+#define _OSM_PARTITION_H_
+
+#include <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;
+	ib_net16_t pkey;
+	ib_net16_t mlid;
+	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.
+*
+*	mlid
+*		The network ordered LID of the well known Multicast Group
+*		that was created for 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
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_find_by_name
+* NAME
+*	osm_prtn_find_by_name
+*
+* DESCRIPTION
+* 	Fides partition by name.
+*
+* SYNOPSIS
+*/
+osm_prtn_t *osm_prtn_find_by_name(IN osm_subn_t * p_subn, IN const char *name);
+/*
+* PARAMETERS
+*	p_subn
+*		[in] Pointer to a subnet object.
+*
+*	name
+*		[in] Required partition name.
+*
+* RETURN VALUES
+*	Pointer to the partition object on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_PARTITION_H_ */
diff --git a/include/opensm/osm_path.h b/include/opensm/osm_path.h
new file mode 100644
index 0000000..8d65d2c
--- /dev/null
+++ b/include/opensm/osm_path.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_PATH_H_
+#define _OSM_PATH_H_
+
+#include <string.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor_api.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.
+ */
+/****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_ */
diff --git a/include/opensm/osm_perfmgr.h b/include/opensm/osm_perfmgr.h
new file mode 100644
index 0000000..d48d2ee
--- /dev/null
+++ b/include/opensm/osm_perfmgr.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2007 The Regents of the University of California.
+ * Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_PERFMGR_H_
+#define _OSM_PERFMGR_H_
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#ifdef ENABLE_OSM_PERF_MGR
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_perfmgr_db.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_event_plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+/****h* OpenSM/PerfMgr
+* NAME
+*	PerfMgr
+*
+* DESCRIPTION
+*       Performance manager thread which takes care of polling the fabric for
+*       Port counters values.
+*
+*	The PerfMgr object is thread safe.
+*
+* AUTHOR
+*	Ira Weiny, LLNL
+*
+*********/
+
+#define OSM_PERFMGR_DEFAULT_SWEEP_TIME_S 180
+#define OSM_PERFMGR_DEFAULT_DUMP_FILE "opensm_port_counters.log"
+#define OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES 500
+
+/****s* OpenSM: PerfMgr/osm_perfmgr_state_t */
+typedef enum {
+	PERFMGR_STATE_DISABLE,
+	PERFMGR_STATE_ENABLED,
+	PERFMGR_STATE_NO_DB
+} osm_perfmgr_state_t;
+
+/****s* OpenSM: PerfMgr/osm_perfmgr_sweep_state_t */
+typedef enum {
+	PERFMGR_SWEEP_SLEEP,
+	PERFMGR_SWEEP_ACTIVE,
+	PERFMGR_SWEEP_SUSPENDED
+} osm_perfmgr_sweep_state_t;
+
+/* Redirection information */
+typedef struct redir {
+	ib_net16_t redir_lid;
+	ib_net32_t redir_qp;
+} redir_t;
+
+/* Node to store information about which nodes we are monitoring */
+typedef struct _monitored_node {
+	cl_map_item_t map_item;
+	struct _monitored_node *next;
+	uint64_t guid;
+	char *name;
+	uint32_t redir_tbl_size;
+	redir_t redir_port[1];	/* redirection on a per port basis */
+} __monitored_node_t;
+
+struct osm_opensm;
+/****s* OpenSM: PerfMgr/osm_perfmgr_t
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*/
+typedef struct osm_perfmgr {
+	cl_event_t sig_sweep;
+	cl_timer_t sweep_timer;
+	struct osm_opensm *osm;
+	osm_subn_t *subn;
+	osm_sm_t *sm;
+	cl_plock_t *lock;
+	osm_log_t *log;
+	osm_mad_pool_t *mad_pool;
+	atomic32_t trans_id;
+	osm_vendor_t *vendor;
+	osm_bind_handle_t bind_handle;
+	cl_disp_reg_handle_t pc_disp_h;
+	osm_perfmgr_state_t state;
+	osm_perfmgr_sweep_state_t sweep_state;
+	uint16_t sweep_time_s;
+	perfmgr_db_t *db;
+	atomic32_t outstanding_queries;	/* this along with sig_query */
+	cl_event_t sig_query;	/* will throttle our querys */
+	uint32_t max_outstanding_queries;
+	cl_qmap_t monitored_map;	/* map the nodes we are tracking */
+	__monitored_node_t *remove_list;
+} osm_perfmgr_t;
+/*
+* FIELDS
+*	subn
+*	      Subnet object for this subnet.
+*
+*	log
+*	      Pointer to the log object.
+*
+*	mad_pool
+*		Pointer to the MAD pool.
+*
+*	mad_ctrl
+*		Mad Controller
+*********/
+
+/****f* OpenSM: Creation Functions */
+void osm_perfmgr_shutdown(osm_perfmgr_t * const p_perfmgr);
+void osm_perfmgr_destroy(osm_perfmgr_t * const p_perfmgr);
+
+/****f* OpenSM: Inline accessor functions */
+inline static void osm_perfmgr_set_state(osm_perfmgr_t * p_perfmgr,
+					 osm_perfmgr_state_t state)
+{
+	p_perfmgr->state = state;
+	if (state == PERFMGR_STATE_ENABLED)
+		osm_sm_signal(p_perfmgr->sm, OSM_SIGNAL_PERFMGR_SWEEP);
+}
+
+inline static osm_perfmgr_state_t osm_perfmgr_get_state(osm_perfmgr_t
+							  * p_perfmgr)
+{
+	return (p_perfmgr->state);
+}
+
+inline static char *osm_perfmgr_get_state_str(osm_perfmgr_t * p_perfmgr)
+{
+	switch (p_perfmgr->state) {
+	case PERFMGR_STATE_DISABLE:
+		return ("Disabled");
+		break;
+	case PERFMGR_STATE_ENABLED:
+		return ("Enabled");
+		break;
+	case PERFMGR_STATE_NO_DB:
+		return ("No Database");
+		break;
+	}
+	return ("UNKNOWN");
+}
+
+inline static char *osm_perfmgr_get_sweep_state_str(osm_perfmgr_t * perfmgr)
+{
+	switch (perfmgr->sweep_state) {
+	case PERFMGR_SWEEP_SLEEP:
+		return ("Sleeping");
+		break;
+	case PERFMGR_SWEEP_ACTIVE:
+		return ("Active");
+		break;
+	case PERFMGR_SWEEP_SUSPENDED:
+		return ("Suspended");
+		break;
+	}
+	return ("UNKNOWN");
+}
+
+inline static void osm_perfmgr_set_sweep_time_s(osm_perfmgr_t * p_perfmgr,
+						uint16_t time_s)
+{
+	p_perfmgr->sweep_time_s = time_s;
+	osm_sm_signal(p_perfmgr->sm, OSM_SIGNAL_PERFMGR_SWEEP);
+}
+
+inline static uint16_t osm_perfmgr_get_sweep_time_s(osm_perfmgr_t * p_perfmgr)
+{
+	return (p_perfmgr->sweep_time_s);
+}
+
+void osm_perfmgr_clear_counters(osm_perfmgr_t * p_perfmgr);
+void osm_perfmgr_dump_counters(osm_perfmgr_t * p_perfmgr,
+			       perfmgr_db_dump_t dump_type);
+void osm_perfmgr_print_counters(osm_perfmgr_t *pm, char *nodename,
+				FILE *fp);
+
+ib_api_status_t osm_perfmgr_bind(osm_perfmgr_t * const p_perfmgr,
+				 const ib_net64_t port_guid);
+
+void osm_perfmgr_process(osm_perfmgr_t * pm);
+
+/****f* OpenSM: PerfMgr/osm_perfmgr_init */
+ib_api_status_t osm_perfmgr_init(osm_perfmgr_t * const perfmgr,
+				 struct osm_opensm *osm,
+				 const osm_subn_opt_t * const p_opt);
+/*
+* PARAMETERS
+*	perfmgr
+*		[in] Pointer to an osm_perfmgr_t object to initialize.
+*
+*	osm
+*		[in] Pointer to the OpenSM object.
+*
+*	p_opt
+*		[in] Starting options
+*
+* RETURN VALUES
+*	IB_SUCCESS if the PerfMgr object was initialized successfully.
+*********/
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+#endif				/* _OSM_PERFMGR_H_ */
diff --git a/include/opensm/osm_perfmgr_db.h b/include/opensm/osm_perfmgr_db.h
new file mode 100644
index 0000000..c28d5bb
--- /dev/null
+++ b/include/opensm/osm_perfmgr_db.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 The Regents of the University of California.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _PERFMGR_EVENT_DB_H_
+#define _PERFMGR_EVENT_DB_H_
+
+#ifdef ENABLE_OSM_PERF_MGR
+
+#include <stdio.h>
+#include <time.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.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_perfmgr;
+/****h* OpenSM/PerfMgr Event Database
+* DESCRIPTION
+*       Database interface to record subnet events
+*
+*       Implementations of this object _MUST_ be thread safe.
+*
+* AUTHOR
+*	Ira Weiny, LLNL
+*
+*********/
+typedef enum {
+	PERFMGR_EVENT_DB_SUCCESS = 0,
+	PERFMGR_EVENT_DB_FAIL,
+	PERFMGR_EVENT_DB_NOMEM,
+	PERFMGR_EVENT_DB_GUIDNOTFOUND,
+	PERFMGR_EVENT_DB_PORTNOTFOUND,
+	PERFMGR_EVENT_DB_NOT_IMPL
+} perfmgr_db_err_t;
+
+/** =========================================================================
+ * Port error reading
+ */
+typedef struct {
+	uint64_t symbol_err_cnt;
+	uint64_t link_err_recover;
+	uint64_t link_downed;
+	uint64_t rcv_err;
+	uint64_t rcv_rem_phys_err;
+	uint64_t rcv_switch_relay_err;
+	uint64_t xmit_discards;
+	uint64_t xmit_constraint_err;
+	uint64_t rcv_constraint_err;
+	uint64_t link_integrity;
+	uint64_t buffer_overrun;
+	uint64_t vl15_dropped;
+	time_t time;
+} perfmgr_db_err_reading_t;
+
+/** =========================================================================
+ * Port data count reading
+ */
+typedef struct {
+	uint64_t xmit_data;	/* can be used for std or extended */
+	uint64_t rcv_data;	/* can be used for std or extended */
+	uint64_t xmit_pkts;	/* can be used for std or extended */
+	uint64_t rcv_pkts;	/* can be used for std or extended */
+	uint64_t unicast_xmit_pkts;
+	uint64_t unicast_rcv_pkts;
+	uint64_t multicast_xmit_pkts;
+	uint64_t multicast_rcv_pkts;
+	time_t time;
+} perfmgr_db_data_cnt_reading_t;
+
+/** =========================================================================
+ * Port select errors
+ */
+typedef struct {
+	uint64_t xmit_wait;
+	time_t time;
+} perfmgr_db_ps_reading_t;
+
+/** =========================================================================
+ * Dump output options
+ */
+typedef enum {
+	PERFMGR_EVENT_DB_DUMP_HR = 0,	/* Human readable */
+	PERFMGR_EVENT_DB_DUMP_MR	/* Machine readable */
+} perfmgr_db_dump_t;
+
+/** =========================================================================
+ * Port counter object.
+ * Store all the port counters for a single port.
+ */
+typedef struct _db_port {
+	perfmgr_db_err_reading_t err_total;
+	perfmgr_db_err_reading_t err_previous;
+	perfmgr_db_data_cnt_reading_t dc_total;
+	perfmgr_db_data_cnt_reading_t dc_previous;
+	time_t last_reset;
+} _db_port_t;
+
+/** =========================================================================
+ * group port counters for ports into the nodes
+ */
+#define NODE_NAME_SIZE (IB_NODE_DESCRIPTION_SIZE << 1)
+typedef struct _db_node {
+	cl_map_item_t map_item;	/* must be first */
+	uint64_t node_guid;
+	_db_port_t *ports;
+	uint8_t num_ports;
+	char node_name[NODE_NAME_SIZE];
+} _db_node_t;
+
+/** =========================================================================
+ * all nodes in the system.
+ */
+typedef struct _db {
+	cl_qmap_t pc_data;	/* stores type (_db_node_t *) */
+	cl_plock_t lock;
+	struct osm_perfmgr *perfmgr;
+} perfmgr_db_t;
+
+/**
+ * functions
+ */
+perfmgr_db_t *perfmgr_db_construct(struct osm_perfmgr *perfmgr);
+void perfmgr_db_destroy(perfmgr_db_t * db);
+
+perfmgr_db_err_t perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid,
+					 uint8_t num_ports, char *node_name);
+
+perfmgr_db_err_t perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid,
+					    uint8_t port,
+					    perfmgr_db_err_reading_t * reading);
+perfmgr_db_err_t perfmgr_db_get_prev_err(perfmgr_db_t * db, uint64_t guid,
+					 uint8_t port,
+					 perfmgr_db_err_reading_t * reading);
+perfmgr_db_err_t perfmgr_db_clear_prev_err(perfmgr_db_t * db, uint64_t guid,
+					   uint8_t port);
+
+perfmgr_db_err_t perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid,
+					   uint8_t port,
+					   perfmgr_db_data_cnt_reading_t *
+					   reading);
+perfmgr_db_err_t perfmgr_db_get_prev_dc(perfmgr_db_t * db, uint64_t guid,
+					uint8_t port,
+					perfmgr_db_data_cnt_reading_t *
+					reading);
+perfmgr_db_err_t perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid,
+					  uint8_t port);
+
+void perfmgr_db_clear_counters(perfmgr_db_t * db);
+perfmgr_db_err_t perfmgr_db_dump(perfmgr_db_t * db, char *file,
+				 perfmgr_db_dump_t dump_type);
+void perfmgr_db_print_by_name(perfmgr_db_t * db, char *nodename, FILE *fp);
+void perfmgr_db_print_by_guid(perfmgr_db_t * db, uint64_t guid, FILE *fp);
+
+/** =========================================================================
+ * helper functions to fill in the various db objects from wire objects
+ */
+
+void perfmgr_db_fill_err_read(ib_port_counters_t * wire_read,
+			      perfmgr_db_err_reading_t * reading);
+void perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read,
+				      perfmgr_db_data_cnt_reading_t * reading);
+void perfmgr_db_fill_data_cnt_read_epc(ib_port_counters_ext_t * wire_read,
+				       perfmgr_db_data_cnt_reading_t * reading);
+
+END_C_DECLS
+
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+#endif				/* _PERFMGR_PM_DB_H_ */
diff --git a/include/opensm/osm_pkey.h b/include/opensm/osm_pkey.h
new file mode 100644
index 0000000..aa141b7
--- /dev/null
+++ b/include/opensm/osm_pkey.h
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_PKEY_H_
+#define _OSM_PKEY_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_map.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/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
+/*
+   Forward references.
+*/
+struct osm_physp;
+struct osm_port;
+struct osm_subn;
+struct osm_node;
+struct osm_physp;
+
+/*
+ * Abstract:
+ * 	Declaration of pkey manipulation functions.
+ */
+
+/****s* OpenSM: osm_pkey_tbl_t
+* NAME
+*	osm_pkey_tbl_t
+*
+* DESCRIPTION
+*	This object represents a pkey table. The need for a special object
+*  is required to optimize search performance of a PKey in the IB standard
+*  non sorted table.
+*
+*	The osm_pkey_tbl_t object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_pkeybl {
+	cl_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
+*
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_PKEY_H_ */
diff --git a/include/opensm/osm_pkey_mgr.h b/include/opensm/osm_pkey_mgr.h
new file mode 100644
index 0000000..91587bd
--- /dev/null
+++ b/include/opensm/osm_pkey_mgr.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Prototype for osm_pkey_mgr_process() function
+ *	This is part of the OpenSM family of objects.
+ */
+
+#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_ */
diff --git a/include/opensm/osm_port.h b/include/opensm/osm_port.h
new file mode 100644
index 0000000..3dda541
--- /dev/null
+++ b/include/opensm/osm_port.h
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of port related objects.
+ *	These objects comprise an IBA port.
+ *	These objects are part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_PORT_H_
+#define _OSM_PORT_H_
+
+#include <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;
+	uint8_t vl_high_limit;
+	unsigned need_update;
+	unsigned is_prof_ignored;
+	osm_dr_path_t dr_path;
+	osm_pkey_tbl_t pkeys;
+	ib_vl_arb_table_t vl_arb[4];
+	cl_ptr_vector_t slvl_by_port;
+} 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.
+*
+*	vl_high_limit
+*		PortInfo:VLHighLimit value which installed by QoS manager
+*		and should be uploaded to port's PortInfo
+*
+*	need_update
+*		When set indicates that port was probably reset and port
+*		related tables (PKey, SL2VL, VLArb) require refreshing.
+*
+*	is_prof_ignored
+*		When set indicates that switch port will be ignored by
+*		the link load equalization algorithm.
+*
+*	dr_path
+*		The directed route path to this port.
+*
+*	pkeys
+*		osm_pkey_tbl_t object holding the port PKeys.
+*
+*	vl_arb[]
+*		Each Physical Port has 4 sections of VL Arbitration table.
+*
+*	slvl_by_port
+*		A vector of pointers to the sl2vl tables (ordered by input port).
+*		Switches have an entry for every other input port (inc SMA=0).
+*		On CAs only one per port.
+*
+* 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
+*********/
+
+/****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_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_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_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
+*
+*********/
+
+/****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;
+	cl_list_item_t list_item;
+	struct osm_node *p_node;
+	ib_net64_t guid;
+	uint32_t discovery_count;
+	unsigned is_new;
+	osm_physp_t *p_physp;
+	cl_qlist_t mcm_list;
+	int flag;
+	void *priv;
+} osm_port_t;
+/*
+* FIELDS
+*	map_item
+*		Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*	list_item
+*		Linkage structure for cl_qlist. Used by ucast mgr during LFT calculation.
+*
+*	p_node
+*		Points to the Node object that owns this port.
+*
+*	guid
+*		Manufacturer assigned GUID for this port.
+*
+*	discovery_count
+*		The number of times this port has been discovered
+*		during the current fabric sweep.  This number is reset
+*		to zero at the start of a sweep.
+*
+*	p_physp
+*		The pointer to physical port used when physical
+*		characteristics contained in the Physical Port are needed.
+*
+*	mcm_list
+*		Multicast member list
+*
+*	flag
+*		Utility flag for port management
+*
+* SEE ALSO
+*	Port, Physical Port, Physical Port Table
+*********/
+
+/****f* OpenSM: Port/osm_port_delete
+* NAME
+*	osm_port_delete
+*
+* DESCRIPTION
+*	This function destroys and deallocates a Port object.
+*
+* SYNOPSIS
+*/
+void osm_port_delete(IN OUT osm_port_t ** const pp_port);
+/*
+* PARAMETERS
+*	pp_port
+*		[in][out] Pointer to a pointer to a Port object to delete.
+*		On return, this pointer is NULL.
+*
+* RETURN VALUE
+*	This function does not return a value.
+*
+* NOTES
+*	Performs any necessary cleanup of the specified Port object.
+*
+* SEE ALSO
+*	Port
+*********/
+
+/****f* OpenSM: Port/osm_port_new
+* NAME
+*	osm_port_new
+*
+* DESCRIPTION
+*	This function allocates and initializes a Port object.
+*
+* SYNOPSIS
+*/
+osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni,
+			 IN struct osm_node *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)
+{
+	CL_ASSERT(p_port->p_physp && osm_physp_is_valid(p_port->p_physp));
+	return (osm_physp_get_base_lid(p_port->p_physp));
+}
+
+/*
+* PARAMETERS
+*	p_port
+*		[in] Pointer to a Port object.
+*
+* RETURN VALUE
+*	Base LID of the port.
+*	If the return value is 0, then this port has no assigned LID.
+*
+* NOTES
+*
+* SEE ALSO
+*	Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_lmc
+* NAME
+*	osm_port_get_lmc
+*
+* DESCRIPTION
+*	Gets the LMC value of a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t osm_port_get_lmc(IN const osm_port_t * const p_port)
+{
+	CL_ASSERT(p_port->p_physp && osm_physp_is_valid(p_port->p_physp));
+	return (osm_physp_get_lmc(p_port->p_physp));
+}
+
+/*
+* PARAMETERS
+*	p_port
+*		[in] Pointer to a Port object.
+*
+* RETURN VALUE
+*	Gets the LMC value of a port.
+*
+* NOTES
+*
+* SEE ALSO
+*	Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_guid
+* NAME
+*	osm_port_get_guid
+*
+* DESCRIPTION
+*	Gets the GUID of a port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t osm_port_get_guid(IN const osm_port_t * 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_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_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_ */
diff --git a/include/opensm/osm_port_profile.h b/include/opensm/osm_port_profile.h
new file mode 100644
index 0000000..fd22719
--- /dev/null
+++ b/include/opensm/osm_port_profile.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of Switch/osm_port_profile_t.
+ *	This object represents a port profile for an IBA switch.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_PORT_PROFILE_H_
+#define _OSM_PORT_PROFILE_H_
+
+#include <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_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
+*********/
+
+/****s* OpenSM: Switch/osm_port_mask_t
+* NAME
+*	osm_port_mask_t
+*
+* DESCRIPTION
+*       The Port Mask object contains a port numbered bit mask
+*	for whether the port should be ignored by the link load
+*	equalization algorithm.
+*
+* SYNOPSIS
+*/
+typedef long osm_port_mask_t[32 / sizeof(long)];
+/*
+* FIELDS
+*	osm_port_mask_t
+*		Bit mask by port number
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_prof_construct
+* NAME
+*	osm_port_prof_construct
+*
+* DESCRIPTION
+*
+*
+* SYNOPSIS
+*/
+static inline void osm_port_prof_construct(IN osm_port_profile_t * 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_prof
+*		[in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_prof_path_count_get
+* NAME
+*	osm_port_prof_path_count_get
+*
+* DESCRIPTION
+*	Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_prof_path_count_get(IN const osm_port_profile_t * const p_prof)
+{
+	return (p_prof->num_paths);
+}
+/*
+* PARAMETERS
+*	p_prof
+*		[in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_PORT_PROFILE_H_ */
diff --git a/include/opensm/osm_prefix_route.h b/include/opensm/osm_prefix_route.h
new file mode 100644
index 0000000..829a9ff
--- /dev/null
+++ b/include/opensm/osm_prefix_route.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_PREFIX_ROUTE_H_
+#define _OSM_PREFIX_ROUTE_H_
+
+#include <complib/cl_types.h>
+#include <complib/cl_qlist.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 {
+	cl_list_item_t list_item;	/* must be first */
+	ib_net64_t prefix;		/* zero means "any" */
+	ib_net64_t guid;		/* zero means "any" */
+} osm_prefix_route_t;
+
+#ifdef ROUTER_EXP
+#error ROUTER_EXP is deprecated, specify prefix routes at runtime instead (see opensm man page for details)
+#endif
+
+END_C_DECLS
+#endif /* _OSM_PREFIX_ROUTE_H_ */
diff --git a/include/opensm/osm_qos_policy.h b/include/opensm/osm_qos_policy.h
new file mode 100644
index 0000000..c38624b
--- /dev/null
+++ b/include/opensm/osm_qos_policy.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Declaration of OSM QoS Policy data types and functions.
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#ifndef OSM_QOS_POLICY_H
+#define OSM_QOS_POLICY_H
+
+#include <iba/ib_types.h>
+#include <complib/cl_list.h>
+#include <opensm/st.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_partition.h>
+
+#define YYSTYPE char *
+#define OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH  128
+#define OSM_QOS_POLICY_DEFAULT_LEVEL_NAME   "default"
+
+#define OSM_QOS_POLICY_ULP_SDP_SERVICE_ID   0x0000000000010000ULL
+#define OSM_QOS_POLICY_ULP_RDS_SERVICE_ID   0x0000000001060000ULL
+#define OSM_QOS_POLICY_ULP_RDS_PORT         0x48CA
+#define OSM_QOS_POLICY_ULP_ISER_SERVICE_ID  0x0000000001060000ULL
+#define OSM_QOS_POLICY_ULP_ISER_PORT        0x0CBC
+
+#define OSM_QOS_POLICY_NODE_TYPE_CA        (((uint8_t)1)<<IB_NODE_TYPE_CA)
+#define OSM_QOS_POLICY_NODE_TYPE_SWITCH    (((uint8_t)1)<<IB_NODE_TYPE_SWITCH)
+#define OSM_QOS_POLICY_NODE_TYPE_ROUTER    (((uint8_t)1)<<IB_NODE_TYPE_ROUTER)
+
+/***************************************************/
+
+typedef struct osm_qos_port {
+	cl_map_item_t map_item;
+	osm_physp_t * p_physp;
+} osm_qos_port_t;
+
+typedef struct osm_qos_port_group {
+	char *name;			/* single string (this port group name) */
+	char *use;			/* single string (description) */
+	uint8_t node_types;		/* node types bitmask */
+	cl_qmap_t port_map;
+} osm_qos_port_group_t;
+
+/***************************************************/
+
+typedef struct osm_qos_vlarb_scope {
+	cl_list_t group_list;		/* list of group names (strings) */
+	cl_list_t across_list;		/* list of 'across' group names (strings) */
+	cl_list_t vlarb_high_list;	/* list of num pairs (n:m,...), 32-bit values */
+	cl_list_t vlarb_low_list;	/* list of num pairs (n:m,...), 32-bit values */
+	uint32_t vl_high_limit;		/* single integer */
+	boolean_t vl_high_limit_set;
+} osm_qos_vlarb_scope_t;
+
+/***************************************************/
+
+typedef struct osm_qos_sl2vl_scope {
+	cl_list_t group_list;		/* list of strings (port group names) */
+	boolean_t from[OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH];
+	boolean_t to[OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH];
+	cl_list_t across_from_list;	/* list of strings (port group names) */
+	cl_list_t across_to_list;	/* list of strings (port group names) */
+	uint8_t sl2vl_table[16];	/* array of sl2vl values */
+	boolean_t sl2vl_table_set;
+} osm_qos_sl2vl_scope_t;
+
+/***************************************************/
+
+typedef struct osm_qos_level {
+	char *use;
+	char *name;
+	uint8_t sl;
+	boolean_t sl_set;
+	uint8_t mtu_limit;
+	boolean_t mtu_limit_set;
+	uint8_t rate_limit;
+	boolean_t rate_limit_set;
+	uint8_t pkt_life;
+	boolean_t pkt_life_set;
+	uint64_t **path_bits_range_arr;	/* array of bit ranges (real values are 32bits) */
+	unsigned path_bits_range_len;	/* num of bit ranges in the array */
+	uint64_t **pkey_range_arr;	/* array of PKey ranges (real values are 16bits) */
+	unsigned pkey_range_len;
+} osm_qos_level_t;
+
+
+/***************************************************/
+
+typedef struct osm_qos_match_rule {
+	char *use;
+	cl_list_t source_list;			/* list of strings */
+	cl_list_t source_group_list;		/* list of pointers to relevant port-group */
+	cl_list_t destination_list;		/* list of strings */
+	cl_list_t destination_group_list;	/* list of pointers to relevant port-group */
+	char *qos_level_name;
+	osm_qos_level_t *p_qos_level;
+	uint64_t **service_id_range_arr;	/* array of SID ranges (64-bit values) */
+	unsigned service_id_range_len;
+	uint64_t **qos_class_range_arr;		/* array of QoS Class ranges (real values are 16bits) */
+	unsigned qos_class_range_len;
+	uint64_t **pkey_range_arr;		/* array of PKey ranges (real values are 16bits) */
+	unsigned pkey_range_len;
+} osm_qos_match_rule_t;
+
+/***************************************************/
+
+typedef struct osm_qos_policy {
+	cl_list_t port_groups;			/* list of osm_qos_port_group_t */
+	cl_list_t sl2vl_tables;			/* list of osm_qos_sl2vl_scope_t */
+	cl_list_t vlarb_tables;			/* list of osm_qos_vlarb_scope_t */
+	cl_list_t qos_levels;			/* list of osm_qos_level_t */
+	cl_list_t qos_match_rules;		/* list of osm_qos_match_rule_t */
+	osm_qos_level_t *p_default_qos_level;	/* default QoS level */
+	osm_subn_t *p_subn;			/* osm subnet object */
+	st_table * p_node_hash;			/* node by name hash */
+} osm_qos_policy_t;
+
+/***************************************************/
+
+osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t * p_physp);
+osm_qos_port_group_t * osm_qos_policy_port_group_create();
+void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p_port_group);
+
+osm_qos_vlarb_scope_t * osm_qos_policy_vlarb_scope_create();
+void osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p_vlarb_scope);
+
+osm_qos_sl2vl_scope_t * osm_qos_policy_sl2vl_scope_create();
+void osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p_sl2vl_scope);
+
+osm_qos_level_t * osm_qos_policy_qos_level_create();
+void osm_qos_policy_qos_level_destroy(osm_qos_level_t * p_qos_level);
+
+boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level,
+				 IN ib_net16_t pkey);
+
+ib_net16_t osm_qos_level_get_shared_pkey(IN const osm_qos_level_t * p_qos_level,
+					 IN const osm_physp_t * p_src_physp,
+					 IN const osm_physp_t * p_dest_physp);
+
+osm_qos_match_rule_t * osm_qos_policy_match_rule_create();
+void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p_match_rule);
+
+osm_qos_policy_t * osm_qos_policy_create(osm_subn_t * p_subn);
+void osm_qos_policy_destroy(osm_qos_policy_t * p_qos_policy);
+int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy, osm_log_t * p_log);
+
+osm_qos_level_t * osm_qos_policy_get_qos_level_by_pr(
+	IN const osm_qos_policy_t * p_qos_policy,
+	IN const ib_path_rec_t * p_pr,
+	IN const osm_physp_t * p_src_physp,
+	IN const osm_physp_t * p_dest_physp,
+	IN ib_net64_t comp_mask);
+
+osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr(
+	IN const osm_qos_policy_t * p_qos_policy,
+	IN const ib_multipath_rec_t * p_mpr,
+	IN const osm_physp_t * p_src_physp,
+	IN const osm_physp_t * p_dest_physp,
+	IN ib_net64_t comp_mask);
+
+/***************************************************/
+
+int osm_qos_parse_policy_file(IN osm_subn_t * const p_subn);
+
+/***************************************************/
+
+#endif				/* ifndef OSM_QOS_POLICY_H */
diff --git a/include/opensm/osm_remote_sm.h b/include/opensm/osm_remote_sm.h
new file mode 100644
index 0000000..4cc980b
--- /dev/null
+++ b/include/opensm/osm_remote_sm.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_sm_t, osm_remote_sm_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_REMOTE_SM_H_
+#define _OSM_REMOTE_SM_H_
+
+#include <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_ */
diff --git a/include/opensm/osm_router.h b/include/opensm/osm_router.h
new file mode 100644
index 0000000..4901aca
--- /dev/null
+++ b/include/opensm/osm_router.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_router_t.
+ *	This object represents an IBA router.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_ROUTER_H_
+#define _OSM_ROUTER_H_
+
+#include <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_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_delete
+* NAME
+*	osm_router_delete
+*
+* 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_new
+*********/
+
+/****f* OpenSM: Router/osm_router_new
+* NAME
+*	osm_router_new
+*
+* DESCRIPTION
+*	The osm_router_new function initializes a Router object for use.
+*
+* SYNOPSIS
+*/
+osm_router_t *osm_router_new(IN osm_port_t * 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_new
+*********/
+
+/****f* OpenSM: Router/osm_router_get_port_ptr
+* NAME
+*	osm_router_get_port_ptr
+*
+* DESCRIPTION
+*	Returns a pointer to the Port object for this router.
+*
+* SYNOPSIS
+*/
+static inline osm_port_t *osm_router_get_port_ptr(IN const osm_router_t *
+						  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_ */
diff --git a/include/opensm/osm_sa.h b/include/opensm/osm_sa.h
new file mode 100644
index 0000000..5a0ae9f
--- /dev/null
+++ b/include/opensm/osm_sa.h
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_sa_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SA_H_
+#define _OSM_SA_H_
+
+#include <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_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <opensm/osm_sm.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
+/****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_sm_t *sm;
+	osm_subn_t *p_subn;
+	osm_vendor_t *p_vendor;
+	osm_log_t *p_log;
+	osm_mad_pool_t *p_mad_pool;
+	cl_dispatcher_t *p_disp;
+	cl_plock_t *p_lock;
+	atomic32_t sa_trans_id;
+	osm_sa_mad_ctrl_t mad_ctrl;
+	cl_timer_t sr_timer;
+	cl_disp_reg_handle_t cpi_disp_h;
+	cl_disp_reg_handle_t nr_disp_h;
+	cl_disp_reg_handle_t pir_disp_h;
+	cl_disp_reg_handle_t gir_disp_h;
+	cl_disp_reg_handle_t lr_disp_h;
+	cl_disp_reg_handle_t pr_disp_h;
+	cl_disp_reg_handle_t smir_disp_h;
+	cl_disp_reg_handle_t mcmr_disp_h;
+	cl_disp_reg_handle_t sr_disp_h;
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	cl_disp_reg_handle_t mpr_disp_h;
+#endif
+	cl_disp_reg_handle_t infr_disp_h;
+	cl_disp_reg_handle_t infir_disp_h;
+	cl_disp_reg_handle_t vlarb_disp_h;
+	cl_disp_reg_handle_t slvl_disp_h;
+	cl_disp_reg_handle_t pkey_disp_h;
+	cl_disp_reg_handle_t lft_disp_h;
+	cl_disp_reg_handle_t sir_disp_h;
+	cl_disp_reg_handle_t mft_disp_h;
+} osm_sa_t;
+/*
+* FIELDS
+*	state
+*		State of this SA object
+*
+*	sm
+*		Pointer to the Subnet Manager object.
+*
+*	p_subn
+*		Pointer to the Subnet object for this subnet.
+*
+*	p_vendor
+*		Pointer to the vendor specific interfaces object.
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	p_mad_pool
+*		Pointer to the MAD pool.
+*
+*	p_disp
+*		Pointer to dispatcher
+*
+*	p_lock
+*		Pointer to Lock for serialization
+*
+*	sa_trans_id
+*		Transaction ID
+*
+*	mad_ctrl
+*		Mad Controller
+*
+* 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_destroy.
+*
+*	Calling osm_sa_construct is a prerequisite to calling any other
+*	method except osm_sa_init.
+*
+* SEE ALSO
+*	SA object, osm_sa_init, osm_sa_destroy
+*********/
+
+/****f* OpenSM: SA/osm_sa_shutdown
+* NAME
+*	osm_sa_shutdown
+*
+* DESCRIPTION
+*	The osm_sa_shutdown function shutdowns an SA, unregistering from all
+*  dispatcher messages and unbinding the QP1 mad service
+*
+* SYNOPSIS
+*/
+void osm_sa_shutdown(IN osm_sa_t * 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
+*********/
+
+/****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
+*********/
+
+/****f* OpenSM: SA/osm_sa_send
+* NAME
+*	osm_sa_send
+*
+* DESCRIPTION
+*	Sends SA MAD via osm_vendor_send and maintains the QP1 sent statistic
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sa_send(osm_sa_t *sa, IN osm_madw_t * const p_madw,
+			    IN boolean_t const resp_expected);
+
+/****f* IBA Base: Types/osm_sa_send_error
+* NAME
+*	osm_sa_send_error
+*
+* DESCRIPTION
+*	Sends a generic SA response with the specified error status.
+*	The payload is simply replicated from the request MAD.
+*
+* SYNOPSIS
+*/
+void osm_sa_send_error(IN osm_sa_t * sa, IN const osm_madw_t * const p_madw,
+		       IN const ib_net16_t sa_status);
+/*
+* PARAMETERS
+*	sa
+*		[in] Pointer to an osm_sa_t object.
+*
+*	p_madw
+*		[in] Original MAD to which the response must be sent.
+*
+*	sa_status
+*		[in] Status to send in the response.
+*
+* RETURN VALUES
+*	None.
+*
+* SEE ALSO
+*	SA object
+*********/
+
+/****f* OpenSM: SA/osm_sa_respond
+* NAME
+*	osm_sa_respond
+*
+* DESCRIPTION
+*	Sends SA MAD response
+*/
+void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
+		    cl_qlist_t *list);
+/*
+* PARAMETERS
+*	sa
+*		[in] Pointer to an osm_sa_t object.
+*
+*	p_madw
+*		[in] Original MAD to which the response must be sent.
+*
+*	attr_size
+*		[in] Size of this SA attribute.
+*
+*	list
+*		[in] List of attribute to respond - it will be freed after
+*		sending.
+*
+* RETURN VALUES
+*	None.
+*
+* SEE ALSO
+*	SA object
+*********/
+
+struct osm_opensm;
+/****f* OpenSM: SA/osm_sa_db_file_dump
+* NAME
+*	osm_sa_db_file_dump
+*
+* DESCRIPTION
+*	Dumps the SA DB to the dump file.
+*
+* SYNOPSIS
+*/
+int osm_sa_db_file_dump(struct osm_opensm *p_osm);
+/*
+* PARAMETERS
+*	p_osm
+*		[in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+*	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 *p_osm);
+/*
+* PARAMETERS
+*	p_osm
+*		[in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+*	0 on success, other value on failure.
+*
+*********/
+
+/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_find_or_create_new_mgrp
+* NAME
+*	osm_mcmr_rcv_find_or_create_new_mgrp
+*
+* DESCRIPTION
+*	Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(IN osm_sa_t * sa,
+				     IN uint64_t comp_mask,
+				     IN ib_member_rec_t *
+				     const p_recvd_mcmember_rec,
+				     OUT osm_mgrp_t ** pp_mgrp);
+/*
+* PARAMETERS
+*	p_sa
+*		[in] Pointer to an osm_sa_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
+*
+*********/
+
+osm_mgrp_t *osm_get_mgrp_by_mgid(IN osm_sa_t * sa, IN ib_gid_t * p_mgid);
+
+END_C_DECLS
+#endif				/* _OSM_SA_H_ */
diff --git a/include/opensm/osm_sa_mad_ctrl.h b/include/opensm/osm_sa_mad_ctrl.h
new file mode 100644
index 0000000..cc2ac53
--- /dev/null
+++ b/include/opensm/osm_sa_mad_ctrl.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_sa_mad_ctrl_t.
+ *	This object represents a controller that receives the IBA SA
+ *	attributes from a node.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SA_MAD_CTRL_H_
+#define _OSM_SA_MAD_CTRL_H_
+
+#include <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>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****h* OpenSM/SA MAD Controller
+* NAME
+*	SA MAD Controller
+*
+* DESCRIPTION
+*	The SA MAD Controller object encapsulates
+*	the information	needed to receive MADs from the transport layer.
+*
+*	The SA MAD Controller object is thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Ranjit Pandit, Intel
+*
+*********/
+
+struct osm_sa;
+/****s* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_t
+* NAME
+*	osm_sa_mad_ctrl_t
+*
+* DESCRIPTION
+*	SA MAD Controller structure.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_sa_mad_ctrl {
+	struct osm_sa *sa;
+	osm_log_t *p_log;
+	osm_mad_pool_t *p_mad_pool;
+	osm_vendor_t *p_vendor;
+	osm_bind_handle_t h_bind;
+	cl_dispatcher_t *p_disp;
+	cl_disp_reg_handle_t h_disp;
+	osm_stats_t *p_stats;
+	osm_subn_t *p_subn;
+} osm_sa_mad_ctrl_t;
+/*
+* FIELDS
+*	sa
+*		Pointer to the SA object.
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	p_mad_pool
+*		Pointer to the MAD pool.
+*
+*	p_vendor
+*		Pointer to the vendor specific interfaces object.
+*
+*	h_bind
+*		Bind handle returned by the transport layer.
+*
+*	p_disp
+*		Pointer to the Dispatcher.
+*
+*	h_disp
+*		Handle returned from dispatcher registration.
+*
+*	p_stats
+*		Pointer to the OpenSM statistics block.
+*
+* SEE ALSO
+*	SA MAD Controller object
+*	SA MADr object
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_construct
+* NAME
+*	osm_sa_mad_ctrl_construct
+*
+* DESCRIPTION
+*	This function constructs a SA MAD Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * 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 struct osm_sa * sa,
+				     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.
+*
+*	sa
+*		[in] Pointer to the SA object.
+*
+*	p_mad_pool
+*		[in] Pointer to the MAD pool.
+*
+*	p_vendor
+*		[in] Pointer to the vendor specific interfaces object.
+*
+*	p_log
+*		[in] Pointer to the log object.
+*
+*	p_stats
+*		[in] Pointer to the OpenSM stastics block.
+*
+*	p_disp
+*		[in] Pointer to the OpenSM central Dispatcher.
+*
+* 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_ */
diff --git a/include/opensm/osm_service.h b/include/opensm/osm_service.h
new file mode 100644
index 0000000..1d97a68
--- /dev/null
+++ b/include/opensm/osm_service.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_SVCR_H_
+#define _OSM_SVCR_H_
+
+/*
+ * Abstract:
+ * 	Declaration of osm_service_rec_t.
+ *	This object represents an IBA Service Record.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#include <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 {
+	cl_list_item_t list_item;
+	ib_service_record_t service_record;
+	uint32_t modified_time;
+	uint32_t lease_period;
+} osm_svcr_t;
+/*
+* FIELDS
+*	map_item
+*		Map Item for qmap linkage.  Must be first element!!
+*
+*	svc_rec
+*		IB Service record structure
+*
+*	modified_time
+*		Last modified time of this record in milliseconds
+*
+*	lease_period
+*		Remaining lease period for this record
+*
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_new
+* NAME
+*	osm_svcr_new
+*
+* DESCRIPTION
+*	Allocates and initializes a Service Record for use.
+*
+* SYNOPSIS
+*/
+osm_svcr_t *osm_svcr_new(IN const ib_service_record_t * p_svc_rec);
+/*
+* PARAMETERS
+*	p_svc_rec
+*		[in] Pointer to IB Service Record
+*
+* RETURN VALUES
+*	pointer to osm_svcr_t structure.
+*
+* NOTES
+*	Allows calling other service record methods.
+*
+* SEE ALSO
+*	Service Record, osm_svcr_delete
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_init
+* NAME
+*	osm_svcr_init
+*
+* DESCRIPTION
+*	Initializes the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_init(IN osm_svcr_t * 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
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_delete
+* NAME
+*	osm_svcr_delete
+*
+* DESCRIPTION
+*	Deallocates the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void osm_svcr_delete(IN osm_svcr_t * const p_svcr);
+/*
+* PARAMETERS
+*	p_svc_rec
+*		[in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+*	Service Record, osm_svcr_new
+*********/
+
+osm_svcr_t *osm_svcr_get_by_rid(IN osm_subn_t const *p_subn,
+				IN osm_log_t * p_log,
+				IN ib_service_record_t * 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_ */
diff --git a/include/opensm/osm_sm.h b/include/opensm/osm_sm.h
new file mode 100644
index 0000000..ebe3dc3
--- /dev/null
+++ b/include/opensm/osm_sm.h
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_sm_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SM_H_
+#define _OSM_SM_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_event_wheel.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_db.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
+* NAME
+*	SM
+*
+* DESCRIPTION
+*	The SM object encapsulates the information needed by the
+*	OpenSM to instantiate a subnet manager.  The OpenSM allocates
+*	one SM object per subnet manager.
+*
+*	The SM object is thread safe.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: SM/osm_sm_t
+* NAME
+*  osm_sm_t
+*
+* DESCRIPTION
+*  Subnet Manager structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_sm {
+	osm_thread_state_t thread_state;
+	unsigned signal_mask;
+	cl_spinlock_t signal_lock;
+	cl_spinlock_t state_lock;
+	cl_event_t signal_event;
+	cl_event_t subnet_up_event;
+	cl_timer_t sweep_timer;
+	cl_timer_t polling_timer;
+	cl_event_wheel_t trap_aging_tracker;
+	cl_thread_t sweeper;
+	unsigned master_sm_found;
+	uint32_t retry_number;
+	ib_net64_t master_sm_guid;
+	osm_remote_sm_t *p_polling_sm;
+	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;
+	cl_spinlock_t mgrp_lock;
+	cl_qlist_t mgrp_list;
+	osm_sm_mad_ctrl_t mad_ctrl;
+	osm_lid_mgr_t lid_mgr;
+	osm_ucast_mgr_t ucast_mgr;
+	cl_disp_reg_handle_t sweep_fail_disp_h;
+	cl_disp_reg_handle_t ni_disp_h;
+	cl_disp_reg_handle_t pi_disp_h;
+	cl_disp_reg_handle_t nd_disp_h;
+	cl_disp_reg_handle_t si_disp_h;
+	cl_disp_reg_handle_t lft_disp_h;
+	cl_disp_reg_handle_t mft_disp_h;
+	cl_disp_reg_handle_t sm_info_disp_h;
+	cl_disp_reg_handle_t trap_disp_h;
+	cl_disp_reg_handle_t slvl_disp_h;
+	cl_disp_reg_handle_t vla_disp_h;
+	cl_disp_reg_handle_t pkey_disp_h;
+} osm_sm_t;
+/*
+* FIELDS
+*	p_subn
+*		Pointer to the Subnet object for this subnet.
+*
+*	p_db
+*		Pointer to the database (persistency) object
+*
+*	p_vendor
+*		Pointer to the vendor specific interfaces object.
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	p_mad_pool
+*		Pointer to the MAD pool.
+*
+*	p_vl15
+*		Pointer to the VL15 interface.
+*
+*	mad_ctrl
+*		MAD Controller.
+*
+*	p_disp
+*		Pointer to the Dispatcher.
+*
+*	p_lock
+*		Pointer to the serializing lock.
+*
+* SEE ALSO
+*	SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_construct
+* NAME
+*	osm_sm_construct
+*
+* DESCRIPTION
+*	This function constructs an SM object.
+*
+* SYNOPSIS
+*/
+void osm_sm_construct(IN osm_sm_t * 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_signal
+* NAME
+*	osm_sm_signal
+*
+* DESCRIPTION
+*	Signal event to SM
+*
+* SYNOPSIS
+*/
+void osm_sm_signal(IN osm_sm_t * const p_sm, osm_signal_t signal);
+/*
+* PARAMETERS
+*	p_sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	signal
+*		[in] sm signal number.
+*
+* NOTES
+*
+* SEE ALSO
+*	SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_sweep
+* NAME
+*	osm_sm_sweep
+*
+* DESCRIPTION
+*	Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+void osm_sm_sweep(IN osm_sm_t * 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_req_get
+* NAME
+*	osm_req_get
+*
+* DESCRIPTION
+*	Starts the process to transmit a directed route request for
+*	the attribute.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_get(IN osm_sm_t * sm,
+	    IN const osm_dr_path_t * 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
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	p_path
+*		[in] Pointer to the directed route path to the node
+*		from which to retrieve the attribute.
+*
+*	attr_id
+*		[in] Attribute ID to request.
+*
+*	attr_mod
+*		[in] Attribute modifier for this request.
+*
+*	err_msg
+*		[in] Message id with which to post this MAD if an error occurs.
+*
+*	p_context
+*		[in] Mad wrapper context structure to be copied into the wrapper
+*		context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+*	IB_SUCCESS if the request was successful.
+*
+* NOTES
+*	This function asynchronously requests the specified attribute.
+*	The response from the node will be routed through the Dispatcher
+*	to the appropriate receive controller object.
+*********/
+/****f* OpenSM: SM/osm_req_set
+* NAME
+*	osm_req_set
+*
+* DESCRIPTION
+*	Starts the process to transmit a directed route Set() request.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_set(IN osm_sm_t * sm,
+	    IN const osm_dr_path_t * 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
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	p_path
+*		[in] Pointer to the directed route path of the recipient.
+*
+*	p_payload
+*		[in] Pointer to the SMP payload to send.
+*
+*	payload_size
+*		[in] The size of the payload to be copied to the SMP data field.
+*
+*	attr_id
+*		[in] Attribute ID to request.
+*
+*	attr_mod
+*		[in] Attribute modifier for this request.
+*
+*	err_msg
+*		[in] Message id with which to post this MAD if an error occurs.
+*
+*	p_context
+*		[in] Mad wrapper context structure to be copied into the wrapper
+*		context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+*	IB_SUCCESS if the request was successful.
+*
+* NOTES
+*	This function asynchronously requests the specified attribute.
+*	The response from the node will be routed through the Dispatcher
+*	to the appropriate receive controller object.
+*********/
+/****f* OpenSM: SM/osm_resp_send
+* NAME
+*	osm_resp_send
+*
+* DESCRIPTION
+*	Starts the process to transmit a directed route response.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_send(IN osm_sm_t * sm,
+	      IN const osm_madw_t * 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.
+*
+*********/
+
+/****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
+*********/
+
+/****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)
+{
+	return (l_priority > r_priority
+		|| (l_priority == r_priority
+		    && cl_ntoh64(l_guid) < cl_ntoh64(r_guid)));
+}
+
+/*
+* PARAMETERS
+*	l_priority
+*		[in] Priority of the SM on the "left"
+*
+*	l_guid
+*		[in] GUID of the SM on the "left"
+*
+*	r_priority
+*		[in] Priority of the SM on the "right"
+*
+*	r_guid
+*		[in] GUID of the SM on the "right"
+*
+* RETURN VALUES
+*	Return TRUE if an sm with l_priority and l_guid is higher than an sm
+*	with r_priority and r_guid, return FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*	State Manager
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_process
+* NAME
+*	osm_sm_state_mgr_process
+*
+* DESCRIPTION
+*	Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sm_state_mgr_process(IN osm_sm_t *sm,
+					 IN osm_sm_signal_t signal);
+/*
+* PARAMETERS
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	signal
+*		[in] Signal to the state SM engine.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	State Manager
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_signal_master_is_alive
+* NAME
+*	osm_sm_state_mgr_signal_master_is_alive
+*
+* DESCRIPTION
+*	Signals that the remote Master SM is alive.
+*	Need to clear the retry_number variable.
+*
+* SYNOPSIS
+*/
+void osm_sm_state_mgr_signal_master_is_alive(IN osm_sm_t *sm);
+/*
+* PARAMETERS
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	State Manager
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_check_legality
+* NAME
+*	osm_sm_state_mgr_check_legality
+*
+* DESCRIPTION
+*	Checks the legality of the signal received, according to the
+*  current state of the SM state machine.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sm_state_mgr_check_legality(IN osm_sm_t *sm,
+						IN osm_sm_signal_t signal);
+/*
+* PARAMETERS
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	signal
+*		[in] Signal to the state SM engine.
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	State Manager
+*********/
+
+void osm_report_sm_state(osm_sm_t *sm);
+
+/****f* OpenSM: SM State Manager/osm_send_trap144
+* NAME
+*	osm_send_trap144
+*
+* DESCRIPTION
+*	Send trap 144 to the master SM.
+*
+* SYNOPSIS
+*/
+int osm_send_trap144(osm_sm_t *sm, ib_net16_t local);
+/*
+* PARAMETERS
+*	sm
+*		[in] Pointer to an osm_sm_t object.
+*
+*	local
+*		[in] OtherLocalChanges mask in network byte order.
+*
+* RETURN VALUES
+*	0 on success, non-zero value otherwise.
+*
+*********/
+
+void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority);
+
+END_C_DECLS
+#endif				/* _OSM_SM_H_ */
diff --git a/include/opensm/osm_sm_mad_ctrl.h b/include/opensm/osm_sm_mad_ctrl.h
new file mode 100644
index 0000000..1c41168
--- /dev/null
+++ b/include/opensm/osm_sm_mad_ctrl.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_sm_mad_ctrl_t.
+ *	This object represents a controller that receives the IBA NodeInfo
+ *	attribute from a node.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SM_MAD_CTRL_H_
+#define _OSM_SM_MAD_CTRL_H_
+
+#include <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_ */
diff --git a/include/opensm/osm_stats.h b/include/opensm/osm_stats.h
new file mode 100644
index 0000000..4331cfa
--- /dev/null
+++ b/include/opensm/osm_stats.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_stats_t.
+ *	This object represents the OpenSM statistics object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_STATS_H_
+#define _OSM_STATS_H_
+
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+#else
+#include <complib/cl_event.h>
+#endif
+#include <complib/cl_atomic.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/Statistics
+* NAME
+*	OpenSM
+*
+* DESCRIPTION
+*	The OpenSM object encapsulates the information needed by the
+*	OpenSM to track interesting traffic and internal statistics.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: Statistics/osm_stats_t
+* NAME
+*	osm_stats_t
+*
+* DESCRIPTION
+*	OpenSM statistics block.
+*
+* SYNOPSIS
+*/
+typedef struct osm_stats {
+	atomic32_t qp0_mads_outstanding;
+	atomic32_t qp0_mads_outstanding_on_wire;
+	atomic32_t qp0_mads_rcvd;
+	atomic32_t qp0_mads_sent;
+	atomic32_t qp0_unicasts_sent;
+	atomic32_t qp0_mads_rcvd_unknown;
+	atomic32_t sa_mads_outstanding;
+	atomic32_t sa_mads_rcvd;
+	atomic32_t sa_mads_sent;
+	atomic32_t sa_mads_rcvd_unknown;
+	atomic32_t sa_mads_ignored;
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_t mutex;
+	pthread_cond_t cond;
+#else
+	cl_event_t event;
+#endif
+} osm_stats_t;
+/*
+* FIELDS
+*	qp0_mads_outstanding
+*		Contains the number of MADs outstanding on QP0.
+*		When this value reaches zero, OpenSM has discovered all
+*		nodes on the subnet, and finished retrieving attributes.
+*		At that time, subnet configuration may begin.
+*		This variable must be manipulated using atomic instructions.
+*
+*	qp0_mads_outstanding_on_wire
+*		The number of MADs outstanding on the wire at any moment.
+*
+*	qp0_mads_rcvd
+*		Total number of QP0 MADs received.
+*
+*	qp0_mads_sent
+*		Total number of QP0 MADs sent.
+*
+*	qp0_unicasts_sent
+*		Total number of response-less MADs sent on the wire.  This count
+*		includes getresp(), send() and trap() methods.
+*
+*	qp0_mads_rcvd_unknown
+*		Total number of unknown QP0 MADs received. This includes
+*		unrecognized attribute IDs and methods.
+*
+*	sa_mads_outstanding
+*		Contains the number of SA MADs outstanding on QP1.
+*
+*	sa_mads_rcvd
+*		Total number of SA MADs received.
+*
+*	sa_mads_sent
+*		Total number of SA MADs sent.
+*
+*	sa_mads_rcvd_unknown
+*		Total number of unknown SA MADs received. This includes
+*		unrecognized attribute IDs and methods.
+*
+*	sa_mads_ignored
+*		Total number of SA MADs received because SM is not
+*		master or SM is in first time sweep.
+*
+* SEE ALSO
+***************/
+
+static inline uint32_t osm_stats_inc_qp0_outstanding(osm_stats_t *stats)
+{
+	uint32_t outstanding;
+
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_lock(&stats->mutex);
+	outstanding = ++stats->qp0_mads_outstanding;
+	pthread_mutex_unlock(&stats->mutex);
+#else
+	outstanding = cl_atomic_inc(&stats->qp0_mads_outstanding);
+#endif
+
+	return outstanding;
+}
+
+static inline uint32_t osm_stats_dec_qp0_outstanding(osm_stats_t *stats)
+{
+	uint32_t outstanding;
+
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_lock(&stats->mutex);
+	outstanding = --stats->qp0_mads_outstanding;
+	if (!outstanding)
+		pthread_cond_signal(&stats->cond);
+	pthread_mutex_unlock(&stats->mutex);
+#else
+	outstanding = cl_atomic_dec(&stats->qp0_mads_outstanding);
+	if (!outstanding)
+		cl_event_signal(&stats->event);
+#endif
+
+	return outstanding;
+}
+
+END_C_DECLS
+#endif				/* _OSM_STATS_H_ */
diff --git a/include/opensm/osm_subnet.h b/include/opensm/osm_subnet.h
new file mode 100644
index 0000000..d97d5f4
--- /dev/null
+++ b/include/opensm/osm_subnet.h
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *	Declaration of osm_subn_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SUBNET_H_
+#define _OSM_SUBNET_H_
+
+#include <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>
+#include <opensm/osm_prefix_route.h>
+#include <stdio.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;
+struct osm_qos_policy;
+
+/****h* OpenSM/Subnet
+* NAME
+*	Subnet
+*
+* DESCRIPTION
+*	The Subnet object encapsulates the information needed by the
+*	OpenSM to manage a subnet.  The OpenSM allocates one Subnet object
+*	per IBA subnet.
+*
+*	The Subnet object is not thread safe, thus callers must provide
+*	serialization.
+*
+*	This object is essentially a container for the various components
+*	of a subnet.  Callers may directly access the member variables.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Subnet/osm_qos_options_t
+* NAME
+*	osm_qos_options_t
+*
+* DESCRIPTION
+*	Subnet QoS options structure.  This structure contains the various
+*	QoS specific configuration parameters for the subnet.
+*
+* SYNOPSIS
+*/
+typedef struct osm_qos_options {
+	unsigned max_vls;
+	int high_limit;
+	char *vlarb_high;
+	char *vlarb_low;
+	char *sl2vl;
+} osm_qos_options_t;
+/*
+* FIELDS
+*
+*	max_vls
+*		The number of maximum VLs on the Subnet (0 == use default)
+*
+*	high_limit
+*		The limit of High Priority component of VL Arbitration
+*		table (IBA 7.6.9) (-1 == use default)
+*
+*	vlarb_high
+*		High priority VL Arbitration table template. (NULL == use default)
+*
+*	vlarb_low
+*		Low priority VL Arbitration table template. (NULL == use default)
+*
+*	sl2vl
+*		SL2VL Mapping table (IBA 7.6.6) template. (NULL == use default)
+*
+*********/
+
+/****s* OpenSM: Subnet/osm_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 {
+	char *config_file;
+	ib_net64_t guid;
+	ib_net64_t m_key;
+	ib_net64_t sm_key;
+	ib_net64_t sa_key;
+	ib_net64_t subnet_prefix;
+	ib_net16_t m_key_lease_period;
+	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 ignore_other_sm;
+	boolean_t single_thread;
+	boolean_t disable_multicast;
+	boolean_t force_log_flush;
+	uint8_t subnet_timeout;
+	uint8_t packet_life_time;
+	uint8_t vl_stall_count;
+	uint8_t leaf_vl_stall_count;
+	uint8_t head_of_queue_lifetime;
+	uint8_t leaf_head_of_queue_lifetime;
+	uint8_t local_phy_errors_threshold;
+	uint8_t overrun_errors_threshold;
+	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 qos;
+	char *qos_policy_file;
+	boolean_t accum_log_file;
+	char *console;
+	uint16_t console_port;
+	char *port_prof_ignore_file;
+	boolean_t port_profile_switch_nodes;
+	boolean_t sweep_on_trap;
+	char *routing_engine_names;
+	boolean_t use_ucast_cache;
+	boolean_t connect_roots;
+	char *lid_matrix_dump_file;
+	char *lfts_file;
+	char *root_guid_file;
+	char *cn_guid_file;
+	char *ids_guid_file;
+	char *guid_routing_order_file;
+	char *sa_db_file;
+	boolean_t exit_on_fatal;
+	boolean_t honor_guid2lid_file;
+	boolean_t daemon;
+	boolean_t sm_inactive;
+	boolean_t babbling_port_policy;
+	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;
+#ifdef ENABLE_OSM_PERF_MGR
+	boolean_t perfmgr;
+	boolean_t perfmgr_redir;
+	uint16_t perfmgr_sweep_time_s;
+	uint32_t perfmgr_max_outstanding_queries;
+	char *event_db_dump_file;
+#endif				/* ENABLE_OSM_PERF_MGR */
+	char *event_plugin_name;
+	char *node_name_map_name;
+	char *prefix_routes_file;
+	boolean_t consolidate_ipv6_snm_req;
+} osm_subn_opt_t;
+/*
+* FIELDS
+*
+*	config_file
+*		The name of the config file.
+*
+*	guid
+*		The port guid that the SM is binding to.
+*
+*	m_key
+*		M_Key value sent to all ports qualifying all Set(PortInfo).
+*
+*	sm_key
+*		SM_Key value of the SM used for SM authentication.
+*
+*	sa_key
+*		SM_Key value to qualify rcv SA queries as "trusted".
+*
+*	subnet_prefix
+*		Subnet prefix used on this subnet.
+*
+*	m_key_lease_period
+*		The lease period used for the M_Key on this subnet.
+*
+*	sweep_interval
+*		The number of seconds between subnet sweeps.  A value of 0
+*		disables sweeping.
+*
+*	max_wire_smps
+*		The maximum number of SMPs sent in parallel.  Default is 4.
+*
+*	transaction_timeout
+*		The maximum time in milliseconds allowed for a transaction
+*		to complete.  Default is 200.
+*
+*	sm_priority
+*		The priority of this SM as specified by the user.  This
+*		value is made available in the SMInfo attribute.
+*
+*	lmc
+*		The LMC value used on this subnet.
+*
+*	lmc_esp0
+*		Whether LMC value used on subnet should be used for
+*		enhanced switch port 0 or not.  If TRUE, it is used.
+*		Otherwise (the default), LMC is set to 0 for ESP0.
+*
+*	max_op_vls
+*		Limit the maximal operational VLs. default is 1.
+*
+*	reassign_lids
+*		If TRUE cause all lids to be re-assigend.
+*		Otherwise (the default),
+*		OpenSM always tries to preserve as LIDs as much as possible.
+*
+*	ignore_other_sm_option
+*		This flag is TRUE if other SMs on the subnet should be ignored.
+*
+*	disable_multicast
+*		This flag is TRUE if OpenSM should disable multicast support.
+*
+*	max_msg_fifo_timeout
+*		The maximal time a message can stay in the incoming message
+*		queue. If there is more than one message in the queue and the
+*		last message stayed in the queue more than this value the SA
+*		request will be immediately returned with a BUSY status.
+*
+*	subnet_timeout
+*		The subnet_timeout that will be set for all the ports in the
+*		design SubnSet(PortInfo.vl_stall_life))
+*
+*	vl_stall_count
+*		The number of sequential packets dropped that cause the port
+*		to enter the VLStalled state.
+*
+*	leaf_vl_stall_count
+*		The number of sequential packets dropped that cause the port
+*		to enter the VLStalled state. This is for switch ports driving
+*		a CA or router port.
+*
+*	head_of_queue_lifetime
+*		The maximal time a packet can live at the head of a VL queue
+*		on any port not driving a CA or router port.
+*
+*	leaf_head_of_queue_lifetime
+*		The maximal time a packet can live at the head of a VL queue
+*		on switch ports driving a CA or router.
+*
+*	local_phy_errors_threshold
+*		Threshold of local phy errors for sending Trap 129
+*
+*	overrun_errors_threshold
+*		Threshold of credits overrun errors for sending Trap 129
+*
+*	sminfo_polling_timeout
+*		Specifies the polling timeout (in milliseconds) - the timeout
+*		between one poll to another.
+*
+*	packet_life_time
+*		The maximal time a packet can stay in a switch.
+*		The value is send to all switches as
+*		SubnSet(SwitchInfo.life_state)
+*
+*	dump_files_dir
+*		The directory to be used for opensm-subnet.lst, opensm.fdbs,
+*		opensm.mcfdbs, and default log file (the latter for Windows,
+*		not Linux).
+*
+*	log_file
+*		Name of the log file (or NULL) for stdout.
+*
+*	log_max_size
+*		This option defines maximal log file size in MB. When
+*		specified the log file will be truncated upon reaching
+*		this limit.
+*
+*	qos
+*		Boolean that specifies whether the OpenSM QoS functionality
+*		should be off or on.
+*
+*	qos_policy_file
+*		Name of the QoS policy file.
+*
+*	accum_log_file
+*		If TRUE (default) - the log file will be accumulated.
+*		If FALSE - the log file will be erased before starting
+*		current opensm run.
+*
+*	port_prof_ignore_file
+*		Name of file with port guids to be ignored by port profiling.
+*
+*	port_profile_switch_nodes
+*		If TRUE will count the number of switch nodes routed through
+*		the link. If FALSE - only CA/RT nodes are counted.
+*
+*	sweep_on_trap
+*		Received traps will initiate a new sweep.
+*
+*	routing_engine_names
+*		Name of routing engine(s) to use.
+*
+*	connect_roots
+*		The option which will enforce root to root connectivity with
+*		up/down routing engine (even if this violates "pure" deadlock
+*		free up/down algorithm)
+*
+*	use_ucast_cache
+*		When TRUE enables unicast routing cache.
+*
+*	lid_matrix_dump_file
+*		Name of the lid matrix dump file from where switch
+*		lid matrices (min hops tables) will be loaded
+*
+*	lfts_file
+*		Name of the unicast LFTs routing file from where switch
+*		forwarding tables will be loaded
+*
+*	root_guid_file
+*		Name of the file that contains list of root guids that
+*		will be used by fat-tree or up/dn routing (provided by User)
+*
+*	cn_guid_file
+*		Name of the file that contains list of compute node guids that
+*		will be used by fat-tree routing (provided by User)
+*
+*	ids_guid_file
+*		Name of the file that contains list of ids which should be
+*		used by Up/Down algorithm instead of node GUIDs
+*
+*	guid_routing_order_file
+*		Name of the file that contains list of guids for routing order
+*		that will be used by minhop and up/dn routing (provided by User).
+*
+*	sa_db_file
+*		Name of the SA database file.
+*
+*	exit_on_fatal
+*		If TRUE (default) - SM will exit on fatal subnet initialization
+*		issues.
+*		If FALSE - SM will not exit.
+*		Fatal initialization issues:
+*		a. SM recognizes 2 different nodes with the same guid, or
+*		   12x link with lane reversal badly configured.
+*
+*	honor_guid2lid_file
+*		Always honor the guid2lid file if it exists and is valid. This
+*		means that the file will be honored when SM is coming out of
+*		STANDBY. By default this is FALSE.
+*
+*	daemon
+*		OpenSM will run in daemon mode.
+*
+*	sm_inactive
+*		OpenSM will start with SM in not active state.
+*
+*	babbling_port_policy
+*		OpenSM will enforce its "babbling" port policy.
+*
+*	perfmgr
+*		Enable or disable the performance manager
+*
+*	perfmgr_redir
+*		Enable or disable the saving of redirection by PerfMgr
+*
+*	perfmgr_sweep_time_s
+*		Define the period (in seconds) of PerfMgr sweeps
+*
+*       event_db_dump_file
+*               File to dump the event database to
+*
+*       event_db_plugin
+*               Specify the name of the event plugin
+*
+*	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 *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_qlist_t prefix_routes_list;
+	cl_qmap_t prtn_pkey_tbl;
+	cl_qmap_t sm_guid_tbl;
+	cl_qlist_t sa_sr_list;
+	cl_qlist_t sa_infr_list;
+	cl_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;
+	struct osm_qos_policy *p_qos_policy;
+	uint16_t max_ucast_lid_ho;
+	uint16_t max_mcast_lid_ho;
+	uint8_t min_ca_mtu;
+	uint8_t min_ca_rate;
+	boolean_t ignore_existing_lfts;
+	boolean_t subnet_initialization_error;
+	boolean_t force_heavy_sweep;
+	boolean_t force_reroute;
+	boolean_t in_sweep_hop_0;
+	boolean_t first_time_master_sweep;
+	boolean_t coming_out_of_standby;
+	unsigned need_update;
+	void *mgroups[IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1];
+} osm_subn_t;
+/*
+* FIELDS
+*	sw_guid_tbl
+*		Container of pointers to all Switch objects in the 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.
+*
+*	sm_guid_tbl
+*		Container of pointers to SM objects representing other SMs
+*		on the subnet.
+*
+*	port_lid_tbl
+*		Container of pointers to all Port objects in the 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.
+*
+*	p_qos_policy
+*		Subnet QoS policy structure.
+*
+*	max_ucast_lid_ho
+*		The minimal max unicast lid reported by all switches
+*
+*	max_mcast_lid_ho
+*		The minimal max multicast lid reported by all switches
+*
+*	min_ca_mtu
+*		The minimal MTU reported by all CAs ports on the subnet
+*
+*	min_ca_rate
+*		The minimal rate reported by all CA ports on the subnet
+*
+*	ignore_existing_lfts
+*		This flag is a dynamic flag to instruct the LFT assignment to
+*		ignore existing legal LFT settings.
+*		The value will be set according to :
+*		- Any change to the list of switches will set it to high
+*		- Coming out of STANDBY it will be cleared (other SM worked)
+*		- Set to FALSE upon end of all lft assignments.
+*
+*	subnet_initalization_error
+*		Similar to the force_heavy_sweep flag. If TRUE - means that
+*		we had errors during initialization (due to SubnSet requests
+*		that failed). We want to declare the subnet as unhealthy, and
+*		force another heavy sweep.
+*
+*	force_heavy_sweep
+*		If TRUE - we want to force a heavy sweep. This can be done
+*		either due to receiving of trap - meaning there is some change
+*		on the subnet, or we received a handover from a remote sm.
+*		In this case we want to sweep and reconfigure the entire
+*		subnet. This will cause another heavy sweep to occure when
+*		the current sweep is done.
+*
+*	force_reroute
+*		If TRUE - we want to force switches in the fabric to be
+*		rerouted.
+*
+*	in_sweep_hop_0
+*		When in_sweep_hop_0 flag is set to TRUE - this means we are
+*		in sweep_hop_0 - meaning we do not want to continue beyond
+*		the current node.
+*		This is relevant for the case of SM on switch, since in the
+*		switch info we need to signal somehow not to continue
+*		the sweeping.
+*
+*	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.
+*
+*	need_update
+*		This flag should be on during first non-master heavy
+*		(including pre-master discovery stage)
+*
+*	mgroups
+*		Array of pointers to all Multicast Group objects in the subnet.
+*		Indexed by MLID offset from base MLID.
+*
+* 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 *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;
+struct osm_mgrp;
+
+/****f* OpenSM: Helper/osm_get_gid_by_mad_addr
+* NAME
+*	osm_get_gid_by_mad_addr
+*
+* DESCRIPTION
+*	Looks for the requester gid in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_get_gid_by_mad_addr(IN struct osm_log *p_log,
+			IN const osm_subn_t * p_subn,
+			IN 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 ib_net64_t guid);
+/*
+* PARAMETERS
+*	p_subn
+*		[in] Pointer to an osm_subn_t object
+*
+*	guid
+*		[in] The port guid in network order
+*
+* RETURN VALUES
+*	The port structure pointer if found. NULL otherwise.
+*
+* SEE ALSO
+*	Subnet object, osm_subn_construct, osm_subn_destroy,
+*	osm_port_t
+*********/
+
+/****f* OpenSM: Subnet/osm_get_mgrp_by_mlid
+* NAME
+*	osm_get_mgrp_by_mlid
+*
+* DESCRIPTION
+*	The looks for the given multicast group in the subnet table by mlid.
+*	NOTE: this code is not thread safe. Need to grab the lock before
+*	calling it.
+*
+* SYNOPSIS
+*/
+static inline
+struct osm_mgrp *osm_get_mgrp_by_mlid(osm_subn_t const *p_subn, ib_net16_t mlid)
+{
+	return p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO];
+}
+/*
+* PARAMETERS
+*	p_subn
+*		[in] Pointer to an osm_subn_t object
+*
+*	mlid
+*		[in] The multicast group mlid in network order
+*
+* RETURN VALUES
+*	The multicast group structure pointer if found. NULL otherwise.
+*********/
+
+/****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_parse_conf_file
+* NAME
+*	osm_subn_parse_conf_file
+*
+* DESCRIPTION
+*	The osm_subn_parse_conf_file function parses the configuration file
+*	and sets the defaults accordingly.
+*
+* SYNOPSIS
+*/
+int osm_subn_parse_conf_file(char *conf_file, osm_subn_opt_t * const p_opt);
+/*
+* PARAMETERS
+*
+*	p_opt
+*		[in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*	0 on success, positive value if file doesn't exist,
+*	negative value otherwise
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_rescan_conf_files
+* NAME
+*	osm_subn_rescan_conf_files
+*
+* DESCRIPTION
+*	The osm_subn_rescan_conf_files function parses the configuration
+*	files and update selected subnet options
+*
+* SYNOPSIS
+*/
+int osm_subn_rescan_conf_files(IN osm_subn_t * const p_subn);
+/*
+* PARAMETERS
+*
+*	p_subn
+*		[in] Pointer to the subnet structure.
+*
+* RETURN VALUES
+*	0 on success, positive value if file doesn't exist,
+*	negative value otherwise
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_output_conf
+* NAME
+*	osm_subn_output_conf
+*
+* DESCRIPTION
+*	Output configuration info
+*
+* SYNOPSIS
+*/
+int osm_subn_output_conf(FILE *out, IN osm_subn_opt_t * const p_opt);
+/*
+* PARAMETERS
+*
+*	out
+*		[in] File stream to output to.
+*
+*	p_opt
+*		[in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*	0 on success, negative value otherwise
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_write_conf_file
+* NAME
+*	osm_subn_write_conf_file
+*
+* DESCRIPTION
+*	Write the configuration file into the cache
+*
+* SYNOPSIS
+*/
+int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t * const p_opt);
+/*
+* PARAMETERS
+*
+*	p_opt
+*		[in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*	0 on success, negative value otherwise
+*
+* NOTES
+*	Assumes the conf file is part of the cache dir which defaults to
+*	OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts
+*********/
+int osm_subn_verify_config(osm_subn_opt_t * const p_opt);
+
+END_C_DECLS
+#endif				/* _OSM_SUBNET_H_ */
diff --git a/include/opensm/osm_switch.h b/include/opensm/osm_switch.h
new file mode 100644
index 0000000..dbc22e5
--- /dev/null
+++ b/include/opensm/osm_switch.h
@@ -0,0 +1,1152 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_switch_t.
+ *	This object represents an IBA switch.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_SWITCH_H_
+#define _OSM_SWITCH_H_
+
+#include <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_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;
+	uint16_t max_lid_ho;
+	uint8_t num_ports;
+	uint16_t num_hops;
+	uint8_t **hops;
+	osm_port_profile_t *p_prof;
+	uint8_t *lft;
+	uint8_t *new_lft;
+	osm_mcast_tbl_t mcast_tbl;
+	uint32_t discovery_count;
+	unsigned need_update;
+	void *priv;
+} osm_switch_t;
+/*
+* FIELDS
+*	map_item
+*		Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*	p_node
+*		Pointer to the Node object for this switch.
+*
+*	switch_info
+*		IBA defined SwitchInfo structure for this switch.
+*
+*	max_lid_ho
+*		Max LID that is accessible from this switch.
+*
+*	num_ports
+*		Number of ports for this switch.
+*
+*	num_hops
+*		Size of hops table for this switch.
+*
+*	hops
+*		LID Matrix for this switch containing the hop count
+*		to every LID from every port.
+*
+*	p_prof
+*		Pointer to array of Port Profile objects for this switch.
+*
+*	lft
+*		This switch's linear forwarding table.
+*
+*	new_lft
+*		This switch's linear forwarding table, as was
+*		calculated by the last routing engine execution.
+*
+*	mcast_tbl
+*		Multicast forwarding table for this switch.
+*
+*	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.
+*
+*	need_update
+*		When set indicates that switch was probably reset, so
+*		fwd tables and rest cached data should be flushed
+*
+* SEE ALSO
+*	Switch object
+*********/
+
+/****s* OpenSM: Switch/struct osm_remote_guids_count
+* NAME
+*	struct osm_remote_guids_count
+*
+* DESCRIPTION
+*	Stores array of pointers to remote node and the numbers of
+*	times a switch has forwarded to it.
+*
+* SYNOPSIS
+*/
+struct osm_remote_guids_count {
+	unsigned count;
+	struct osm_remote_node {
+		osm_node_t *node;
+		unsigned forwarded_to;
+	} guids[0];
+};
+/*
+* FIELDS
+*	count
+*		A number of used entries in array.
+*
+*	node
+*		A pointer to node.
+*
+*	forwarded_to
+*		A count of lids forwarded to this node.
+*********/
+
+/****f* OpenSM: Switch/osm_switch_delete
+* NAME
+*	osm_switch_delete
+*
+* DESCRIPTION
+*	Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void osm_switch_delete(IN OUT osm_switch_t ** const pp_sw);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	Switch object, osm_switch_new
+*********/
+
+/****f* OpenSM: Switch/osm_switch_new
+* NAME
+*	osm_switch_new
+*
+* DESCRIPTION
+*	The osm_switch_new function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+osm_switch_t *osm_switch_new(IN osm_node_t * 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_delete
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_hop_count
+* NAME
+*	osm_switch_get_hop_count
+*
+* DESCRIPTION
+*	Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_hop_count(IN const osm_switch_t * const p_sw,
+			 IN const uint16_t lid_ho, IN const uint8_t port_num)
+{
+	return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
+	    OSM_NO_PATH : p_sw->hops[lid_ho][port_num];
+}
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to a Switch object.
+*
+*	lid_ho
+*		[in] LID value (host order) for which to return the hop count
+*
+*	port_num
+*		[in] Port number in the switch
+*
+* RETURN VALUES
+*	Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_hops
+* NAME
+*	osm_switch_set_hops
+*
+* DESCRIPTION
+*	Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+cl_status_t
+osm_switch_set_hops(IN osm_switch_t * const p_sw,
+		    IN const uint16_t lid_ho,
+		    IN const uint8_t port_num, IN const uint8_t num_hops);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to a Switch object.
+*
+*	lid_ho
+*		[in] LID value (host order) for which to set the count.
+*
+*	port_num
+*		[in] port number for which to set the count.
+*
+*	num_hops
+*		[in] value to assign to this entry.
+*
+* RETURN VALUES
+*	Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_clear_hops
+* NAME
+*	osm_switch_clear_hops
+*
+* DESCRIPTION
+*	Cleanup existing hops tables (lid matrix)
+*
+* SYNOPSIS
+*/
+void osm_switch_clear_hops(IN osm_switch_t * p_sw);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to a Switch object.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_least_hops
+* NAME
+*	osm_switch_get_least_hops
+*
+* DESCRIPTION
+*	Returns the number of hops in the short path to this lid from
+*	any port on the switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_least_hops(IN const osm_switch_t * const p_sw,
+			  IN const uint16_t lid_ho)
+{
+	return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
+	    OSM_NO_PATH : p_sw->hops[lid_ho][0];
+}
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to an osm_switch_t object.
+*
+*	lid_ho
+*		[in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+*	Returns the number of hops in the short path to this lid from
+*	any port on the switch.
+*
+* NOTES
+*
+* SEE ALSO
+*	Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_port_least_hops
+* NAME
+*	osm_switch_get_port_least_hops
+*
+* DESCRIPTION
+*	Returns the number of hops in the short path to this port from
+*	any port on the switch.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_switch_get_port_least_hops(IN const osm_switch_t * const p_sw,
+			       IN const osm_port_t * p_port);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to an osm_switch_t object.
+*
+*	p_port
+*		[in] Pointer to an osm_port_t object for which to
+*		retrieve the shortest hop count.
+*
+* RETURN VALUES
+*	Returns the number of hops in the short path to this lid from
+*	any port on the switch.
+*
+* NOTES
+*
+* SEE ALSO
+*	Switch object
+*********/
+
+/****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)
+{
+	if (lid_ho == 0 || lid_ho > IB_LID_UCAST_END_HO)
+		return OSM_NO_PATH;
+	return p_sw->lft[lid_ho];
+}
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to an osm_switch_t object.
+*
+*	lid_ho
+*		[in] LID (host order) for which to retrieve the shortest hop count.
+*
+* 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_switch_get_port_by_lid(p_sw, 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_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_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 cl_ntoh16(p_sw->switch_info.lin_top) / IB_SMP_DATA_SIZE;
+}
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*	Returns the maximum block ID (host order) of this switch.
+*
+* NOTES
+*
+* SEE ALSO
+*	Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_lft_block
+* NAME
+*	osm_switch_get_lft_block
+*
+* DESCRIPTION
+*	Retrieve a linear forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
+			 IN const uint16_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_lft_block
+* NAME
+*	osm_switch_set_lft_block
+*
+* DESCRIPTION
+*	Copies in the specified block into
+*	the switch's Linear Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_lft_block(IN osm_switch_t * const p_sw,
+			 IN const uint8_t * const p_block,
+			 IN const uint32_t block_num)
+{
+	uint16_t lid_start =
+		(uint16_t) (block_num * IB_SMP_DATA_SIZE);
+	CL_ASSERT(p_sw);
+
+	if (lid_start + IB_SMP_DATA_SIZE > IB_LID_UCAST_END_HO)
+		return IB_INVALID_PARAMETER;
+
+	memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
+	return IB_SUCCESS;
+}
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to the switch object.
+*
+*	p_block
+*		[in] Pointer to the forwarding table block.
+*
+*	block_num
+*		[in] Block number for this block
+*
+* RETURN VALUE
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_mft_block
+* NAME
+*	osm_switch_set_mft_block
+*
+* DESCRIPTION
+*	Sets a block of multicast port masks into the multicast table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_mft_block(IN osm_switch_t * 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 osm_port_t * p_port,
+			  IN const uint16_t lid_ho,
+			  IN unsigned start_from,
+			  IN const boolean_t ignore_existing,
+			  IN const boolean_t dor);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to the switch object.
+*
+*	p_port
+*		[in] Pointer to the port object for which to get a path
+*		advisory.
+*
+*	lid_ho
+*		[in] LID value (host order) for which to get a path advisory.
+*
+*	start_from
+*		[in] Port number from where to start balance counting.
+*
+*	ignore_existing
+*		[in] Set to cause the switch to choose the optimal route
+*		regardless of existing paths.
+*		If false, the switch will choose an existing route if one
+*		exists, otherwise will choose the optimal route.
+*
+*	dor
+*		[in] If TRUE, Dimension Order Routing will be done.
+*
+* 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 osm_port_t * p_port,
+				IN const uint16_t mlid_ho,
+				IN const boolean_t ignore_existing);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to the switch object.
+*
+*	p_port
+*		[in] Pointer to the port object for which to get
+*		the multicast path.
+*
+*	mlid_ho
+*		[in] MLID for the multicast group in question.
+*
+*	ignore_existing
+*		[in] Set to cause the switch to choose the optimal route
+*		regardless of existing paths.
+*		If false, the switch will choose an existing route if one exists,
+*		otherwise will choose the optimal route.
+*
+* RETURN VALUE
+*	Returns the recommended port on which to route this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size
+* NAME
+*	osm_switch_get_mcast_fwd_tbl_size
+*
+* DESCRIPTION
+*	Returns the number of entries available in the multicast forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_mcast_fwd_tbl_size(IN const osm_switch_t * 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
+*/
+int
+osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids);
+/*
+* PARAMETERS
+*	p_sw
+*		[in] Pointer to the Switch object.
+*
+*	max_lids
+*		[in] Max number of lids in the subnet.
+*
+* RETURN VALUE
+*	Returns zero on success, or negative value if an error occurred.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr
+* NAME
+*	osm_switch_get_mcast_tbl_ptr
+*
+* DESCRIPTION
+*	Returns a pointer to the switch's multicast table.
+*
+* SYNOPSIS
+*/
+static inline osm_mcast_tbl_t *osm_switch_get_mcast_tbl_ptr(IN const
+							    osm_switch_t *
+							    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
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_SWITCH_H_ */
diff --git a/include/opensm/osm_ucast_cache.h b/include/opensm/osm_ucast_cache.h
new file mode 100644
index 0000000..11335c7
--- /dev/null
+++ b/include/opensm/osm_ucast_cache.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2008      Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Header file that describes Unicast Cache functions.
+ *
+ * Environment:
+ * 	Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_UCAST_CACHE_H_
+#define _OSM_UCAST_CACHE_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.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
+
+struct osm_ucast_mgr;
+
+/****h* OpenSM/Unicast Manager/Unicast Cache
+* NAME
+*	Unicast Cache
+*
+* DESCRIPTION
+*	The Unicast Cache object encapsulates the information
+*	needed to cache and write unicast routing of the subnet.
+*
+*	The Unicast Cache object is NOT thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Yevgeny Kliteynik, Mellanox
+*
+*********/
+
+/****f* OpenSM: Unicast Cache/osm_ucast_cache_invalidate
+* NAME
+*	osm_ucast_cache_invalidate
+*
+* DESCRIPTION
+*	The osm_ucast_cache_invalidate function purges the
+*	unicast cache and marks the cache as invalid.
+*
+* SYNOPSIS
+*/
+void osm_ucast_cache_invalidate(struct osm_ucast_mgr *p_mgr);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to the ucast mgr object.
+*
+* RETURN VALUE
+*	This function does not return any value.
+*
+* NOTES
+*
+* SEE ALSO
+*	Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Cache/osm_ucast_cache_check_new_link
+* NAME
+*	osm_ucast_cache_check_new_link
+*
+* DESCRIPTION
+*	The osm_ucast_cache_check_new_link checks whether
+*	the newly discovered link still allows us to use
+*	cached unicast routing.
+*
+* SYNOPSIS
+*/
+void osm_ucast_cache_check_new_link(struct osm_ucast_mgr *p_mgr,
+				    osm_node_t * p_node_1, uint8_t port_num_1,
+				    osm_node_t * p_node_2, uint8_t port_num_2);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to the unicast manager object.
+*
+*	physp1
+*		[in] Pointer to the first physical port of the link.
+*
+*	physp2
+*		[in] Pointer to the second physical port of the link.
+*
+* RETURN VALUE
+*	This function does not return any value.
+*
+* NOTES
+*	The function checks whether the link was previously
+*	cached/dropped or is this a completely new link.
+*	If it decides that the new link makes cached routing
+*	invalid, the cache is purged and marked as invalid.
+*
+* SEE ALSO
+*	Unicast Cache object
+*********/
+
+/****f* OpenSM: Unicast Cache/osm_ucast_cache_add_link
+* NAME
+*	osm_ucast_cache_add_link
+*
+* DESCRIPTION
+*	The osm_ucast_cache_add_link adds link to the cache.
+*
+* SYNOPSIS
+*/
+void osm_ucast_cache_add_link(struct osm_ucast_mgr *p_mgr,
+			      osm_physp_t * physp1, osm_physp_t * physp2);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to the unicast manager object.
+*
+*	physp1
+*		[in] Pointer to the first physical port of the link.
+*
+*	physp2
+*		[in] Pointer to the second physical port of the link.
+*
+* RETURN VALUE
+*	This function does not return any value.
+*
+* NOTES
+*	Since the cache operates with ports and not links,
+*	the function adds two port entries (both sides of the
+*	link) to the cache.
+*	If it decides that the dropped link makes cached routing
+*	invalid, the cache is purged and marked as invalid.
+*
+* SEE ALSO
+*	Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Cache/osm_ucast_cache_add_node
+* NAME
+*	osm_ucast_cache_add_node
+*
+* DESCRIPTION
+*	The osm_ucast_cache_add_node adds node and all
+*	its links to the cache.
+*
+* SYNOPSIS
+*/
+void osm_ucast_cache_add_node(struct osm_ucast_mgr *p_mgr, osm_node_t * p_node);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to the unicast manager object.
+*
+*	p_node
+*		[in] Pointer to the node object that should be cached.
+*
+* RETURN VALUE
+*	This function does not return any value.
+*
+* NOTES
+*	If the function decides that the dropped node makes cached
+*	routing invalid, the cache is purged and marked as invalid.
+*
+* SEE ALSO
+*	Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Cache/osm_ucast_cache_process
+* NAME
+*	osm_ucast_cache_process
+*
+* DESCRIPTION
+*	The osm_ucast_cache_process function writes the
+*	cached unicast routing on the subnet switches.
+*
+* SYNOPSIS
+*/
+int osm_ucast_cache_process(struct osm_ucast_mgr *p_mgr);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to the unicast manager object.
+*
+* RETURN VALUE
+*	This function returns zero on sucess and non-zero
+*	value otherwise.
+*
+* NOTES
+*	Iterates through all the subnet switches and writes
+*	the LFTs that were calculated during the last routing
+*       engine execution to the switches.
+*
+* SEE ALSO
+*	Unicast Manager object
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_UCAST_CACHE_H_ */
diff --git a/include/opensm/osm_ucast_mgr.h b/include/opensm/osm_ucast_mgr.h
new file mode 100644
index 0000000..a040476
--- /dev/null
+++ b/include/opensm/osm_ucast_mgr.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_ucast_mgr_t.
+ *	This object represents the Unicast Manager object.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_UCAST_MGR_H_
+#define _OSM_UCAST_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_ucast_cache.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/Unicast Manager
+* NAME
+*	Unicast Manager
+*
+* DESCRIPTION
+*	The Unicast Manager object encapsulates the information
+*	needed to control unicast LID forwarding on the subnet.
+*
+*	The Unicast Manager object is thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+struct osm_sm;
+/****s* OpenSM: Unicast Manager/osm_ucast_mgr_t
+* NAME
+*	osm_ucast_mgr_t
+*
+* DESCRIPTION
+*	Unicast Manager structure.
+*
+*	This object should be treated as opaque and should
+*	be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_ucast_mgr {
+	struct osm_sm *sm;
+	osm_subn_t *p_subn;
+	osm_log_t *p_log;
+	cl_plock_t *p_lock;
+	cl_qlist_t port_order_list;
+	boolean_t is_dor;
+	boolean_t some_hop_count_set;
+	cl_qmap_t cache_sw_tbl;
+	boolean_t cache_valid;
+} osm_ucast_mgr_t;
+/*
+* FIELDS
+*	sm
+*		Pointer to the SM object.
+*
+*	p_subn
+*		Pointer to the Subnet object for this subnet.
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	p_lock
+*		Pointer to the serializing lock.
+*
+*	is_dor
+*		Dimension Order Routing (DOR) will be done
+*
+*	port_order_list
+*		List of ports ordered for routing.
+*
+*	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.
+*
+*	some_hop_count_set
+*		Initialized to FALSE at the beginning of each the min hop
+*		tables calculation iteration cycle, set to TRUE to indicate
+*		that some hop count changes were done.
+*
+*	cache_sw_tbl
+*		Cached switches table.
+*
+*	cache_valid
+*		TRUE if the unicast cache is valid.
+*
+* SEE ALSO
+*	Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_construct
+* NAME
+*	osm_ucast_mgr_construct
+*
+* DESCRIPTION
+*	This function constructs a Unicast Manager object.
+*
+* SYNOPSIS
+*/
+void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * 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 struct osm_sm * sm);
+/*
+* PARAMETERS
+*	p_mgr
+*		[in] Pointer to an osm_ucast_mgr_t object to initialize.
+*
+*	sm
+*		[in] Pointer to the SM object.
+*
+* RETURN VALUES
+*	IB_SUCCESS if the Unicast Manager object was initialized
+*	successfully.
+*
+* NOTES
+*	Allows calling other Unicast Manager methods.
+*
+* SEE ALSO
+*	Unicast Manager object, osm_ucast_mgr_construct,
+*	osm_ucast_mgr_destroy
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_set_fwd_table
+* NAME
+*	osm_ucast_mgr_set_fwd_table
+*
+* DESCRIPTION
+*	Setup forwarding table for the switch (from prepared new_lft).
+*
+* SYNOPSIS
+*/
+int 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
+*/
+int 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
+*/
+int 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 zero on success and negative value on failure.
+*
+* NOTES
+*	This function processes the subnet, configuring switch
+*	unicast forwarding tables.
+*
+* SEE ALSO
+*	Unicast Manager, Node Info Response Controller
+*********/
+END_C_DECLS
+#endif				/* _OSM_UCAST_MGR_H_ */
diff --git a/include/opensm/osm_version.h.in b/include/opensm/osm_version.h.in
new file mode 100644
index 0000000..d783245
--- /dev/null
+++ b/include/opensm/osm_version.h.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_VERSION_H_
+#define _OSM_VERSION_H_
+
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+*	OSM_VERSION
+*
+* DESCRIPTION
+*	The version string for OpenSM
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM @VERSION@"
+/********/
+
+#endif				/* _OSM_VERSION_H_ */
diff --git a/include/opensm/osm_vl15intf.h b/include/opensm/osm_vl15intf.h
new file mode 100644
index 0000000..028eec0
--- /dev/null
+++ b/include/opensm/osm_vl15intf.h
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_vl15_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#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 <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor_api.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_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.
+*
+* 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_destroy.
+*
+*	Calling osm_vl15_construct is a prerequisite to calling any other
+*	method except osm_vl15_init.
+*
+* SEE ALSO
+*	VL15 object, osm_vl15_init, osm_vl15_destroy
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_destroy
+* NAME
+*	osm_vl15_destroy
+*
+* DESCRIPTION
+*	The osm_vl15_destroy function destroys the object, releasing
+*	all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_destroy(IN osm_vl15_t * 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);
+/*
+* 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.
+*
+* RETURN VALUES
+*	IB_SUCCESS if the VL15 object was initialized successfully.
+*
+* NOTES
+*	Allows calling other VL15 methods.
+*
+* SEE ALSO
+*	VL15 object, osm_vl15_construct, osm_vl15_destroy
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_post
+* NAME
+*	osm_vl15_post
+*
+* DESCRIPTION
+*	Posts a MAD to the VL15 interface for transmission.
+*
+* SYNOPSIS
+*/
+void osm_vl15_post(IN osm_vl15_t * 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_ */
diff --git a/include/opensm/st.h b/include/opensm/st.h
new file mode 100644
index 0000000..30cc308
--- /dev/null
+++ b/include/opensm/st.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#include <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
+#define st_ptr_t unsigned long
+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 */
diff --git a/include/vendor/osm_mtl_bind.h b/include/vendor/osm_mtl_bind.h
new file mode 100644
index 0000000..3994d59
--- /dev/null
+++ b/include/vendor/osm_mtl_bind.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_BIND_H_
+#define _OSM_BIND_H_
+
+#include <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_
diff --git a/include/vendor/osm_pkt_randomizer.h b/include/vendor/osm_pkt_randomizer.h
new file mode 100644
index 0000000..5a8ef5f
--- /dev/null
+++ b/include/vendor/osm_pkt_randomizer.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_subn_t.
+ *	This object represents an IBA subnet.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_PKT_RANDOMIZER_H_
+#define _OSM_PKT_RANDOMIZER_H_
+
+#include <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_log.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
+/****h* OpenSM/Packet Randomizer
+* NAME
+*	Packet Randomizer
+*
+* DESCRIPTION
+*	The Packet Randomizer object encapsulates the information needed for
+*	randomly dropping packets for debug.
+*
+*	The Packet Randomizer object is not thread safe, thus callers must
+*	provide serialization.
+*
+* AUTHOR
+*	Yael Kalka, Mellanox
+*
+*********/
+/****d* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_t
+* NAME
+*	osm_pkt_randomizer_t
+*
+* DESCRIPTION
+*	Packet randomizer structure. This structure contains the various
+*  parameters needed by the packet randomizer.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkt_randomizer {
+	uint8_t osm_pkt_drop_rate;
+	uint8_t osm_pkt_num_unstable_links;
+	uint8_t osm_pkt_unstable_link_rate;
+	osm_dr_path_t *fault_dr_paths;
+	uint8_t num_paths_initialized;
+} osm_pkt_randomizer_t;
+
+/*
+* FIELDS
+*
+*  osm_pkt_drop_rate
+*     Used by the randomizer whether to drop a packet or not.
+*     Taken from the global variable OSM_PKT_DROP_RATE. If not given or
+*     if set to zero, the randomizer will not run.
+*
+*  osm_pkt_num_unstable_links
+*     The number of unstable links to be drawn.
+*     Taken from the global variable OSM_PKT_NUM_UNSTABLE_LINKS. default = 1.
+*
+*  osm_pkt_unstable_link_rate
+*     Used by the randomizer whether to add a packet to the unstable links
+*     list or not. Taken from the global variable OSM_PKT_UNSTABLE_LINK_RATE.
+*     default = 20.
+*
+*	fault_dr_path
+*		Array of osm_dr_path_t objects, that includes all the dr_paths
+*     that are marked as errored.
+*
+*  num_paths_initialized
+*     Describes the number of paths from the fault_dr_paths array that
+*     have already been initialized.
+*
+* SEE ALSO
+*	Packet Randomizer object
+*********/
+
+/****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_init
+* NAME
+*	osm_pkt_randomizer_init
+*
+* DESCRIPTION
+*	The osm_pkt_randomizer_init function initializes the Packet Randomizer object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkt_randomizer_init(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer,
+			IN osm_log_t * p_log);
+/*
+* PARAMETERS
+*  p_pkt_randomizer
+*     [in] Pointer to the Packet Randomizer object to be initialized.
+*
+*	p_log
+*		[in] Pointer to the log object.
+*
+* RETURN VALUE
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_destroy
+* NAME
+*	osm_pkt_randomizer_destroy
+*
+* DESCRIPTION
+*	The osm_pkt_randomizer_destroy function destroys the Packet Randomizer object.
+*
+* SYNOPSIS
+*/
+void
+osm_pkt_randomizer_destroy(IN osm_pkt_randomizer_t ** pp_pkt_randomizer,
+			   IN osm_log_t * p_log);
+/*
+* PARAMETERS
+*  p_pkt_randomizer
+*     [in] Pointer to the Packet Randomizer object to be destroyed.
+*
+*	p_log
+*		[in] Pointer to the log object.
+*
+* RETURN VALUE
+*	None
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_madw_drop
+* NAME
+*	osm_pkt_randomizer_madw_drop
+*
+* DESCRIPTION
+*	The osm_pkt_randomizer_madw_drop is base function of the packet
+*  randomizer.
+*  It decides according to different random criteria whether or not
+*  the packet received should be dropped (according to its dr_path).
+*  This function is relevant both for mads sent by the SM and mads
+*  received by the SM.
+*  It returns TRUE if the mad should be dropped, and FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_pkt_randomizer_mad_drop(IN osm_log_t * p_log,
+			    IN osm_pkt_randomizer_t * p_pkt_randomizer,
+			    IN const ib_mad_t * p_mad);
+/*
+* PARAMETERS
+*  p_subn
+*     [in] Pointer to the Subnet object for this subnet.
+*
+*	p_log
+*		[in] Pointer to the log object.
+*
+*  p_mad
+*     [in] Pointer to the ib_mad_t mad to be checked.
+*
+* RETURN VALUE
+*	TRUE if the mad should be dropped. FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_PKT_RANDOMIZER_H */
diff --git a/include/vendor/osm_ts_useraccess.h b/include/vendor/osm_ts_useraccess.h
new file mode 100644
index 0000000..d68c924
--- /dev/null
+++ b/include/vendor/osm_ts_useraccess.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include "ts_ib_useraccess.h"
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+typedef struct ib_user_mad_filter osm_ts_user_mad_filter;
+typedef struct ib_set_port_info_ioctl osm_ts_set_port_info_ioctl;
+typedef struct ib_get_port_info_ioctl osm_ts_get_port_info_ioctl;
+typedef struct ib_gid_entry_ioctl osm_ts_gid_entry_ioctl;
+
+END_C_DECLS
diff --git a/include/vendor/osm_umadt.h b/include/vendor/osm_umadt.h
new file mode 100644
index 0000000..129627d
--- /dev/null
+++ b/include/vendor/osm_umadt.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mad_wrapper_t.
+ *	This object represents the context wrapper for OpenSM MAD processing.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_UMADT_h_
+#define _OSM_UMADT_h_
+
+#include "iba/ib_types.h"
+#include <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_ */
diff --git a/include/vendor/osm_vendor.h b/include/vendor/osm_vendor.h
new file mode 100644
index 0000000..4d0ae4c
--- /dev/null
+++ b/include/vendor/osm_vendor.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Include file used by OpenSM to pull in the correct vendor file.
+ */
+
+/*
+  this is the generic include file which includes
+  the proper vendor specific file
+*/
+#include <opensm/osm_config.h>
+
+#if defined( OSM_VENDOR_INTF_TEST )
+#include <vendor/osm_vendor_test.h>
+#elif defined( OSM_VENDOR_INTF_UMADT )
+#include <vendor/osm_vendor_umadt.h>
+#elif defined( OSM_VENDOR_INTF_MTL )
+/* HACK - I do not know how to prevent complib from loading kernel H files */
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_TS )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_ANAFA )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_SIM )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_OPENIB )
+#include <vendor/osm_vendor_ibumad.h>
+#elif defined( OSM_VENDOR_INTF_AL )
+#include <vendor/osm_vendor_al.h>
+#elif
+#error No MAD Interface selected!
+#error Choose an interface in osm_config.h
+#endif
diff --git a/include/vendor/osm_vendor_al.h b/include/vendor/osm_vendor_al.h
new file mode 100644
index 0000000..e7371c9
--- /dev/null
+++ b/include/vendor/osm_vendor_al.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mad_wrapper_t.
+ *	This object represents the context wrapper for OpenSM MAD processing.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_VENDOR_AL_H_
+#define _OSM_VENDOR_AL_H_
+
+#include <iba/ib_types.h>
+#include <iba/ib_al.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_base.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/Vendor AL
+* NAME
+*	Vendor AL
+*
+* DESCRIPTION
+*
+*	The Vendor AL object is thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+*	Enable various hacks to compensate for bugs in external code...
+*
+*
+* AUTHOR
+*
+*
+*********/
+/****h* OpenSM/Vendor Access Layer (AL)
+* NAME
+*	Vendor AL
+*
+* DESCRIPTION
+*	This file is the vendor specific file for the AL Infiniband API.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+#define OSM_AL_SQ_SGE 256
+#define OSM_AL_RQ_SGE 256
+#define OSM_DEFAULT_RETRY_COUNT 3
+/* AL supports RMPP */
+#define VENDOR_RMPP_SUPPORT 1
+/****s* OpenSM: Vendor AL/osm_ca_info_t
+* NAME
+*   osm_ca_info_t
+*
+* DESCRIPTION
+* 	Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+/*
+* FIELDS
+*	guid
+*		Node GUID of the local CA.
+*
+*	attr_size
+*		Size of the CA attributes for this CA.
+*
+*	p_attr
+*		Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports
+* NAME
+*	osm_ca_info_get_num_ports
+*
+* DESCRIPTION
+*	Returns the number of ports owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info)
+{
+	return (p_ca_info->p_attr->num_ports);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+*	Returns the number of ports owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid
+* NAME
+*	osm_ca_info_get_port_guid
+*
+* DESCRIPTION
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info,
+			  IN const uint8_t index)
+{
+	return (p_ca_info->p_attr->p_port_attr[index].port_guid);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+*	index
+*		[in] Port "index" for which to retrieve the port GUID.
+*		The index is the offset into the ca's internal array
+*		of port attributes.
+*
+* RETURN VALUE
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_num
+* NAME
+*	osm_ca_info_get_port_num
+*
+* DESCRIPTION
+*	Returns the port number of the specified port owned by this CA.
+*	Port numbers start with 1 for HCA's.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_port_num(IN const osm_ca_info_t * const p_ca_info,
+			 IN const uint8_t index)
+{
+	return (p_ca_info->p_attr->p_port_attr[index].port_num);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+*	index
+*		[in] Port "index" for which to retrieve the port GUID.
+*		The index is the offset into the ca's internal array
+*		of port attributes.
+*
+* RETURN VALUE
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_ca_guid
+* NAME
+*	osm_ca_info_get_ca_guid
+*
+* DESCRIPTION
+*	Returns the GUID of the specified CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_ca_guid(IN const osm_ca_info_t * const p_ca_info)
+{
+	return (p_ca_info->p_attr->ca_guid);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+*	Returns the GUID of the specified CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+* 	handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor {
+	ib_al_handle_t h_al;
+	osm_log_t *p_log;
+	uint32_t ca_count;
+	osm_ca_info_t *p_ca_info;
+	uint32_t timeout;
+	ib_ca_handle_t h_ca;
+	ib_pd_handle_t h_pd;
+
+} osm_vendor_t;
+/*
+* FIELDS
+*	h_al
+*		Handle returned by AL open call (ib_open_al).
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	ca_count
+*		Number of CA's in the array pointed to by p_ca_info.
+*
+*	p_ca_info
+*		Pointer to dynamically allocated array of CA info objects.
+*
+*	h_pool
+*		MAD Pool handle returned by ib_create_mad_pool at init time.
+*
+*	timeout
+*		Transaction timeout time in milliseconds.
+*
+* SEE ALSO
+*********/
+
+#define OSM_BIND_INVALID_HANDLE 0
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+* 	handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef void *osm_bind_handle_t;
+/***********/
+
+/****s* OpenSM/osm_vend_wrap_t
+* NAME
+*   AL Vendor MAD Wrapper
+*
+* DESCRIPTION
+*	AL specific MAD wrapper. AL transport layer uses this for
+*	housekeeping.
+*
+* SYNOPSIS
+*********/
+typedef struct _osm_vend_wrap_t {
+	uint32_t size;
+	osm_bind_handle_t h_bind;
+	ib_mad_element_t *p_elem;
+	ib_av_handle_t h_av;
+	void *p_resp_madw;
+
+} osm_vend_wrap_t;
+/*
+* FIELDS
+*	size
+*		Size of the allocated MAD
+*
+*	h_bind
+*		Bind handle used on this transaction
+*
+*	p_elem
+*		Pointer to the mad element structure associated with
+*		this mad.
+*
+*	h_av
+*		Address vector handle used for this transaction.
+*
+*	p_resp_madw
+*		Pointer to the mad wrapper structure used to hold the pending
+*		reponse to the mad, if any.  If a response is expected, the
+*		wrapper for the reponse is allocated during the send call.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_AL_H_ */
diff --git a/include/vendor/osm_vendor_api.h b/include/vendor/osm_vendor_api.h
new file mode 100644
index 0000000..70eb6cc
--- /dev/null
+++ b/include/vendor/osm_vendor_api.h
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *  Specification of the OpenSM transport API. This API is OpenSM's view
+ *  of the Infiniband transport.
+ */
+
+#ifndef _OSM_VENDOR_API_H_
+#define _OSM_VENDOR_API_H_
+
+#include <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 vendor wrapper to the mad pool. It also means that the
+*   mad buffer is returned to the transport.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_put(IN osm_bind_handle_t h_bind,
+	       IN osm_vend_wrap_t * const p_vend_wrap);
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+*   p_vend_wrap
+*      [in] pointer to the mad vendor wrapper to put back into the pool.
+*
+* RETURN VALUE
+*   None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****i* OpenSM Vendor API/osm_vendor_local_lid_change
+* NAME
+*   osm_vendor_local_lid_change
+*
+* DESCRIPTION
+*  Notifies the vendor transport layer that the local address
+*  has changed.  This allows the vendor layer to perform housekeeping
+*  functions such as address vector updates.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind);
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+* RETURN VALUE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_sm
+* NAME
+*   osm_vendor_set_sm
+*
+* DESCRIPTION
+*  Modifies the port info for the bound port to set the "IS_SM" bit
+*  according to the value given (TRUE or FALSE).
+*
+* SYNOPSIS
+*/
+void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val);
+/*
+* PARAMETERS
+*   h_bind
+*     [in] bind handle for this port.
+*
+*   is_sm_val
+*     [in] If TRUE - will set the is_sm to TRUE, if FALSE - will set the
+*          the is_sm to FALSE.
+*
+* RETURN VALUE
+*  None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_debug
+* NAME
+*   osm_vendor_set_debug
+*
+* DESCRIPTION
+*  Modifies the vendor specific debug level.
+*
+* SYNOPSIS
+*/
+void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level);
+/*
+* PARAMETERS
+*   p_vend
+*     [in] vendor handle.
+*
+*   level
+*     [in] vendor specific debug level.
+*
+* RETURN VALUE
+*  None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_API_H_ */
diff --git a/include/vendor/osm_vendor_ibumad.h b/include/vendor/osm_vendor_ibumad.h
new file mode 100644
index 0000000..3a3f070
--- /dev/null
+++ b/include/vendor/osm_vendor_ibumad.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_VENDOR_UMAD_H_
+#define _OSM_VENDOR_UMAD_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+
+#include <infiniband/common.h>
+#include <infiniband/umad.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/Vendor Access Layer (UMAD)
+* NAME
+*	Vendor UMAD
+*
+* DESCRIPTION
+*	This file is the vendor specific file for the UMAD Infiniband API.
+*
+* AUTHOR
+*
+*
+*********/
+#define OSM_DEFAULT_RETRY_COUNT 3
+#define OSM_UMAD_MAX_CAS	32
+#define OSM_UMAD_MAX_PORTS_PER_CA	2
+/****s* OpenSM: Vendor UMAD/osm_ca_info_t
+* NAME
+*   osm_ca_info_t
+*
+* DESCRIPTION
+* 	Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+} osm_ca_info_t;
+/*
+* FIELDS
+*	guid
+*		Node GUID of the local CA.
+*
+*	attr_size
+*		Size of the CA attributes for this CA.
+*
+*	p_attr
+*		Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports
+* NAME
+*	osm_ca_info_get_num_ports
+*
+* DESCRIPTION
+*	Returns the number of ports owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info)
+{
+	return (p_ca_info->p_attr->num_ports);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+* RETURN VUMADUE
+*	Returns the number of ports owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor UMAD/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+* 	handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef void *osm_bind_handle_t;
+/***********/
+
+typedef struct _umad_match {
+	ib_net64_t tid;
+	void *v;
+	uint32_t version;
+} umad_match_t;
+
+#define DEFAULT_OSM_UMAD_MAX_PENDING	1000
+
+typedef struct vendor_match_tbl {
+	uint32_t last_version;
+	int max;
+	umad_match_t *tbl;
+} vendor_match_tbl_t;
+
+typedef struct _osm_vendor {
+	osm_log_t *p_log;
+	uint32_t ca_count;
+	osm_ca_info_t *p_ca_info;
+	uint32_t timeout;
+	int max_retries;
+	osm_bind_handle_t agents[UMAD_CA_MAX_AGENTS];
+	char ca_names[OSM_UMAD_MAX_CAS][UMAD_CA_NAME_LEN];
+	vendor_match_tbl_t mtbl;
+	umad_port_t umad_port;
+	pthread_mutex_t cb_mutex;
+	pthread_mutex_t match_tbl_mutex;
+	int umad_port_id;
+	void *receiver;
+	int issmfd;
+	char issm_path[256];
+} osm_vendor_t;
+
+#define OSM_BIND_INVALID_HANDLE 0
+
+typedef struct _osm_vend_wrap {
+	int agent;
+	int size;
+	int retries;
+	void *umad;
+	osm_bind_handle_t h_bind;
+} osm_vend_wrap_t;
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_UMAD_H_ */
diff --git a/include/vendor/osm_vendor_mlx.h b/include/vendor/osm_vendor_mlx.h
new file mode 100644
index 0000000..106e0b4
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_H_
+#define _OSMV_H_
+
+#include <sys/types.h>
+#include <opensm/osm_log.h>
+#include <complib/cl_qlist.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 reference
+*/
+struct _osm_pkt_randomizer;
+
+/* The structure behind the OSM Vendor handle */
+
+typedef struct _osm_vendor {
+
+	/* for holding common transport info - useful at ibmgt transport */
+	void *p_transport_info;
+
+	osm_log_t *p_log;
+
+	/* Uniform timeout for every ACK/single MAD */
+	uint32_t resp_timeout;
+
+	/* Uniform timeout for every rmpp transaction */
+	uint32_t ttime_timeout;
+
+	/* All the bind handles associated with the vendor */
+	cl_qlist_t bind_handles;
+
+	/* run randomizer flag */
+	boolean_t run_randomizer;
+
+	/* Packet Randomizer object */
+	struct _osm_pkt_randomizer *p_pkt_randomizer;
+
+} osm_vendor_t;
+
+/* Repeating the definitions in osm_vendor_api.h */
+
+typedef void *osm_bind_handle_t;
+
+typedef struct _osm_vend_wrap {
+	ib_mad_t *p_mad;
+} osm_vend_wrap_t;
+
+#ifndef OSM_BIND_INVALID_HANDLE
+#define OSM_BIND_INVALID_HANDLE NULL
+#endif
+
+END_C_DECLS
+#endif
diff --git a/include/vendor/osm_vendor_mlx_defs.h b/include/vendor/osm_vendor_mlx_defs.h
new file mode 100644
index 0000000..d4c2c30
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_defs.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_DEFS_H_
+#define _OSMV_DEFS_H_
+
+#include <vendor/osm_vendor_mlx_inout.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_mlx_txn.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
+/* The maximum number of outstanding MADs an RMPP sender can transmit */
+#define OSMV_RMPP_RECV_WIN       16
+/* The maximum number of retransmissions of the same MAD */
+#define OSMV_MAX_RETRANSMIT      3
+/* Transaction Timeout = OSMV_TXN_TIMEOUT_FACTOR * Response Timeout */
+#define OSMV_TXN_TIMEOUT_FACTOR  128
+/************/
+/****s* OSM Vendor: Types/osmv_bind_obj_t
+* NAME
+*	osmv_bind_obj_t
+*
+* DESCRIPTION
+*	The object managing a single bind context.
+*       The bind handle is a direct pointer to it.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_bind_obj {
+	/* Used to signal when the struct is being destroyed */
+	struct _osmv_bind_obj *magic_ptr;
+
+	 osm_vendor_t /*const */  * p_vendor;
+
+	uint32_t hca_hndl;
+	uint32_t port_num;
+
+	/* Atomic access protector */
+	cl_spinlock_t lock;
+
+	/* is_closing == TRUE --> the handle is being unbound */
+	boolean_t is_closing;
+
+	/* Event callbacks */
+	osm_vend_mad_recv_callback_t recv_cb;
+	osm_vend_mad_send_err_callback_t send_err_cb;
+	/* ... and their context */
+	void *cb_context;
+
+	/* A pool to manage MAD wrappers */
+	osm_mad_pool_t *p_osm_pool;
+
+	/* each subvendor implements its own transport mgr */
+	void *p_transp_mgr;
+
+	/* The transaction DB */
+	osmv_txn_mgr_t txn_mgr;
+
+} osmv_bind_obj_t;
+
+END_C_DECLS
+#endif				/* _OSMV_DEFS_H_ */
diff --git a/include/vendor/osm_vendor_mlx_dispatcher.h b/include/vendor/osm_vendor_mlx_dispatcher.h
new file mode 100644
index 0000000..ba83f30
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_dispatcher.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_MAD_DISPATCHER_H_
+#define _OSMV_MAD_DISPATCHER_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/*
+ * NAME
+ *   osmv_dispatch_mad
+ *
+ * DESCRIPTION
+ *   Lower-level MAD dispatcher.
+ *   Implements a switch between the following MAD consumers:
+ *   (1) Non-RMPP consumer (DATA)
+ *   (2) RMPP receiver     (DATA/ABORT/STOP)
+ *   (3) RMPP sender       (ACK/ABORT/STOP)
+ *
+ * PARAMETERS
+ *   h_bind                The bind handle
+ *   p_mad_buf             The 256 byte buffer of individual MAD
+ *   p_mad_addr            The MAD originator's address
+ */
+ib_api_status_t
+osmv_dispatch_mad(IN osm_bind_handle_t h_bind,
+		  IN const void *p_mad_buf,
+		  IN const osm_mad_addr_t * p_mad_addr);
+
+END_C_DECLS
+#endif
diff --git a/include/vendor/osm_vendor_mlx_hca.h b/include/vendor/osm_vendor_mlx_hca.h
new file mode 100644
index 0000000..9b56943
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_hca.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_HCA_H_
+#define _OSMV_HCA_H_
+
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_mlx_inout.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#if defined( OSM_VENDOR_INTF_TS_NO_VAPI ) || defined( OSM_VENDOR_INTF_SIM )
+#define VAPI_hca_hndl_t uint32_t
+#define VAPI_hca_id_t char*
+#endif
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t const *p_vend,
+				IN ib_net64_t const guid,
+				OUT uint32_t * p_hca_hndl,
+				OUT char *p_hca_id,
+				OUT uint8_t * p_hca_idx,
+				OUT uint32_t * p_port_num);
+
+END_C_DECLS
+#endif				/* _OSMV_HCA_H_ */
diff --git a/include/vendor/osm_vendor_mlx_inout.h b/include/vendor/osm_vendor_mlx_inout.h
new file mode 100644
index 0000000..868639b
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_inout.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_INOUT_H_
+#define _OSMV_INOUT_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#ifdef IN
+#undef IN
+#endif
+#ifdef OUT
+#undef OUT
+#endif
+#ifndef OSM_VENDOR_INTF_ANAFA
+#ifndef OSM_VENDOR_INTF_TS_NO_VAPI
+#ifndef OSM_VENDOR_INTF_SIM
+#include <mtl_common.h>
+#endif
+#endif
+#endif
+#ifndef IN
+#define IN
+#endif
+#ifndef OUT
+#define OUT
+#endif
+#ifndef OSM_VENDOR_INTF_TS_NO_VAPI
+#ifndef OSM_VENDOR_INTF_ANAFA
+#ifndef OSM_VENDOR_INTF_SIM
+#include <vapi_types.h>
+#include <evapi.h>
+#endif
+#endif
+#endif
+END_C_DECLS
+#endif				/* _OSMV_INOUT_H_ */
diff --git a/include/vendor/osm_vendor_mlx_rmpp_ctx.h b/include/vendor/osm_vendor_mlx_rmpp_ctx.h
new file mode 100644
index 0000000..dac1f13
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_rmpp_ctx.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_RMPP_CTX_H
+#define _OSMV_RMPP_CTX_H
+
+#include <complib/cl_event.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <vendor/osm_vendor_mlx_sar.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 _osmv_rmpp_send_ctx {
+
+	uint8_t status;
+
+	uint32_t window_first;
+	uint32_t window_last;
+
+	uint32_t mad_sz;
+	boolean_t is_sa_mad;
+
+	cl_event_t event;
+
+	/* Segmentation engine */
+	osmv_rmpp_sar_t sar;
+	osm_log_t *p_log;
+
+} osmv_rmpp_send_ctx_t;
+
+typedef struct _osmv_rmpp_recv_ctx {
+
+	boolean_t is_sa_mad;
+
+	uint32_t expected_seg;
+
+	/* Reassembly buffer */
+	cl_qlist_t *p_rbuf;
+
+	/* Reassembly engine */
+	osmv_rmpp_sar_t sar;
+	osm_log_t *p_log;
+
+} osmv_rmpp_recv_ctx_t;
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_init
+ *
+ * DESCRIPTION
+ *  c'tor for rmpp_send_ctx obj
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *arbt_mad,
+			uint32_t mad_sz, osm_log_t * p_log);
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_done
+ *
+ * DESCRIPTION
+ *  d'tor for rmpp_send_ctx obj
+ *
+ * SEE ALSO
+ *
+ */
+void osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * ctx);
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_get_wf
+ *
+ * DESCRIPTION
+ *  returns number of first segment in current window
+ * SEE ALSO
+ *
+ */
+static inline uint32_t
+osmv_rmpp_send_ctx_get_wf(IN const osmv_rmpp_send_ctx_t * p_ctx)
+{
+	CL_ASSERT(p_ctx);
+	return p_ctx->window_first;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_set_wf
+ *
+ * DESCRIPTION
+ *  sets number of first segment in current window
+ * SEE ALSO
+ *
+ */
+static inline void
+osmv_rmpp_send_ctx_set_wf(IN osmv_rmpp_send_ctx_t * p_ctx, IN uint32_t val)
+{
+	CL_ASSERT(p_ctx);
+	p_ctx->window_first = val;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_get_wl
+ *
+ * DESCRIPTION
+ *  returns number of last segment in current window
+ * SEE ALSO
+ *
+ */
+static inline uint32_t
+osmv_rmpp_send_ctx_get_wl(IN const osmv_rmpp_send_ctx_t * p_send_ctx)
+{
+	CL_ASSERT(p_send_ctx);
+	return p_send_ctx->window_last;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_set_wl
+ *
+ * DESCRIPTION
+ *  sets number of last segment in current window
+ * SEE ALSO
+ *
+ */
+static inline void
+osmv_rmpp_send_ctx_set_wl(IN osmv_rmpp_send_ctx_t * p_ctx, IN uint32_t val)
+{
+	CL_ASSERT(p_ctx);
+	p_ctx->window_last = val;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_get_num_segs
+ *
+ * DESCRIPTION
+ *   returns the total number of mad segments to send
+ * SEE ALSO
+ *
+ */
+uint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx);
+
+/*
+ * NAME
+ *   osmv_rmpp_send_ctx_get_seg
+ *
+ * DESCRIPTION
+ *   Retrieves the mad segment by seg number (including setting the mad relevant bits & hdrs)
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx,
+			   IN uint32_t seg_idx, IN uint32_t resp_timeout,
+			   OUT void *p_mad);
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_init
+ *
+ * DESCRIPTION
+ *   c'tor for rmpp_recv_ctx obj
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log);
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_done
+ *
+ * DESCRIPTION
+ *   d'tor for rmpp_recv_ctx obj
+ * SEE ALSO
+ *
+ */
+void osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx);
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_get_es
+ *
+ * DESCRIPTION
+ *   retrunes index of expected segement in the curr window
+ *
+ */
+static inline uint32_t
+osmv_rmpp_recv_ctx_get_es(IN const osmv_rmpp_recv_ctx_t * p_recv_ctx)
+{
+	CL_ASSERT(p_recv_ctx);
+	return p_recv_ctx->expected_seg;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_set_es
+ *
+ * DESCRIPTION
+ *   sets index of expected segement in the curr window
+ *
+ */
+static inline void
+osmv_rmpp_recv_ctx_set_es(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN uint32_t val)
+{
+	CL_ASSERT(p_recv_ctx);
+	p_recv_ctx->expected_seg = val;
+}
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_store_madw_seg
+ *
+ * DESCRIPTION
+ *  stores rmpp mad in the list
+ *
+ */
+ib_api_status_t
+osmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx,
+				 IN void *p_mad);
+
+uint32_t
+osmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx);
+
+uint32_t
+osmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t *
+					   p_recv_ctx);
+
+uint32_t
+osmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx);
+
+/*
+ * NAME
+ *   osmv_rmpp_recv_ctx_reassemble_arbt_mad
+ *
+ * DESCRIPTION
+ *  reassembles all rmpp buffs to one big arbitrary mad
+ */
+ib_api_status_t
+osmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx,
+				       IN uint32_t size, IN void *p_arbt_mad);
+
+END_C_DECLS
+#endif
diff --git a/include/vendor/osm_vendor_mlx_sar.h b/include/vendor/osm_vendor_mlx_sar.h
new file mode 100644
index 0000000..a65b4f2
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_sar.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_SAR_H_
+#define _OSMV_SAR_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.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 _osmv_rmpp_sar {
+	void *p_arbt_mad;
+	uint32_t data_len;	/* total data len in all the mads */
+	/* these data members contain only constants */
+	uint32_t hdr_sz;
+	uint32_t data_sz;	/*typical data sz for this kind of mad (sa or regular */
+
+} osmv_rmpp_sar_t;
+
+/*
+ * NAME
+ *   osmv_rmpp_sar_alloc
+ *
+ * DESCRIPTION
+ *   c'tor for rmpp_sar object
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_sar_init(osmv_rmpp_sar_t * p_sar, void *p_arbt_mad,
+		   uint32_t mad_size, boolean_t is_sa_mad);
+
+/*
+ * NAME
+ *   osmv_rmpp_sar_dealloc
+ *
+ * DESCRIPTION
+ *   d'tor for rmpp_sar object
+ *
+ * SEE ALSO
+ *
+ */
+void osmv_rmpp_sar_done(osmv_rmpp_sar_t * p_sar);
+
+/*
+ * NAME
+ *   osmv_rmpp_sar_get_mad_seg
+ *
+ * DESCRIPTION
+ *  segments the original mad buffer . returnes a mad with the data of the i-th segment
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_sar_get_mad_seg(osmv_rmpp_sar_t * p_sar, uint32_t seg_idx,
+			  void *p_buf);
+
+/*
+ * NAME
+ *   osmv_rmpp_sar_reassemble_arbt_mad
+ *
+ * DESCRIPTION
+ *  gets a qlist of mads and reassmbles to one big mad buffer
+ *  ALSO - deallocates the mad list
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_rmpp_sar_reassemble_arbt_mad(osmv_rmpp_sar_t * p_sar, cl_qlist_t * p_bufs);
+
+END_C_DECLS
+#endif				/* _OSMV_SAR_H_ */
diff --git a/include/vendor/osm_vendor_mlx_sender.h b/include/vendor/osm_vendor_mlx_sender.h
new file mode 100644
index 0000000..e849744
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_sender.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_RMPP_SENDER_H_
+#define _OSMV_RMPP_SENDER_H_
+
+#include <vendor/osm_vendor_mlx.h>
+#include <vendor/osm_vendor_mlx_txn.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
+/****d* OSM Vendor/osmv_simple_send_madw
+ * NAME
+ *   osmv_simple_send_madw
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 bytes).
+ *
+ *   If this MAD requires a response, set the timeout event.
+ *   The function call returns when the MAD's send completion is received.
+ *
+ */
+ib_api_status_t
+osmv_simple_send_madw(IN osm_bind_handle_t h_bind,
+		      IN osm_madw_t * const p_madw,
+		      IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry);
+
+/****d* OSM Vendor/osmv_rmpp_send_madw
+ * NAME
+ *   osmv_rmpp_send_madw
+ *
+ * DESCRIPTION
+ *	Send a single MAD wrapper (of arbitrary length).
+ *      Follow the RMPP semantics
+ *      (segmentation, send window, timeouts etc).
+ *
+ *      The function call returns either when the whole MAD
+ *      has been acknowledged, or upon error.
+ */
+ib_api_status_t
+osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind,
+		    IN osm_madw_t * const p_madw,
+		    IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds);
+
+/*
+ *  NAME            osmv_rmpp_send_ack
+ *
+ *  DESCRIPTION
+ */
+
+ib_api_status_t
+osmv_rmpp_send_ack(IN osm_bind_handle_t h_bind,
+		   IN const ib_mad_t * p_req_mad,
+		   IN uint32_t seg_num,
+		   IN uint32_t nwl, IN const osm_mad_addr_t * p_mad_addr);
+
+/*
+ *  NAME           osmv_rmpp_send_nak
+ *
+ *  DESCRIPTION    Send the RMPP ABORT or STOP packet
+ */
+
+ib_api_status_t
+osmv_rmpp_send_nak(IN osm_bind_handle_t h_bind,
+		   IN const ib_mad_t * p_req_mad,
+		   IN const osm_mad_addr_t * p_mad_addr,
+		   IN uint8_t nak_type, IN uint8_t status);
+
+/*
+ *  NAME           osmv_rmpp_snd_error
+ *
+ *  DESCRIPTION    Mark an error status and signal the sender thread to handle it
+ */
+
+static inline void
+osmv_rmpp_snd_error(IN osmv_rmpp_send_ctx_t * p_send_ctx,
+		    IN ib_api_status_t status)
+{
+	p_send_ctx->status = status;
+
+	/* Release the thread waiting on send()
+	 * It will release the transaction's context
+	 */
+	cl_event_signal(&p_send_ctx->event);
+}
+
+END_C_DECLS
+#endif				/* _OSMV_RMPP_SENDER_H_ */
diff --git a/include/vendor/osm_vendor_mlx_svc.h b/include/vendor/osm_vendor_mlx_svc.h
new file mode 100644
index 0000000..f23a77d
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_svc.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_SVC_H_
+#define _OSMV_SVC_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <vendor/osm_vendor_mlx_defs.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
+inline static boolean_t osmv_mad_is_response(IN const ib_mad_t * p_mad)
+{
+	return (ib_mad_is_response(p_mad) ||
+		(p_mad->method == IB_MAD_METHOD_TRAP_REPRESS));
+}
+
+inline static uint8_t osmv_invert_method(IN uint8_t req_method)
+{
+	switch (req_method) {
+	case IB_MAD_METHOD_GET_RESP:
+		/* Not a 1-1 mapping! */
+		return IB_MAD_METHOD_GET;
+
+	case IB_MAD_METHOD_GET:
+		return IB_MAD_METHOD_GET_RESP;
+
+	case IB_MAD_METHOD_SET:
+		return IB_MAD_METHOD_GET_RESP;
+
+	case IB_MAD_METHOD_GETTABLE_RESP:
+		return IB_MAD_METHOD_GETTABLE;
+
+	case IB_MAD_METHOD_GETTABLE:
+		return IB_MAD_METHOD_GETTABLE_RESP;
+
+	case IB_MAD_METHOD_GETMULTI_RESP:
+		/* Not a 1-1 mapping! */
+		return IB_MAD_METHOD_GETMULTI;
+
+	case IB_MAD_METHOD_GETTRACETABLE:
+	case IB_MAD_METHOD_GETMULTI:
+		return IB_MAD_METHOD_GETMULTI_RESP;
+
+	case IB_MAD_METHOD_TRAP:
+		return IB_MAD_METHOD_TRAP_REPRESS;
+
+	case IB_MAD_METHOD_TRAP_REPRESS:
+		return IB_MAD_METHOD_TRAP;
+
+	case IB_MAD_METHOD_REPORT:
+		return IB_MAD_METHOD_REPORT_RESP;
+
+	case IB_MAD_METHOD_REPORT_RESP:
+		return IB_MAD_METHOD_REPORT;
+
+		/*  IB_MAD_METHOD_SEND does not have a response */
+	case IB_MAD_METHOD_SEND:
+		return IB_MAD_METHOD_SEND;
+
+	default:
+		CL_ASSERT(FALSE);
+	}
+
+	return 0;		/* Just make the compiler happy */
+}
+
+inline static boolean_t osmv_mad_is_rmpp(IN const ib_mad_t * p_mad)
+{
+	uint8_t rmpp_flags;
+	CL_ASSERT(NULL != p_mad);
+
+	rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags;
+	/* HACK - JUST SA and DevMgt for now - need to add BIS and DevAdm */
+	if ((p_mad->mgmt_class != IB_MCLASS_SUBN_ADM) &&
+	    (p_mad->mgmt_class != IB_MCLASS_DEV_MGMT))
+		return (0);
+	return (0 != (rmpp_flags & IB_RMPP_FLAG_ACTIVE));
+}
+
+inline static boolean_t osmv_mad_is_multi_resp(IN const ib_mad_t * p_mad)
+{
+	CL_ASSERT(NULL != p_mad);
+	return (IB_MAD_METHOD_GETMULTI == p_mad->method
+		|| IB_MAD_METHOD_GETTRACETABLE == p_mad->method);
+}
+
+inline static boolean_t osmv_mad_is_sa(IN const ib_mad_t * p_mad)
+{
+	CL_ASSERT(NULL != p_mad);
+	return (IB_MCLASS_SUBN_ADM == p_mad->mgmt_class);
+}
+
+inline static boolean_t osmv_rmpp_is_abort_stop(IN const ib_mad_t * p_mad)
+{
+	uint8_t rmpp_type;
+	CL_ASSERT(p_mad);
+
+	rmpp_type = ((ib_rmpp_mad_t *) p_mad)->rmpp_type;
+	return (IB_RMPP_TYPE_STOP == rmpp_type
+		|| IB_RMPP_TYPE_ABORT == rmpp_type);
+}
+
+inline static boolean_t osmv_rmpp_is_data(IN const ib_mad_t * p_mad)
+{
+	CL_ASSERT(p_mad);
+	return (IB_RMPP_TYPE_DATA == ((ib_rmpp_mad_t *) p_mad)->rmpp_type);
+}
+
+inline static boolean_t osmv_rmpp_is_ack(IN const ib_mad_t * p_mad)
+{
+	CL_ASSERT(p_mad);
+	return (IB_RMPP_TYPE_ACK == ((ib_rmpp_mad_t *) p_mad)->rmpp_type);
+}
+
+inline static boolean_t osmv_rmpp_is_first(IN const ib_mad_t * p_mad)
+{
+	uint8_t rmpp_flags;
+	CL_ASSERT(NULL != p_mad);
+
+	rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags;
+	return (0 != (IB_RMPP_FLAG_FIRST & rmpp_flags));
+}
+
+inline static boolean_t osmv_rmpp_is_last(IN const ib_mad_t * p_mad)
+{
+	uint8_t rmpp_flags;
+	CL_ASSERT(NULL != p_mad);
+
+	rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags;
+	return (0 != (IB_RMPP_FLAG_LAST & rmpp_flags));
+}
+
+inline static uint8_t *osmv_mad_copy(IN const ib_mad_t * p_mad)
+{
+	uint8_t *p_copy;
+
+	CL_ASSERT(p_mad);
+	p_copy = malloc(MAD_BLOCK_SIZE);
+
+	if (NULL != p_copy) {
+		memset(p_copy, 0, MAD_BLOCK_SIZE);
+		memcpy(p_copy, p_mad, MAD_BLOCK_SIZE);
+	}
+
+	return p_copy;
+}
+
+/* Should be passed externally from the Makefile */
+/*  #define OSMV_RANDOM_DROP 1 */
+#define OSMV_DROP_RATE   0.3
+
+inline static boolean_t osmv_random_drop(void)
+{
+	srand(1);		/* Pick a new base */
+	return (rand() / (double)RAND_MAX < OSMV_DROP_RATE);
+}
+
+END_C_DECLS
+#endif				/* _OSMV_SVC_H_ */
diff --git a/include/vendor/osm_vendor_mlx_transport.h b/include/vendor/osm_vendor_mlx_transport.h
new file mode 100644
index 0000000..2840e49
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_transport.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/**
+ *  FILE                   osmv_transport.h
+ *  AUTHOR                 Edward Bortnikov
+ *
+ *  DESCRIPTION
+ *     The lower-level MAD transport interface implementation
+ *     that allows sending a single MAD/receiving a callback
+ *     when a single MAD is received.
+*/
+
+#ifndef _OSMV_TRANSPORT_H_
+#define _OSMV_TRANSPORT_H_
+
+#include <vendor/osm_vendor_mlx.h>
+#include <vendor/osm_vendor_mlx_defs.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/*
+ * NAME
+ *   osmv_transport_init
+ *
+ * DESCRIPTION
+ *   Setup the MAD transport infrastructure (filters, callbacks etc).
+ */
+#define VENDOR_HCA_MAXNAMES 32
+ib_api_status_t
+osmv_transport_init(IN osm_bind_info_t * p_info,
+		    IN char hca_id[VENDOR_HCA_MAXNAMES],
+		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo);
+
+/*
+ * NAME
+ *   osmv_transport_send_mad
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 byte)
+ */
+ib_api_status_t
+osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
+			IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr);
+
+/*
+ * NAME
+ *   osmv_transport_done
+ *
+ * DESCRIPTION
+ *   deallocator of transportation infrastructure
+ */
+void osmv_transport_done(IN const osm_bind_handle_t h_bind);
+
+END_C_DECLS
+#endif				/* _OSMV_TRANSPORT_H_ */
diff --git a/include/vendor/osm_vendor_mlx_transport_anafa.h b/include/vendor/osm_vendor_mlx_transport_anafa.h
new file mode 100644
index 0000000..dac26ed
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_transport_anafa.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/**
+ *  FILE                   osmv_transport.h
+ *  AUTHOR                 Edward Bortnikov
+ *
+ *  DESCRIPTION
+ *     The lower-level MAD transport interface implementation
+ *     that allows sending a single MAD/receiving a callback
+ *     when a single MAD is received.
+*/
+
+#ifndef _OSMV_TRANSPORT_ANAFA_H_
+#define _OSMV_TRANSPORT_ANAFA_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+#define OSMV_ANAFA_ID 0
+typedef struct _osmv_TOPSPIN_ANAFA_transport_mgr_ {
+	int device_fd;
+	cl_thread_t receiver;
+} osmv_TOPSPIN_ANAFA_transport_mgr_t;
+
+typedef struct _osmv_TOPSPIN_ANAFA_transport_info_ {
+	int device_fd;
+} osmv_TOPSPIN_ANAFA_transport_info_t;
+
+END_C_DECLS
+#endif				/* _OSMV_TRANSPORT_ANAFA_H_ */
diff --git a/include/vendor/osm_vendor_mlx_txn.h b/include/vendor/osm_vendor_mlx_txn.h
new file mode 100644
index 0000000..ce59191
--- /dev/null
+++ b/include/vendor/osm_vendor_mlx_txn.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSMV_TXN_H_
+#define _OSMV_TXN_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_madw.h>
+#include <complib/cl_event_wheel.h>
+
+#include <vendor/osm_vendor_mlx_rmpp_ctx.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 enum _osmv_txn_rmpp_state {
+
+	OSMV_TXN_RMPP_NONE = 0,	/* Not part of RMPP transaction */
+
+	OSMV_TXN_RMPP_SENDER,
+	OSMV_TXN_RMPP_RECEIVER
+} osmv_txn_rmpp_state_t;
+
+typedef struct _osmv_rmpp_txfr {
+
+	osmv_txn_rmpp_state_t rmpp_state;
+	boolean_t is_rmpp_init_by_peer;
+	osmv_rmpp_send_ctx_t *p_rmpp_send_ctx;
+	osmv_rmpp_recv_ctx_t *p_rmpp_recv_ctx;
+
+} osmv_rmpp_txfr_t;
+
+typedef struct _osmv_txn_ctx {
+
+	/* The original Transaction ID */
+	uint64_t tid;
+	/* The key by which the Transaction is stored */
+	uint64_t key;
+
+	/* RMPP Send/Receive contexts, if applicable */
+	osmv_rmpp_txfr_t rmpp_txfr;
+
+	/* A MAD that was sent during the transaction (request or response) */
+	osm_madw_t *p_madw;
+
+	/* Reference to a log to enable tracing */
+	osm_log_t *p_log;
+
+} osmv_txn_ctx_t;
+
+typedef struct _osmv_txn_mgr {
+
+	/* Container of all the transactions */
+	cl_qmap_t *p_txn_map;
+
+	/* The timeouts DB */
+	cl_event_wheel_t *p_event_wheel;
+
+	/* Reference to a log to enable tracing */
+	osm_log_t *p_log;
+
+} osmv_txn_mgr_t;
+
+/* *    *   *   *   *   *   osmv_txn_ctx_t functions  *    *   *   *   *   *   *   *   */
+
+/*
+ * NAME
+ *   osmv_txn_init
+ *
+ * DESCRIPTION
+ *   allocs & inits the osmv_txn_ctx obj and insert it into the db
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_init(IN osm_bind_handle_t h_bind,
+	      IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
+
+/*
+ * NAME
+ *   osmv_rmpp_txfr_init_sender
+ *
+ * DESCRIPTION
+ *   init the rmpp send ctx in the transaction
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,
+			  IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw);
+
+/*
+ * NAME
+ *   osmv_rmpp_txfr_init_receiver
+ *
+ * DESCRIPTION
+ *   init the rmpp recv ctx in the transaction
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,
+			    IN osmv_txn_ctx_t * p_txn,
+			    IN boolean_t is_init_by_peer);
+
+/*
+ * NAME
+ *   osmv_txn_done
+ *
+ * DESCRIPTION
+ *   destroys txn object and removes it from the db
+ *
+ * SEE ALSO
+ *
+ */
+void
+osmv_txn_done(IN osm_bind_handle_t h_bind,
+	      IN uint64_t key, IN boolean_t is_in_cb);
+/*
+ * NAME
+ *   osmv_txn_get_tid
+ *
+ * DESCRIPTION
+ *   returns tid of the transaction
+ * SEE ALSO
+ *
+ */
+static inline uint64_t osmv_txn_get_tid(IN osmv_txn_ctx_t * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->tid;
+}
+
+/*
+ * NAME
+ *   osmv_txn_get_key
+ *
+ * DESCRIPTION
+ *   returns key of the transaction
+ * SEE ALSO
+ *
+ */
+
+static inline uint64_t osmv_txn_get_key(IN osmv_txn_ctx_t * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->key;
+}
+
+/*
+ * NAME
+ *   osmv_txn_is_rmpp_init_by_peer
+ *
+ * DESCRIPTION
+ *   returns whether the rmpp txfr was init by the peer
+ *
+ * SEE ALSO
+ *
+ */
+static inline boolean_t osmv_txn_is_rmpp_init_by_peer(IN osmv_txn_ctx_t * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->rmpp_txfr.is_rmpp_init_by_peer;
+}
+
+/*
+ * NAME
+ *   osmv_txn_get_rmpp_send_ctx
+ *
+ * DESCRIPTION
+ *   returns osmv_rmpp_send_ctx obj
+ * SEE ALSO
+ *
+ */
+static inline osmv_rmpp_send_ctx_t *osmv_txn_get_rmpp_send_ctx(IN osmv_txn_ctx_t
+							       * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->rmpp_txfr.p_rmpp_send_ctx;
+}
+
+/*
+ * NAME
+ *   osmv_txn_get_rmpp_recv_ctx
+ *
+ * DESCRIPTION
+ *   returns osmv_rmpp_recv_ctx obj
+ * SEE ALSO
+ *
+ */
+static inline osmv_rmpp_recv_ctx_t *osmv_txn_get_rmpp_recv_ctx(IN osmv_txn_ctx_t
+							       * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->rmpp_txfr.p_rmpp_recv_ctx;
+}
+
+/*
+ * NAME
+ *   osmv_txn_get_rmpp_state
+ *
+ * DESCRIPTION
+ *   returns the rmpp role of the transactino ( send/ recv)
+ * SEE ALSO
+ *
+ */
+static inline osmv_txn_rmpp_state_t
+osmv_txn_get_rmpp_state(IN osmv_txn_ctx_t * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->rmpp_txfr.rmpp_state;
+}
+
+/*
+ * NAME
+ *   osmv_txn_set_rmpp_state
+ *
+ * DESCRIPTION
+ *   sets the rmpp role of the transaction (send/ recv)
+ * SEE ALSO
+ *
+ */
+static inline void
+osmv_txn_set_rmpp_state(IN osmv_txn_ctx_t * p_txn,
+			IN osmv_txn_rmpp_state_t state)
+{
+	CL_ASSERT(NULL != p_txn);
+	p_txn->rmpp_txfr.rmpp_state = state;
+}
+
+/*
+ * NAME
+ *   osmv_txn_get_madw
+ *
+ * DESCRIPTION
+ *   returns the requester madw
+ * SEE ALSO
+ *
+ */
+static inline osm_madw_t *osmv_txn_get_madw(IN osmv_txn_ctx_t * p_txn)
+{
+	CL_ASSERT(NULL != p_txn);
+	return p_txn->p_madw;
+}
+
+/*
+ * NAME
+ *   osmv_txn_set_madw
+ *
+ * DESCRIPTION
+ *   sets the requester madw
+ * SEE ALSO
+ *
+ */
+static inline void
+osmv_txn_set_madw(IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw)
+{
+	CL_ASSERT(NULL != p_txn);
+	p_txn->p_madw = p_madw;
+}
+
+/*
+ * NAME
+ *  osmv_txn_set_timeout_ev
+ *
+ * DESCRIPTION
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind,
+			IN uint64_t key, IN uint64_t msec);
+/*
+ * NAME
+ *  osmv_txn_remove_timeout_ev
+ *
+ * DESCRIPTION
+
+ * SEE ALSO
+ *
+ */
+void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key);
+/*
+ * NAME
+ *  osmv_txn_lookup
+ *
+ * DESCRIPTION
+ *   get a transaction by its key
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_lookup(IN osm_bind_handle_t h_bind,
+		IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
+
+void osmv_txn_abort_rmpp_txns(IN osm_bind_handle_t h_bind);
+
+/*      *       *       *       *       *       *       *       *       *       *       *       */
+/*
+ * NAME
+ *  osmv_txnmgr_init
+ *
+ * DESCRIPTION
+ *  c'tor for txn mgr obj
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr,
+		 IN osm_log_t * p_log, IN cl_spinlock_t * p_lock);
+
+/*
+ * NAME
+ *  osmv_txnmgr_done
+ *
+ * DESCRIPTION
+ *  c'tor for txn mgr obj
+ * SEE ALSO
+ *
+ */
+void osmv_txnmgr_done(IN osm_bind_handle_t h_bind);
+
+void osmv_txn_lock(IN osm_bind_handle_t h_bind);
+void osmv_txn_unlock(IN osm_bind_handle_t h_bind);
+
+inline static uint64_t osmv_txn_uniq_key(IN uint64_t tid)
+{
+	uint64_t pid = getpid();
+
+	return ((pid << 32) | (tid & 0xFFFFFFFF));
+}
+
+END_C_DECLS
+#endif				/* _OSMV_TXN_H_ */
diff --git a/include/vendor/osm_vendor_mtl.h b/include/vendor/osm_vendor_mtl.h
new file mode 100644
index 0000000..df48260
--- /dev/null
+++ b/include/vendor/osm_vendor_mtl.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Definition of interface for the MTL Vendor
+ *	   This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_VENDOR_MTL_H_
+#define _OSM_VENDOR_MTL_H_
+
+#undef IN
+#undef OUT
+#include <vapi_types.h>
+#include <evapi.h>
+#include <ib_mgt.h>
+#define IN
+#define OUT
+#include "iba/ib_types.h"
+#include "iba/ib_al.h"
+#include <complib/cl_thread.h>
+#include <complib/cl_types_osd.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/Vendor MTL
+* NAME
+*	Vendor MTL
+*
+* DESCRIPTION
+*
+*	The Vendor MTL object is thread safe.
+*
+*	This object should be treated as opaque and should be
+*	manipulated only through the provided functions.
+*
+*
+* AUTHOR
+*
+*
+*********/
+/****s* OpenSM: Vendor MTL/osm_ca_info_t
+* NAME
+*   osm_ca_info_t
+*
+* DESCRIPTION
+* 	Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+
+/*
+* FIELDS
+*	guid
+*		Node GUID of the local CA.
+*
+*	attr_size
+*		Size of the CA attributes for this CA.
+*
+*	p_attr
+*		Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+#define OSM_DEFAULT_RETRY_COUNT 3
+
+/***** OpenSM: Vendor MTL/osm_vendor_t
+* NAME
+*  osm_vendor_t
+*
+* DESCRIPTION
+* 	The structure defining a vendor
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor {
+	ib_al_handle_t h_al;
+	osm_log_t *p_log;
+	uint32_t ca_count;
+	osm_ca_info_t *p_ca_info;
+	uint32_t timeout;
+	struct osm_transaction_mgr_t *p_transaction_mgr;
+} osm_vendor_t;
+
+/*
+* FIELDS
+*	h_al
+*		Handle returned by MTL open call (ib_open_al).
+*
+*	p_log
+*		Pointer to the log object.
+*
+*	ca_count
+*		Number of CA's in the array pointed to by p_ca_info.
+*
+*	p_ca_info
+*		Pointer to dynamically allocated array of CA info objects.
+*
+*	timeout
+*		Transaction timeout time in milliseconds.
+*
+*  p_transaction_mgr
+*     Pointer to Transaction Manager.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Vendor MTL/CA Info/osm_ca_info_get_port_guid
+* NAME
+*	osm_ca_info_get_port_guid
+*
+* DESCRIPTION
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info,
+			  IN const uint8_t index)
+{
+	return (p_ca_info->p_attr->p_port_attr[index].port_guid);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+*	index
+*		[in] Port "index" for which to retrieve the port GUID.
+*		The index is the offset into the ca's internal array
+*		of port attributes.
+*
+* RETURN VALUE
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Vendor MTL/CA Info/osm_ca_info_get_num_ports
+* NAME
+*	osm_ca_info_get_num_ports
+*
+* DESCRIPTION
+*	Returns the number of ports of the given ca_info
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info)
+{
+	return (p_ca_info->p_attr->num_ports);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+*	Returns the number of CA ports
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port
+ * NAME
+ *	osm_vendor_get_guid_ca_and_port
+ *
+ * DESCRIPTION
+ * Given the vendor obj and a guid
+ * return the ca id and port number that have that guid
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
+				IN ib_net64_t const guid,
+				OUT VAPI_hca_hndl_t * p_hca_hndl,
+				OUT VAPI_hca_id_t * p_hca_id,
+				OUT uint32_t * p_port_num);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to an osm_vendor_t object.
+*
+*	guid
+*		[in] The guid to search for.
+*
+*	p_hca_id
+*		[out] The HCA Id (VAPI_hca_id_t *) that the port is found on.
+*
+*	p_port_num
+*		[out] Pointer to a port number arg to be filled with the port number with the given guid.
+*
+* RETURN VALUES
+*	IB_SUCCESS on SUCCESS
+*  IB_INVALID_GUID if the guid is notfound on any Local HCA Port
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Vendor MTL/osm_vendor_get_all_port_attr
+ * NAME
+ *	osm_vendor_get_all_port_attr
+ *
+ * DESCRIPTION
+ * Fill in the array of port_attr with all available ports on ALL the
+ * avilable CAs on this machine.
+ * ALSO -
+ * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+					     IN ib_port_attr_t *
+					     const p_attr_array,
+					     IN uint32_t * const p_num_ports);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to an osm_vendor_t object.
+*
+*	p_attr_array
+*		[out] Pre-allocated array of port attributes to be filled in
+*
+*	p_num_ports
+*		[out] The size of the given array. Filled in by the actual numberof ports found.
+*
+* RETURN VALUES
+*	IB_SUCCESS if OK
+*  IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+#define OSM_BIND_INVALID_HANDLE 0
+
+/****s* OpenSM: Vendor MTL/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+* 	handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef void *osm_bind_handle_t;
+
+/***********/
+
+/****s* OpenSM: Vendor MTL/osm_vend_wrap_t
+* NAME
+*   MTL Vendor MAD Wrapper
+*
+* DESCRIPTION
+*	MTL specific MAD wrapper. MTL transport layer uses this for
+*	housekeeping.
+*
+* SYNOPSIS
+*********/
+typedef struct _osm_vend_wrap_t {
+	uint32_t size;
+	osm_bind_handle_t h_bind;
+	// ib_av_handle_t         h_av;
+	ib_mad_t *mad_buf_p;
+	void *p_resp_madw;
+} osm_vend_wrap_t;
+
+/*
+* FIELDS
+*	size
+*		Size of the allocated MAD
+*
+*	h_bind
+*		Bind handle used on this transaction
+*
+*	h_av
+*		Address vector handle used for this transaction.
+*
+*	p_resp_madw
+*		Pointer to the mad wrapper structure used to hold the pending
+*		reponse to the mad, if any.  If a response is expected, the
+*		wrapper for the reponse is allocated during the send call.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_MTL_H_ */
diff --git a/include/vendor/osm_vendor_mtl_hca_guid.h b/include/vendor/osm_vendor_mtl_hca_guid.h
new file mode 100644
index 0000000..1b3da88
--- /dev/null
+++ b/include/vendor/osm_vendor_mtl_hca_guid.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Provides interface over VAPI for obtaining the local ports guids or from guid
+ *    obtaining the HCA and port number.
+ */
+
+#ifndef _OSM_VENDOR_HCA_GUID_H_
+#define _OSM_VENDOR_HCA_GUID_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****s* OpenSM: Vendor AL/osm_ca_info_t
+* NAME
+*   osm_ca_info_t
+*
+* DESCRIPTION
+* 	Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+
+/*
+* FIELDS
+*	guid
+*		Node GUID of the local CA.
+*
+*	attr_size
+*		Size of the CA attributes for this CA.
+*
+*	p_attr
+*		Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid
+* NAME
+*	osm_ca_info_get_port_guid
+*
+* DESCRIPTION
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info,
+			  IN const uint8_t index)
+{
+	return (p_ca_info->p_attr->p_port_attr[index].port_guid);
+}
+
+/*
+* PARAMETERS
+*	p_ca_info
+*		[in] Pointer to a CA Info object.
+*
+*	index
+*		[in] Port "index" for which to retrieve the port GUID.
+*		The index is the offset into the ca's internal array
+*		of port attributes.
+*
+* RETURN VALUE
+*	Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port
+ * NAME
+ *	osm_vendor_get_guid_ca_and_port
+ *
+ * DESCRIPTION
+ * Given the vendor obj and a guid
+ * return the ca id and port number that have that guid
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
+				IN ib_net64_t const guid,
+				OUT VAPI_hca_id_t * p_hca_id,
+				OUT uint32_t * p_port_num);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to an osm_vendor_t object.
+*
+*	guid
+*		[in] The guid to search for.
+*
+*	p_hca_id
+*		[out] The HCA Id (VAPI_hca_id_t *) that the port is found on.
+*
+*	p_port_num
+*		[out] Pointer to a port number arg to be filled with the port number with the given guid.
+*
+* RETURN VALUES
+*	IB_SUCCESS on SUCCESS
+*  IB_INVALID_GUID if the guid is notfound on any Local HCA Port
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM Vendor/osm_vendor_get_all_port_attr
+ * NAME
+ *	osm_vendor_get_all_port_attr
+ *
+ * DESCRIPTION
+ * Fill in the array of port_attr with all available ports on ALL the
+ * avilable CAs on this machine.
+ * ALSO -
+ * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+					     IN ib_port_attr_t *
+					     const p_attr_array,
+					     IN uint32_t * const p_num_ports);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to an osm_vendor_t object.
+*
+*	p_attr_array
+*		[out] Pre-allocated array of port attributes to be filled in
+*
+*	p_num_ports
+*		[out] The size of the given array. Filled in by the actual numberof ports found.
+*
+* RETURN VALUES
+*	IB_SUCCESS if OK
+*  IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/*  _OSM_VENDOR_HCA_GUID_H_ */
diff --git a/include/vendor/osm_vendor_mtl_transaction_mgr.h b/include/vendor/osm_vendor_mtl_transaction_mgr.h
new file mode 100644
index 0000000..6ec5b86
--- /dev/null
+++ b/include/vendor/osm_vendor_mtl_transaction_mgr.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Definition of interface for the MTL Vendor
+ *	   This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_TRANSACTION_MGR_H_
+#define _OSM_TRANSACTION_MGR_H_
+
+  /*
+     #include <vapi_types.h>
+     #include <evapi.h>
+   */
+
+#include <iba/ib_types.h>
+#include <iba/ib_al.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_types_osd.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#ifdef OSM_VENDOR_INTF_MTL
+#include <ib_mgt.h>
+#include <opensm/osm_mtl_bind.h>
+#endif
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else				/* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif				/* __cplusplus */
+
+BEGIN_C_DECLS
+/****s* OpenSM: Transaction Manager/osm_madw_req_t
+* NAME
+*  osm_madw_req_t
+*
+* DESCRIPTION
+*  The structure defining each object in the transaction_mgr.
+*  For every request mad sent, we will save such an object for it.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_madw_req {
+	cl_list_item_t list_item;
+	cl_map_item_t map_item;
+	osm_madw_t *p_madw;
+	uint64_t waking_time;
+	uint8_t retry_cnt;
+	osm_bind_handle_t *p_bind;
+} osm_madw_req_t;
+
+/*
+* FIELDS
+*  list_item
+*     List item for qlist linkage. Must be first element!!
+*
+*  map_item
+*     Map item for qmap linkage.
+*
+*  p_madw
+*     pointer to mad wrapper that is expecting to get a response.
+*
+*  waking_time
+*     Time stamp (in microseconds) when the p_madw needs to wake up.
+*     This value is
+*      cl_get_time_stamp() + timeout  during the sending of the mad.
+*      where timeout should be given in microseconds.
+*
+*  retry_cnt
+*     The number of outstanding retries to be called.
+*********/
+
+/****s* OpenSM: Transaction Manager/osm_transaction_mgr_t
+* NAME
+*  osm_transaction_mgr_t
+*
+* DESCRIPTION
+*  This structure defines the transaction manager.
+*  It holds a qlist and a qmap, a lock on the transaction manager, and
+*  a timer used for the list.
+*  The manager is responsible for keeping track of every request mad that was
+*  sent. It is used for finding mads according to their transaction id, and for
+*  acting as an event wheel - reporting as error each packet was supposed to get
+*  a response and didn't get one by the timeout time expected.
+*
+*  Both the list and the map hold the osm_madw_req_t objects - one for every madw.
+*
+*  Managing of the list:
+*  The timer wakes on the timeout of the first madw. If the waking_time is greater than
+*  the current time - then the mad received a response. If not - the mad didn't get
+*  its response.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_transaction_mgr {
+	cl_qmap_t *madw_by_tid_map_p;
+	cl_qlist_t *madw_reqs_list_p;
+	cl_spinlock_t transaction_mgr_lock;
+	cl_timer_t madw_list_timer;
+} osm_transaction_mgr_t;
+
+/*
+* FIELDS
+*  madw_by_tid_map_p
+*     A qmap with key = transaction id. and value of osm_madw_req_t.
+*
+*  madw_reqs_list_p
+*     A qlist of all the madw with their waking time.
+*
+*  transaction_mgr_lock
+*     Lock used on the transaction manager - make sure changes on it are serial.
+*
+*  madw_list_timer
+*     Timer on the list.
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_init
+* NAME
+*	osm_transaction_mgr_init
+*
+* DESCRIPTION
+*	Initialize the transaction manager.
+*  Will update the p_transaction_mgr in the vendor object with
+*  the new Transaction Manager created.*
+*
+* SYNOPSIS
+*/
+void osm_transaction_mgr_init(IN osm_vendor_t * const p_vend);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to a Osm Vendor object.
+*
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_destroy
+* NAME
+*	osm_transaction_mgr_destroy
+*
+* DESCRIPTION
+*	Destroy the transaction manager.
+*  Will de-allocate all memory allocated by the Transaction
+*  Manager up to now.
+*
+* SYNOPSIS
+*/
+void osm_transaction_mgr_destroy(IN osm_vendor_t * const p_vend);
+
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to a Osm Vendor object.
+*
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_insert_madw
+* NAME
+*	osm_transaction_mgr_insert_madw
+*
+* DESCRIPTION
+*	Insert a new madw to the manager. The madw is added with a waking_time,
+*  Which is equal to the current_time + timeout. This is the maximum time
+*  that the madw can leave without being handled (e.g - get a response).
+*  If there are no madw saved in the manager - start the timer for vendor
+*  timeout period.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_transaction_mgr_insert_madw(IN osm_bind_handle_t * p_bind,
+				IN osm_madw_t * p_madw);
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to a mtl bind object.
+*
+*  p_madw
+*     [in] Pointer to the Mad Wrapper to be added.
+*
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_erase_madw
+* NAME
+*	osm_transaction_mgr_erase_madw
+*
+* DESCRIPTION
+*	Erase a madw object from the manager.
+*  The removal is done using the transaction id of the mad - using
+*  it the madw_p is allocated (in the qmap) and removed from the
+*  qmap and qlist.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_transaction_mgr_erase_madw(IN osm_vendor_t * const p_vend,
+			       IN ib_mad_t * p_mad);
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to a Osm Vendor object.
+*
+*  p_mad
+*      [in] Pointer to the Mad to be removed.
+*
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_get_madw_for_tid
+* NAME
+*	osm_transaction_mgr_get_madw_for_tid
+*
+* DESCRIPTION
+*	Return the mad wrapper, given the p_mad (and in it the transaction id)
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_transaction_mgr_get_madw_for_tid(IN osm_vendor_t * const p_vend,
+				     IN ib_mad_t * const p_mad,
+				     OUT osm_madw_t ** req_madw_p);
+/*
+* PARAMETERS
+*	p_vend
+*		[in] Pointer to a Osm Vendor object.
+*
+*  p_mad
+*      [in] Pointer to the Mad to be located.
+*
+* req_madw_p
+*      [out] Pointer to the mad Wrapper to be found.
+*
+*********/
+
+/****f* OpenSM: Transaction Manager/osm_transaction_mgr_callback
+* NAME
+*	osm_transaction_mgr_callback
+*
+* DESCRIPTION
+*	This callback is called on timeout of the timer.
+*  It checks the time of the head madw in the qlist, and compares it to
+*  the current time.
+*  Will send an error callback if the time of the madw is less than the
+*  current time - this means that the madw wasn't removed in the timeout
+*  it was supposed to be handled.
+*
+* SYNOPSIS
+*/
+void osm_transaction_mgr_callback(IN void *context);
+/*
+* PARAMETERS
+*	context
+*		[in] void* context
+*
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_TRANSACTION_MGR_H_ */
diff --git a/include/vendor/osm_vendor_sa_api.h b/include/vendor/osm_vendor_sa_api.h
new file mode 100644
index 0000000..4a4eeaf
--- /dev/null
+++ b/include/vendor/osm_vendor_sa_api.h
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Specification of the OpenSM SA Client API. This API uses the basic osm
+ *    vendor API to provide SA Client interface.
+ */
+
+#ifndef _OSM_VENDOR_SA_API_H_
+#define _OSM_VENDOR_SA_API_H_
+
+#include <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_ */
diff --git a/include/vendor/osm_vendor_test.h b/include/vendor/osm_vendor_test.h
new file mode 100644
index 0000000..a1ae1eb
--- /dev/null
+++ b/include/vendor/osm_vendor_test.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _OSM_VENDOR_TEST_H_
+#define _OSM_VENDOR_TEST_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.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
+/* This value must be zero for the TEST transport. */
+#define OSM_BIND_INVALID_HANDLE 0
+/*
+ * Abstract:
+ * 	Declaration of vendor specific transport interface.
+ *  This is the "Test" vendor which allows compilation and some
+ *  testing without a real vendor interface.
+ *	These objects are part of the OpenSM family of objects.
+ */
+/****h* OpenSM/Vendor Test
+* NAME
+*	Vendor Test
+*
+* DESCRIPTION
+*	The Vendor Test structure encapsulates an artificial transport layer
+*	interface for testing.
+*
+* AUTHOR
+*	Steve King, Intel
+*
+*********/
+/****s* OpenSM: Vendor Test/osm_vend_wrap_t
+* NAME
+*	osm_vend_wrap_t
+*
+* DESCRIPTION
+*	Vendor specific MAD wrapper context.
+*
+*	This structure allows direct access to member variables.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vend_wrap {
+	uint32_t dummy;
+
+} osm_vend_wrap_t;
+/*********/
+
+/****s* OpenSM: Vendor Test/osm_vendor_t
+* NAME
+*	osm_vendor_t
+*
+* DESCRIPTION
+*	Vendor specific MAD interface.
+*
+*	This interface defines access to the vendor specific MAD
+*	transport layer.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor {
+	osm_log_t *p_log;
+	uint32_t timeout;
+
+} osm_vendor_t;
+/*********/
+
+typedef struct _osm_bind_handle {
+	osm_vendor_t *p_vend;
+	ib_net64_t port_guid;
+	uint8_t mad_class;
+	uint8_t class_version;
+	boolean_t is_responder;
+	boolean_t is_trap_processor;
+	boolean_t is_report_processor;
+	uint32_t send_q_size;
+	uint32_t recv_q_size;
+
+} *osm_bind_handle_t;
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_TEST_H_ */
diff --git a/include/vendor/osm_vendor_ts.h b/include/vendor/osm_vendor_ts.h
new file mode 100644
index 0000000..a43f4e4
--- /dev/null
+++ b/include/vendor/osm_vendor_ts.h
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Definition of interface for the TS Vendor
+ *	   This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_VENDOR_TS_H_
+#define _OSM_VENDOR_TS_H_
+
+#undef IN
+#undef OUT
+#include <vapi_types.h>
+#include <evapi.h>
+#include <ib/ts_api_ng/useraccess/include/ts_ib_useraccess.h>
+#define IN
+#define OUT
+#include "iba/ib_types.h"
+#include "iba/ib_al.h"
+#include <complib/cl_thread.h>
+#include <complib/cl_types_osd.h>
+#include <opensm/osm_base.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
+/****s* OpenSM: Vendor TS/osm_bind_handle_t
+ * NAME
+ *   osm_bind_handle_t
+ *
+ * DESCRIPTION
+ * 	handle returned by the vendor transport bind call.
+ *
+ * SYNOPSIS
+ */
+typedef void *osm_bind_handle_t;
+/*
+**********/
+#define OSM_DEFAULT_RETRY_COUNT 3
+
+/****s* OpenSM: Vendor osm_ts_bind_info_t
+ * NAME
+ *   osm_ts_bind_info_t
+ *
+ * DESCRIPTION
+ * 	Handle to the result of binding a class callbacks .
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_ts_bind_info {
+	int ul_dev_fd;
+	VAPI_hca_hndl_t hca_hndl;
+	struct _osm_vendor *p_vend;
+	void *client_context;
+	uint8_t port_num;
+	void *rcv_callback;
+	void *send_err_callback;
+	struct _osm_mad_pool *p_osm_pool;
+	cl_thread_t poller;
+} osm_ts_bind_info_t;
+/*
+ * FIELDS
+ *	ul_dev_file_hdl
+ *		the file handle to be used for sending the MADs
+ *
+ * hca_hndl
+ *     Handle to the HCA provided by the underlying VAPI
+ *
+ *	p_vend
+ *		Pointer to the vendor object.
+ *
+ *	client_context
+ *		User's context passed during osm_bind
+ *
+ *  hca_id
+ *     HCA Id we bind to.
+ *
+ *	port_num
+ *		Port number (within the HCA) of the bound port.
+ *
+ *	rcv_callback
+ *		OSM Callback function to be called on receive of MAD.
+ *
+ *  send_err_callback
+ *     OSM Callback to be called on send error.
+ *
+ *  p_osm_pool
+ *     Points to the MAD pool used by OSM
+ *
+ *  poller
+ *     A thread reading from the device file handle
+ *
+ * SEE ALSO
+ *********/
+
+/****h* OpenSM/Vendor TS
+ * NAME
+ *	Vendor TS
+ *
+ * DESCRIPTION
+ *
+ *	The Vendor TS object is thread safe.
+ *
+ *	This object should be treated as opaque and should be
+ *	manipulated only through the provided functions.
+ *
+ *
+ * AUTHOR
+ *
+ *
+ *********/
+
+/****s* OpenSM: Vendor TS/osm_ca_info_t
+ * NAME
+ *   osm_ca_info_t
+ *
+ * DESCRIPTION
+ * 	Structure containing information about local Channle Adapters.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+
+/*
+ * FIELDS
+ *	guid
+ *		Node GUID of the local CA.
+ *
+ *	attr_size
+ *		Size of the CA attributes for this CA.
+ *
+ *	p_attr
+ *		Pointer to dynamicly allocated CA Attribute structure.
+ *
+ * SEE ALSO
+ *********/
+
+/***** OpenSM: Vendor TS/osm_vendor_t
+ * NAME
+ *  osm_vendor_t
+ *
+ * DESCRIPTION
+ * 	The structure defining a TS vendor
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_vendor {
+	osm_log_t *p_log;
+	uint32_t ca_count;
+	osm_ca_info_t *p_ca_info;
+	uint32_t timeout;
+	struct _osm_transaction_mgr *p_transaction_mgr;
+	osm_ts_bind_info_t smi_bind;
+	osm_ts_bind_info_t gsi_bind;
+} osm_vendor_t;
+
+/*
+ * FIELDS
+ *	h_al
+ *		Handle returned by TS open call .
+ *
+ *	p_log
+ *		Pointer to the log object.
+ *
+ *	ca_count
+ *		Number of CA's in the array pointed to by p_ca_info.
+ *
+ *	p_ca_info
+ *		Pointer to dynamically allocated array of CA info objects.
+ *
+ *	timeout
+ *		Transaction timeout time in milliseconds.
+ *
+ *  p_transaction_mgr
+ *     Pointer to Transaction Manager.
+ *
+ *  smi_bind
+ *     Bind information for handling SMI MADs
+ *
+ *  gsi_bind
+ *     Bind information for GSI MADs
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Vendor TS/CA Info/osm_ca_info_get_port_guid
+ * NAME
+ *	osm_ca_info_get_port_guid
+ *
+ * DESCRIPTION
+ *	Returns the port GUID of the specified port owned by this CA.
+ *
+ * SYNOPSIS
+ */
+static inline ib_net64_t
+osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info,
+			  IN const uint8_t index)
+{
+	return (p_ca_info->p_attr->p_port_attr[index].port_guid);
+}
+
+/*
+ * PARAMETERS
+ *	p_ca_info
+ *		[in] Pointer to a CA Info object.
+ *
+ *	index
+ *		[in] Port "index" for which to retrieve the port GUID.
+ *		The index is the offset into the ca's internal array
+ *		of port attributes.
+ *
+ * RETURN VALUE
+ *	Returns the port GUID of the specified port owned by this CA.
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Vendor TS/CA Info/osm_ca_info_get_num_ports
+ * NAME
+ *	osm_ca_info_get_num_ports
+ *
+ * DESCRIPTION
+ *	Returns the number of ports of the given ca_info
+ *
+ * SYNOPSIS
+ */
+static inline uint8_t
+osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info)
+{
+	return (p_ca_info->p_attr->num_ports);
+}
+
+/*
+ * PARAMETERS
+ *	p_ca_info
+ *		[in] Pointer to a CA Info object.
+ *
+ * RETURN VALUE
+ *	Returns the number of CA ports
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port
+ * NAME
+ *	osm_vendor_get_guid_ca_and_port
+ *
+ * DESCRIPTION
+ * Given the vendor obj and a guid
+ * return the ca id and port number that have that guid
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
+				IN ib_net64_t const guid,
+				OUT VAPI_hca_hndl_t * p_hca_hndl,
+				OUT VAPI_hca_id_t * p_hca_id,
+				OUT uint32_t * p_port_num);
+
+/*
+ * PARAMETERS
+ *	p_vend
+ *		[in] Pointer to an osm_vendor_t object.
+ *
+ *	guid
+ *		[in] The guid to search for.
+ *
+ *	p_hca_id
+ *		[out] The HCA Id (VAPI_hca_id_t *) that the port is found on.
+ *
+ *	p_port_num
+ *		[out] Pointer to a port number arg to be filled with the port number with the given guid.
+ *
+ * RETURN VALUES
+ *	IB_SUCCESS on SUCCESS
+ *  IB_INVALID_GUID if the guid is notfound on any Local HCA Port
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Vendor TS/osm_vendor_get_all_port_attr
+ * NAME
+ *	osm_vendor_get_all_port_attr
+ *
+ * DESCRIPTION
+ * Fill in the array of port_attr with all available ports on ALL the
+ * avilable CAs on this machine.
+ * ALSO -
+ * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+					     IN ib_port_attr_t *
+					     const p_attr_array,
+					     IN uint32_t * const p_num_ports);
+
+/*
+ * PARAMETERS
+ *	p_vend
+ *		[in] Pointer to an osm_vendor_t object.
+ *
+ *	p_attr_array
+ *		[out] Pre-allocated array of port attributes to be filled in
+ *
+ *	p_num_ports
+ *		[out] The size of the given array. Filled in by the actual numberof ports found.
+ *
+ * RETURN VALUES
+ *	IB_SUCCESS if OK
+ *  IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided.
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+#define OSM_BIND_INVALID_HANDLE 0
+
+/****s* OpenSM: Vendor TS/osm_vend_wrap_t
+ * NAME
+ *   TS Vendor MAD Wrapper
+ *
+ * DESCRIPTION
+ *	TS specific MAD wrapper. TS transport layer uses this for
+ *	housekeeping.
+ *
+ * SYNOPSIS
+ *********/
+typedef struct _osm_vend_wrap_t {
+	uint32_t size;
+	osm_bind_handle_t h_bind;
+	ib_mad_t *p_mad_buf;
+	void *p_resp_madw;
+} osm_vend_wrap_t;
+
+/*
+ * FIELDS
+ *	size
+ *		Size of the allocated MAD
+ *
+ *	h_bind
+ *		Bind handle used on this transaction
+ *
+ *	h_av
+ *		Address vector handle used for this transaction.
+ *
+ *	p_resp_madw
+ *		Pointer to the mad wrapper structure used to hold the pending
+ *		reponse to the mad, if any.  If a response is expected, the
+ *		wrapper for the reponse is allocated during the send call.
+ *
+ * SEE ALSO
+ *********/
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_TS_H_ */
diff --git a/include/vendor/osm_vendor_umadt.h b/include/vendor/osm_vendor_umadt.h
new file mode 100644
index 0000000..8cdb631
--- /dev/null
+++ b/include/vendor/osm_vendor_umadt.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osm_mad_wrapper_t.
+ *	This object represents the context wrapper for OpenSM MAD processing.
+ *	This object is part of the OpenSM family of objects.
+ */
+
+#ifndef _OSM_VENDOR_UMADT_h_
+#define _OSM_VENDOR_UMADT_h_
+
+#include "iba/ib_types.h"
+#include "complib/cl_qlist.h"
+#include "complib/cl_thread.h"
+#include <opensm/osm_base.h>
+#include <vendor/umadt.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/ Vendor Umadt
+* NAME
+*	MAD Wrapper
+*
+* DESCRIPTION
+*
+*
+* AUTHOR
+*	Ranjit Pandit, Intel
+*
+*********/
+typedef void *osm_vendor_t;
+#define OSM_BIND_INVALID_HANDLE 0
+
+/****s* OpenSM: Vendor Umadt /osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+* 	handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+
+typedef void *osm_bind_handle_t;
+
+/****s* OpenSM: Vendor Umadt /mad_direction_t
+* NAME
+*	mad_direction_t
+*
+* DESCRIPTION
+*	Tags for mad wrapper to indicate the direction of mads.
+*	Umadt vendor transport layer uses this tag to call the appropriate
+* 	Umadt APIs.
+*
+* SYNOPSIS
+*/
+typedef enum _mad_direction_t {
+	SEND = 0,
+	RECEIVE,
+} mad_direction_t;
+
+/****s* OpenSM/ osm_vend_wrap_t
+* NAME
+*   Umadt Vendor MAD Wrapper
+*
+* DESCRIPTION
+*	Umadt specific MAD wrapper. Umadt transport layer sets this for
+*	housekeeping.
+*
+* SYNOPSIS
+*********/
+typedef struct _osm_vend_wrap_t {
+	MadtStruct *p_madt_struct;
+	mad_direction_t direction;	// send or receive
+	uint32_t size;
+} osm_vend_wrap_t;
+/*
+* FIELDS
+*	p_madt_struct
+*		Umadt mad structure to identify a mad.
+*
+*	direction
+*		Used to identify a mad with it's direction.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+#endif				/* _OSM_VENDOR_UMADT_h_ */
diff --git a/libvendor/ChangeLog b/libvendor/ChangeLog
new file mode 100644
index 0000000..c9648ec
--- /dev/null
+++ b/libvendor/ChangeLog
@@ -0,0 +1,64 @@
+2007-07-11  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.2.1
+
+2007-07-10  Sean Hefty <sean.hefty at intel.com>
+
+	* osm_vendor_ibumad.c:  Use pkey index, rather than pkey
+	  on umad_set_pkey call. Using index 0 for now.
+
+2007-05-07  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.(h c): Remove support for issmdisabled
+
+2007-03-29  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.2.0
+
+2007-03-27  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.(h c): Add support for issmdisabled
+
+2007-03-13  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.c: In osm_vendor_set_sm, set issmfd to
+	  -1 on open error
+
+2007-03-12  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.c: In umad_receiver, display DR path of
+	  sent MAD when it times out. In osm_vendor_send, simplify redundant
+	  code. Cosmetic change to osm_log message in osm_vendor_bind.
+
+2007-02-20  Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.1.1
+
+2007-02-20  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_vendor_ibumad.(h c): Fix termination crash associated
+	  with umad_receiver thread termination.
+
+	* osm_vendor_mlx_sa.c, osm_vendor_mlx_sim.c: Changes for
+	  compilation failures detected during ibutils/ibmgtsim building
+
+2007=01-10  Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_vendor_ibumad.c: Close umad port in
+	  osm_vendor_delete so same process can reinitialize
+	  and resuse vendor layer.
+
+2006-10-12  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.c (umad_receiver): Fix endian of LID
+	  displayed in send timeout error message.
+
+2006-10-10  Hal Rosenstock <halr at voltaire.com>
+
+	* osm_vendor_ibumad.c: Print errors to stderr rather than
+	  stdout.
+
+2006-09-28  Eitan Zahavi <eitan at mellanox.co.il>
+
+	* osm_vendor_mlx_sa.c: Missing status on timeout SA query.
+
diff --git a/libvendor/Makefile.am b/libvendor/Makefile.am
new file mode 100644
index 0000000..22f7a08
--- /dev/null
+++ b/libvendor/Makefile.am
@@ -0,0 +1,86 @@
+
+SUBDIRS = .
+
+if DEBUG
+DBGFLAGS = -ggdb -D_DEBUG_
+else
+DBGFLAGS = -g
+endif
+
+INCLUDES = $(OSMV_INCLUDES)
+
+lib_LTLIBRARIES = libosmvendor.la
+
+libosmvendor_la_CFLAGS = -Wall $(DBGFLAGS)
+
+if HAVE_LD_VERSION_SCRIPT
+    libosmvendor_version_script = -Wl,--version-script=$(srcdir)/libosmvendor.map
+else
+    libosmvendor_version_script =
+endif
+
+osmvendor_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmvendor.ver | sed 's/LIBVERSION=//')
+
+COMM_HDRS= $(srcdir)/../include/vendor/osm_vendor_api.h \
+			$(srcdir)/../include/vendor/osm_vendor.h \
+			$(srcdir)/../include/vendor/osm_vendor_sa_api.h
+
+if OSMV_OPENIB
+libosmvendor_la_SOURCES = osm_vendor_ibumad.c \
+			  osm_vendor_ibumad_sa.c
+HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_ibumad.h
+endif
+if OSMV_SIM
+libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+		osm_vendor_mlx_sim.c \
+		osm_vendor_mlx_hca_sim.c \
+		osm_vendor_mlx_dispatcher.c \
+		osm_vendor_mlx_rmpp_ctx.c \
+		osm_vendor_mlx_sar.c \
+		osm_vendor_mlx_sender.c \
+		osm_vendor_mlx_txn.c \
+		osm_vendor_mlx_sa.c \
+		osm_pkt_randomizer.c
+HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+endif
+if OSMV_GEN1
+libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+		osm_pkt_randomizer.c \
+		osm_vendor_mlx_hca.c \
+		osm_vendor_mlx_dispatcher.c \
+		osm_vendor_mlx_rmpp_ctx.c \
+		osm_vendor_mlx_sar.c \
+		osm_vendor_mlx_sender.c \
+		osm_vendor_mlx_ts.c \
+		osm_vendor_mlx_txn.c \
+		osm_vendor_mlx_sa.c
+HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+endif
+if OSMV_VAPI
+libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+		osm_pkt_randomizer.c \
+		osm_vendor_mlx_hca.c \
+		osm_vendor_mlx_dispatcher.c \
+		osm_vendor_mlx_rmpp_ctx.c \
+		osm_vendor_mlx_sar.c \
+		osm_vendor_mlx_sender.c \
+		osm_vendor_mlx_ibmgt.c \
+		osm_vendor_mlx_txn.c \
+		osm_vendor_mlx_sa.c
+HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+endif
+
+libosmvendor_la_LIBADD = -L../complib -losmcomp
+libosmvendor_la_LDFLAGS = -version-info $(osmvendor_api_version) \
+	-export-dynamic $(libosmvendor_version_script)
+libosmvendor_la_DEPENDENCIES = $(srcdir)/libosmvendor.map
+
+libosmvendorincludedir = $(includedir)/infiniband/vendor
+
+libosmvendorinclude_HEADERS = $(HDRS)
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmvendor.map $(srcdir)/libosmvendor.ver
diff --git a/libvendor/Makefile.in b/libvendor/Makefile.in
new file mode 100644
index 0000000..0d2f576
--- /dev/null
+++ b/libvendor/Makefile.in
@@ -0,0 +1,862 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = libvendor
+DIST_COMMON = $(am__libosmvendorinclude_HEADERS_DIST) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+	"$(DESTDIR)$(libosmvendorincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__libosmvendor_la_SOURCES_DIST = osm_vendor_mlx.c \
+	osm_pkt_randomizer.c osm_vendor_mlx_hca.c \
+	osm_vendor_mlx_dispatcher.c osm_vendor_mlx_rmpp_ctx.c \
+	osm_vendor_mlx_sar.c osm_vendor_mlx_sender.c \
+	osm_vendor_mlx_ts.c osm_vendor_mlx_txn.c osm_vendor_mlx_sa.c \
+	osm_vendor_ibumad.c osm_vendor_ibumad_sa.c \
+	osm_vendor_mlx_sim.c osm_vendor_mlx_hca_sim.c \
+	osm_vendor_mlx_ibmgt.c
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE at am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_mlx.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_pkt_randomizer.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_hca.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_dispatcher.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_sar.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_sender.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_ibmgt.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_txn.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@	libosmvendor_la-osm_vendor_mlx_sa.lo
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE at am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_mlx.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_sim.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_hca_sim.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_dispatcher.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_sar.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_sender.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_txn.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_vendor_mlx_sa.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@	libosmvendor_la-osm_pkt_randomizer.lo
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_TRUE at am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_ibumad.lo \
+ at OSMV_GEN1_FALSE@@OSMV_OPENIB_TRUE@	libosmvendor_la-osm_vendor_ibumad_sa.lo
+ at OSMV_GEN1_TRUE@am_libosmvendor_la_OBJECTS =  \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_pkt_randomizer.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_hca.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_dispatcher.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_sar.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_sender.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_ts.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_txn.lo \
+ at OSMV_GEN1_TRUE@	libosmvendor_la-osm_vendor_mlx_sa.lo
+libosmvendor_la_OBJECTS = $(am_libosmvendor_la_OBJECTS)
+libosmvendor_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libosmvendor_la_CFLAGS) \
+	$(CFLAGS) $(libosmvendor_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libosmvendor_la_SOURCES)
+DIST_SOURCES = $(am__libosmvendor_la_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+am__libosmvendorinclude_HEADERS_DIST =  \
+	$(srcdir)/../include/vendor/osm_vendor_api.h \
+	$(srcdir)/../include/vendor/osm_vendor.h \
+	$(srcdir)/../include/vendor/osm_vendor_sa_api.h \
+	$(srcdir)/../include/vendor/osm_vendor_mlx.h \
+	$(srcdir)/../include/vendor/osm_pkt_randomizer.h \
+	$(srcdir)/../include/vendor/osm_vendor_ibumad.h
+libosmvendorincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libosmvendorinclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+ at DEBUG_FALSE@DBGFLAGS = -g
+ at DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_
+INCLUDES = $(OSMV_INCLUDES)
+lib_LTLIBRARIES = libosmvendor.la
+libosmvendor_la_CFLAGS = -Wall $(DBGFLAGS)
+ at HAVE_LD_VERSION_SCRIPT_FALSE@libosmvendor_version_script = 
+ at HAVE_LD_VERSION_SCRIPT_TRUE@libosmvendor_version_script = -Wl,--version-script=$(srcdir)/libosmvendor.map
+osmvendor_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmvendor.ver | sed 's/LIBVERSION=//')
+COMM_HDRS = $(srcdir)/../include/vendor/osm_vendor_api.h \
+			$(srcdir)/../include/vendor/osm_vendor.h \
+			$(srcdir)/../include/vendor/osm_vendor_sa_api.h
+
+ at OSMV_GEN1_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+ at OSMV_GEN1_TRUE@		osm_pkt_randomizer.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_hca.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_dispatcher.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_rmpp_ctx.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_sar.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_sender.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_ts.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_txn.c \
+ at OSMV_GEN1_TRUE@		osm_vendor_mlx_sa.c
+
+ at OSMV_OPENIB_TRUE@libosmvendor_la_SOURCES = osm_vendor_ibumad.c \
+ at OSMV_OPENIB_TRUE@			  osm_vendor_ibumad_sa.c
+
+ at OSMV_SIM_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_sim.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_hca_sim.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_dispatcher.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_rmpp_ctx.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_sar.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_sender.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_txn.c \
+ at OSMV_SIM_TRUE@		osm_vendor_mlx_sa.c \
+ at OSMV_SIM_TRUE@		osm_pkt_randomizer.c
+
+ at OSMV_VAPI_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \
+ at OSMV_VAPI_TRUE@		osm_pkt_randomizer.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_hca.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_dispatcher.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_rmpp_ctx.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_sar.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_sender.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_ibmgt.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_txn.c \
+ at OSMV_VAPI_TRUE@		osm_vendor_mlx_sa.c
+
+ at OSMV_GEN1_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+ at OSMV_GEN1_TRUE@	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+
+ at OSMV_OPENIB_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_ibumad.h
+ at OSMV_SIM_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+ at OSMV_SIM_TRUE@	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+
+ at OSMV_VAPI_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \
+ at OSMV_VAPI_TRUE@	$(srcdir)/../include/vendor/osm_pkt_randomizer.h
+
+libosmvendor_la_LIBADD = -L../complib -losmcomp
+libosmvendor_la_LDFLAGS = -version-info $(osmvendor_api_version) \
+	-export-dynamic $(libosmvendor_version_script)
+
+libosmvendor_la_DEPENDENCIES = $(srcdir)/libosmvendor.map
+libosmvendorincludedir = $(includedir)/infiniband/vendor
+libosmvendorinclude_HEADERS = $(HDRS)
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmvendor.map $(srcdir)/libosmvendor.ver
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  libvendor/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  libvendor/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libosmvendor.la: $(libosmvendor_la_OBJECTS) $(libosmvendor_la_DEPENDENCIES) 
+	$(libosmvendor_la_LINK) -rpath $(libdir) $(libosmvendor_la_OBJECTS) $(libosmvendor_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libosmvendor_la-osm_vendor_mlx.lo: osm_vendor_mlx.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Tpo -c -o libosmvendor_la-osm_vendor_mlx.lo `test -f 'osm_vendor_mlx.c' || echo '$(srcdir)/'`osm_vendor_mlx.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx.c' object='libosmvendor_la-osm_vendor_mlx.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx.lo `test -f 'osm_vendor_mlx.c' || echo '$(srcdir)/'`osm_vendor_mlx.c
+
+libosmvendor_la-osm_pkt_randomizer.lo: osm_pkt_randomizer.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_pkt_randomizer.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Tpo -c -o libosmvendor_la-osm_pkt_randomizer.lo `test -f 'osm_pkt_randomizer.c' || echo '$(srcdir)/'`osm_pkt_randomizer.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Tpo $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_pkt_randomizer.c' object='libosmvendor_la-osm_pkt_randomizer.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_pkt_randomizer.lo `test -f 'osm_pkt_randomizer.c' || echo '$(srcdir)/'`osm_pkt_randomizer.c
+
+libosmvendor_la-osm_vendor_mlx_hca.lo: osm_vendor_mlx_hca.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_hca.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Tpo -c -o libosmvendor_la-osm_vendor_mlx_hca.lo `test -f 'osm_vendor_mlx_hca.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_hca.c' object='libosmvendor_la-osm_vendor_mlx_hca.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_hca.lo `test -f 'osm_vendor_mlx_hca.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca.c
+
+libosmvendor_la-osm_vendor_mlx_dispatcher.lo: osm_vendor_mlx_dispatcher.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_dispatcher.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Tpo -c -o libosmvendor_la-osm_vendor_mlx_dispatcher.lo `test -f 'osm_vendor_mlx_dispatcher.c' || echo '$(srcdir)/'`osm_vendor_mlx_dispatcher.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_dispatcher.c' object='libosmvendor_la-osm_vendor_mlx_dispatcher.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_dispatcher.lo `test -f 'osm_vendor_mlx_dispatcher.c' || echo '$(srcdir)/'`osm_vendor_mlx_dispatcher.c
+
+libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo: osm_vendor_mlx_rmpp_ctx.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Tpo -c -o libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo `test -f 'osm_vendor_mlx_rmpp_ctx.c' || echo '$(srcdir)/'`osm_vendor_mlx_rmpp_ctx.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_rmpp_ctx.c' object='libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo `test -f 'osm_vendor_mlx_rmpp_ctx.c' || echo '$(srcdir)/'`osm_vendor_mlx_rmpp_ctx.c
+
+libosmvendor_la-osm_vendor_mlx_sar.lo: osm_vendor_mlx_sar.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sar.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sar.lo `test -f 'osm_vendor_mlx_sar.c' || echo '$(srcdir)/'`osm_vendor_mlx_sar.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_sar.c' object='libosmvendor_la-osm_vendor_mlx_sar.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sar.lo `test -f 'osm_vendor_mlx_sar.c' || echo '$(srcdir)/'`osm_vendor_mlx_sar.c
+
+libosmvendor_la-osm_vendor_mlx_sender.lo: osm_vendor_mlx_sender.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sender.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sender.lo `test -f 'osm_vendor_mlx_sender.c' || echo '$(srcdir)/'`osm_vendor_mlx_sender.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_sender.c' object='libosmvendor_la-osm_vendor_mlx_sender.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sender.lo `test -f 'osm_vendor_mlx_sender.c' || echo '$(srcdir)/'`osm_vendor_mlx_sender.c
+
+libosmvendor_la-osm_vendor_mlx_ts.lo: osm_vendor_mlx_ts.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_ts.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Tpo -c -o libosmvendor_la-osm_vendor_mlx_ts.lo `test -f 'osm_vendor_mlx_ts.c' || echo '$(srcdir)/'`osm_vendor_mlx_ts.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_ts.c' object='libosmvendor_la-osm_vendor_mlx_ts.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_ts.lo `test -f 'osm_vendor_mlx_ts.c' || echo '$(srcdir)/'`osm_vendor_mlx_ts.c
+
+libosmvendor_la-osm_vendor_mlx_txn.lo: osm_vendor_mlx_txn.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_txn.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Tpo -c -o libosmvendor_la-osm_vendor_mlx_txn.lo `test -f 'osm_vendor_mlx_txn.c' || echo '$(srcdir)/'`osm_vendor_mlx_txn.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_txn.c' object='libosmvendor_la-osm_vendor_mlx_txn.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_txn.lo `test -f 'osm_vendor_mlx_txn.c' || echo '$(srcdir)/'`osm_vendor_mlx_txn.c
+
+libosmvendor_la-osm_vendor_mlx_sa.lo: osm_vendor_mlx_sa.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sa.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sa.lo `test -f 'osm_vendor_mlx_sa.c' || echo '$(srcdir)/'`osm_vendor_mlx_sa.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_sa.c' object='libosmvendor_la-osm_vendor_mlx_sa.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sa.lo `test -f 'osm_vendor_mlx_sa.c' || echo '$(srcdir)/'`osm_vendor_mlx_sa.c
+
+libosmvendor_la-osm_vendor_ibumad.lo: osm_vendor_ibumad.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_ibumad.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Tpo -c -o libosmvendor_la-osm_vendor_ibumad.lo `test -f 'osm_vendor_ibumad.c' || echo '$(srcdir)/'`osm_vendor_ibumad.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_ibumad.c' object='libosmvendor_la-osm_vendor_ibumad.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_ibumad.lo `test -f 'osm_vendor_ibumad.c' || echo '$(srcdir)/'`osm_vendor_ibumad.c
+
+libosmvendor_la-osm_vendor_ibumad_sa.lo: osm_vendor_ibumad_sa.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_ibumad_sa.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Tpo -c -o libosmvendor_la-osm_vendor_ibumad_sa.lo `test -f 'osm_vendor_ibumad_sa.c' || echo '$(srcdir)/'`osm_vendor_ibumad_sa.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_ibumad_sa.c' object='libosmvendor_la-osm_vendor_ibumad_sa.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_ibumad_sa.lo `test -f 'osm_vendor_ibumad_sa.c' || echo '$(srcdir)/'`osm_vendor_ibumad_sa.c
+
+libosmvendor_la-osm_vendor_mlx_sim.lo: osm_vendor_mlx_sim.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sim.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sim.lo `test -f 'osm_vendor_mlx_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_sim.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_sim.c' object='libosmvendor_la-osm_vendor_mlx_sim.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sim.lo `test -f 'osm_vendor_mlx_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_sim.c
+
+libosmvendor_la-osm_vendor_mlx_hca_sim.lo: osm_vendor_mlx_hca_sim.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_hca_sim.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Tpo -c -o libosmvendor_la-osm_vendor_mlx_hca_sim.lo `test -f 'osm_vendor_mlx_hca_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca_sim.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_hca_sim.c' object='libosmvendor_la-osm_vendor_mlx_hca_sim.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_hca_sim.lo `test -f 'osm_vendor_mlx_hca_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca_sim.c
+
+libosmvendor_la-osm_vendor_mlx_ibmgt.lo: osm_vendor_mlx_ibmgt.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_ibmgt.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Tpo -c -o libosmvendor_la-osm_vendor_mlx_ibmgt.lo `test -f 'osm_vendor_mlx_ibmgt.c' || echo '$(srcdir)/'`osm_vendor_mlx_ibmgt.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osm_vendor_mlx_ibmgt.c' object='libosmvendor_la-osm_vendor_mlx_ibmgt.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_ibmgt.lo `test -f 'osm_vendor_mlx_ibmgt.c' || echo '$(srcdir)/'`osm_vendor_mlx_ibmgt.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-libosmvendorincludeHEADERS: $(libosmvendorinclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libosmvendorincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmvendorincludedir)"
+	@list='$(libosmvendorinclude_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libosmvendorincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libosmvendorincludedir)/$$f'"; \
+	  $(libosmvendorincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libosmvendorincludedir)/$$f"; \
+	done
+
+uninstall-libosmvendorincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libosmvendorinclude_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libosmvendorincludedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libosmvendorincludedir)/$$f"; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmvendorincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-libosmvendorincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES \
+	uninstall-libosmvendorincludeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-libLTLIBRARIES \
+	install-libosmvendorincludeHEADERS install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs installdirs-am \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+	uninstall-libLTLIBRARIES uninstall-libosmvendorincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libvendor/libosmvendor.map b/libvendor/libosmvendor.map
new file mode 100644
index 0000000..17416b3
--- /dev/null
+++ b/libvendor/libosmvendor.map
@@ -0,0 +1,20 @@
+OSMVENDOR_2.0 {
+	global:
+		umad_receiver;
+		osm_vendor_init;
+		osm_vendor_new;
+		osm_vendor_delete;
+		osm_vendor_get_all_port_attr;
+		osm_vendor_bind;
+		osm_vendor_unbind;
+		osm_vendor_get;
+		osm_vendor_put;
+		osm_vendor_send;
+		osm_vendor_local_lid_change;
+		osm_vendor_set_sm;
+		osm_vendor_set_debug;
+		osmv_bind_sa;
+		osmv_query_sa;
+		osm_vendor_get_guid_ca_and_port;
+	local: *;
+};
diff --git a/libvendor/libosmvendor.ver b/libvendor/libosmvendor.ver
new file mode 100644
index 0000000..0c3a85b
--- /dev/null
+++ b/libvendor/libosmvendor.ver
@@ -0,0 +1,9 @@
+# In this file we track the current API version
+# of the vendor interface (and libraries)
+# The version is built of the following
+# tree numbers:
+# API_REV:RUNNING_REV:AGE
+# API_REV - advance on any added API
+# RUNNING_REV - advance any change to the vendor files
+# AGE - number of backward versions the API still supports
+LIBVERSION=2:0:0
diff --git a/libvendor/osm_pkt_randomizer.c b/libvendor/osm_pkt_randomizer.c
new file mode 100644
index 0000000..3e77b56
--- /dev/null
+++ b/libvendor/osm_pkt_randomizer.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_pkt_randomizer_t.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <vendor/osm_pkt_randomizer.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+/**********************************************************************
+ * Return TRUE if the path is in a fault path, and FALSE otherwise.
+ * By in a fault path the meaning is that there is a path in the fault
+ * paths that the given path includes it.
+ * E.g: if there is a fault path: 0,1,4
+ * For the given path: 0,1,4,7 the return value will be TRUE, also for
+ * the given path: 0,1,4 the return value will be TRUE, but for
+ * the given paths: 0,1 or 0,3,1,4 - the return value will be FALSE.
+ **********************************************************************/
+boolean_t
+__osm_pkt_randomizer_is_path_in_fault_paths(IN osm_log_t * p_log,
+					    IN osm_dr_path_t * p_dr_path,
+					    IN osm_pkt_randomizer_t *
+					    p_pkt_rand)
+{
+	boolean_t res = FALSE, found_path;
+	osm_dr_path_t *p_found_dr_path;
+	uint8_t ind1, ind2;
+
+	OSM_LOG_ENTER(p_log);
+
+	for (ind1 = 0; ind1 < p_pkt_rand->num_paths_initialized; ind1++) {
+		found_path = TRUE;
+		p_found_dr_path = &(p_pkt_rand->fault_dr_paths[ind1]);
+		/* if the hop count of the found path is greater than the
+		   hop count of the input path - then it is not part of it.
+		   Check the next path. */
+		if (p_found_dr_path->hop_count > p_dr_path->hop_count)
+			continue;
+
+		/* go over all the ports in the found path and see if they match
+		   the ports in the input path */
+		for (ind2 = 0; ind2 <= p_found_dr_path->hop_count; ind2++)
+			if (p_found_dr_path->path[ind2] !=
+			    p_dr_path->path[ind2])
+				found_path = FALSE;
+
+		/* If found_path is TRUE  then there is a full match of the path */
+		if (found_path == TRUE) {
+			OSM_LOG(p_log, OSM_LOG_VERBOSE,
+				"Given path is in a fault path\n");
+			res = TRUE;
+			break;
+		}
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return res;
+}
+
+/**********************************************************************
+ * For a given dr_path - return TRUE if the path should be dropped,
+ * return FALSE otherwise.
+ * The check uses random criteria in order to determine whether or not
+ * the path should be dropped.
+ * First - if not all paths are initialized, it randomally chooses if
+ * to use this path as a fault path or not.
+ * Second - if the path is in the fault paths (meaning - it is equal
+ * to or includes one of the fault paths) - then it randomally chooses
+ * if to drop it or not.
+ **********************************************************************/
+boolean_t
+__osm_pkt_randomizer_process_path(IN osm_log_t * p_log,
+				  IN osm_pkt_randomizer_t * p_pkt_rand,
+				  IN osm_dr_path_t * p_dr_path)
+{
+	boolean_t res = FALSE;
+	static boolean_t rand_value_init = FALSE;
+	static int rand_value;
+	boolean_t in_fault_paths;
+	uint8_t i;
+	char buf[BUF_SIZE];
+	char line[BUF_SIZE];
+
+	OSM_LOG_ENTER(p_log);
+
+	if (rand_value_init == FALSE) {
+		int seed;
+#ifdef WIN32
+		SYSTEMTIME st;
+#else
+		struct timeval tv;
+		struct timezone tz;
+#endif				/*  WIN32 */
+
+		/* initiate the rand_value according to timeofday */
+		rand_value_init = TRUE;
+
+#ifdef WIN32
+		GetLocalTime(&st);
+		seed = st.wMilliseconds;
+#else
+		gettimeofday(&tv, &tz);
+		seed = tv.tv_usec;
+#endif				/*  WIN32 */
+
+		srand(seed);
+	}
+
+	/* If the hop_count is 1 - then this is a mad down to our local port - don't drop it */
+	if (p_dr_path->hop_count <= 1)
+		goto Exit;
+
+	rand_value = rand();
+
+	sprintf(buf, "Path: ");
+	/* update the dr_path into the buf */
+	for (i = 0; i <= p_dr_path->hop_count; i++) {
+		sprintf(line, "[%X]", p_dr_path->path[i]);
+		strcat(buf, line);
+	}
+
+	/* Check if the path given is in one of the fault paths */
+	in_fault_paths =
+	    __osm_pkt_randomizer_is_path_in_fault_paths(p_log, p_dr_path,
+							p_pkt_rand);
+
+	/* Check if all paths are initialized */
+	if (p_pkt_rand->num_paths_initialized <
+	    p_pkt_rand->osm_pkt_num_unstable_links) {
+		/* Not all packets are initialized. */
+		if (in_fault_paths == FALSE) {
+			/* the path is not in the false paths. Check using the rand value
+			   if to update it there or not. */
+			if (rand_value %
+			    (p_pkt_rand->osm_pkt_unstable_link_rate) == 0) {
+				OSM_LOG(p_log, OSM_LOG_VERBOSE,
+					"%s added to the fault_dr_paths list\n"
+					"\t\t\t rand_value:%u, unstable_link_rate:%u \n",
+					buf, rand_value,
+					p_pkt_rand->osm_pkt_unstable_link_rate);
+
+				/* update the path in the fault paths */
+				memcpy(&
+				       (p_pkt_rand->
+					fault_dr_paths[p_pkt_rand->
+						       num_paths_initialized]),
+				       p_dr_path, sizeof(osm_dr_path_t));
+				p_pkt_rand->num_paths_initialized++;
+				in_fault_paths = TRUE;
+			}
+		}
+	}
+
+	if (in_fault_paths == FALSE) {
+		/* If in_fault_paths is FALSE - just ignore the path */
+		OSM_LOG(p_log, OSM_LOG_VERBOSE, "%s not in fault paths\n", buf);
+		goto Exit;
+	}
+
+	/* The path is in the fault paths. Need to choose (randomally if to drop it
+	   or not. */
+	rand_value = rand();
+
+	if (rand_value % (p_pkt_rand->osm_pkt_drop_rate) == 0) {
+		/* drop the current packet */
+		res = TRUE;
+		OSM_LOG(p_log, OSM_LOG_VERBOSE, "Dropping path:%s\n", buf);
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return res;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_pkt_randomizer_mad_drop(IN osm_log_t * p_log,
+			    IN osm_pkt_randomizer_t * p_pkt_randomizer,
+			    IN const ib_mad_t * p_mad)
+{
+	const ib_smp_t *p_smp;
+	boolean_t res = FALSE;
+	osm_dr_path_t dr_path;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_smp = (ib_smp_t *) p_mad;
+
+	if (p_smp->mgmt_class != IB_MCLASS_SUBN_DIR)
+		/* This is a lid route mad. Don't drop it */
+		goto Exit;
+
+	osm_dr_path_init(&dr_path, 0,	/* The h_bind is not really important for us to save */
+			 p_smp->hop_count, p_smp->initial_path);
+
+	if (__osm_pkt_randomizer_process_path
+	    (p_log, p_pkt_randomizer, &dr_path)) {
+		/* the mad should be dropped o */
+		OSM_LOG(p_log, OSM_LOG_VERBOSE,
+			"mad TID: 0x%" PRIx64 " is being dropped\n",
+			cl_ntoh64(p_smp->trans_id));
+		res = TRUE;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return res;
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkt_randomizer_init(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer,
+			IN osm_log_t * p_log)
+{
+	uint8_t tmp;
+	ib_api_status_t res = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	*pp_pkt_randomizer = malloc(sizeof(osm_pkt_randomizer_t));
+	if (*pp_pkt_randomizer == NULL) {
+		res = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+	memset(*pp_pkt_randomizer, 0, sizeof(osm_pkt_randomizer_t));
+	(*pp_pkt_randomizer)->num_paths_initialized = 0;
+
+	tmp = atol(getenv("OSM_PKT_DROP_RATE"));
+	(*pp_pkt_randomizer)->osm_pkt_drop_rate = tmp;
+
+	if (getenv("OSM_PKT_NUM_UNSTABLE_LINKS") != NULL
+	    && (tmp = atol(getenv("OSM_PKT_NUM_UNSTABLE_LINKS"))) > 0)
+		(*pp_pkt_randomizer)->osm_pkt_num_unstable_links = tmp;
+	else
+		(*pp_pkt_randomizer)->osm_pkt_num_unstable_links = 1;
+
+	if (getenv("OSM_PKT_UNSTABLE_LINK_RATE") != NULL
+	    && (tmp = atol(getenv("OSM_PKT_UNSTABLE_LINK_RATE"))) > 0)
+		(*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = tmp;
+	else
+		(*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = 20;
+
+	OSM_LOG(p_log, OSM_LOG_VERBOSE, "Using OSM_PKT_DROP_RATE=%u \n"
+		"\t\t\t\t OSM_PKT_NUM_UNSTABLE_LINKS=%u \n"
+		"\t\t\t\t OSM_PKT_UNSTABLE_LINK_RATE=%u \n",
+		(*pp_pkt_randomizer)->osm_pkt_drop_rate,
+		(*pp_pkt_randomizer)->osm_pkt_num_unstable_links,
+		(*pp_pkt_randomizer)->osm_pkt_unstable_link_rate);
+
+	/* allocate the fault_dr_paths variable */
+	/* It is the number of the paths that will be saved as fault = osm_pkt_num_unstable_links */
+	(*pp_pkt_randomizer)->fault_dr_paths = malloc(sizeof(osm_dr_path_t) *
+						      (*pp_pkt_randomizer)->
+						      osm_pkt_num_unstable_links);
+	if ((*pp_pkt_randomizer)->fault_dr_paths == NULL) {
+		res = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+
+	memset((*pp_pkt_randomizer)->fault_dr_paths, 0,
+	       sizeof(osm_dr_path_t) *
+	       (*pp_pkt_randomizer)->osm_pkt_num_unstable_links);
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (res);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkt_randomizer_destroy(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer,
+			   IN osm_log_t * p_log)
+{
+	OSM_LOG_ENTER(p_log);
+
+	if (*pp_pkt_randomizer != NULL) {
+		free((*pp_pkt_randomizer)->fault_dr_paths);
+		free(*pp_pkt_randomizer);
+	}
+	OSM_LOG_EXIT(p_log);
+}
diff --git a/libvendor/osm_vendor_ibumad.c b/libvendor/osm_vendor_ibumad.c
new file mode 100644
index 0000000..734a860
--- /dev/null
+++ b/libvendor/osm_vendor_ibumad.c
@@ -0,0 +1,1154 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_vendor_t (for umad).
+ * This object represents the OpenIB vendor layer.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#ifdef OSM_VENDOR_INTF_OPENIB
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_math.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/****s* OpenSM: Vendor UMAD/osm_umad_bind_info_t
+ * NAME
+ *   osm_umad_bind_info_t
+ *
+ * DESCRIPTION
+ *    Structure containing bind information.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_umad_bind_info {
+	osm_vendor_t *p_vend;
+	void *client_context;
+	osm_mad_pool_t *p_mad_pool;
+	osm_vend_mad_recv_callback_t mad_recv_callback;
+	osm_vend_mad_send_err_callback_t send_err_callback;
+	ib_net64_t port_guid;
+	int port_id;
+	int agent_id;
+	int agent_id1;		/* SMI requires two agents */
+} osm_umad_bind_info_t;
+
+typedef struct _umad_receiver {
+	pthread_t tid;
+	osm_vendor_t *p_vend;
+	osm_log_t *p_log;
+} umad_receiver_t;
+
+static void osm_vendor_close_port(osm_vendor_t * const p_vend);
+
+static void clear_madw(osm_vendor_t * p_vend)
+{
+	umad_match_t *m, *e, *old_m;
+	ib_net64_t old_tid;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+	pthread_mutex_lock(&p_vend->match_tbl_mutex);
+	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
+		if (m->tid) {
+			old_m = m;
+			old_tid = m->tid;
+			m->tid = 0;
+			osm_mad_pool_put(((osm_umad_bind_info_t
+					   *) ((osm_madw_t *) m->v)->h_bind)->
+					 p_mad_pool, m->v);
+			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5401: "
+				"evicting entry %p (tid was 0x%" PRIx64 ")\n",
+				old_m, old_tid);
+			goto Exit;
+		}
+	}
+	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+static osm_madw_t *get_madw(osm_vendor_t * p_vend, ib_net64_t * tid)
+{
+	umad_match_t *m, *e;
+	ib_net64_t mtid = (*tid & CL_HTON64(0x00000000ffffffffllu));
+	osm_madw_t *res;
+
+	/*
+	 * Since mtid == 0 is the empty key, we should not
+	 * waste time looking for it
+	 */
+	if (mtid == 0)
+		return 0;
+
+	pthread_mutex_lock(&p_vend->match_tbl_mutex);
+	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
+		if (m->tid == mtid) {
+			m->tid = 0;
+			*tid = mtid;
+			res = m->v;
+			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+			return res;
+		}
+	}
+
+	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+	return 0;
+}
+
+static void
+put_madw(osm_vendor_t * p_vend, osm_madw_t * p_madw, ib_net64_t tid)
+{
+	umad_match_t *m, *e, *old_lru, *lru = 0;
+	osm_madw_t *p_req_madw;
+	osm_umad_bind_info_t *p_bind;
+	ib_net64_t old_tid;
+	uint32_t oldest = ~0;
+
+	pthread_mutex_lock(&p_vend->match_tbl_mutex);
+	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
+		if (m->tid == 0) {
+			m->tid = tid;
+			m->v = p_madw;
+			m->version =
+			    cl_atomic_inc((atomic32_t *) & p_vend->mtbl.
+					  last_version);
+			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+			return;
+		}
+		if (oldest > m->version) {
+			oldest = m->version;
+			lru = m;
+		}
+	}
+
+	old_lru = lru;
+	old_tid = lru->tid;
+	p_req_madw = old_lru->v;
+	p_bind = p_req_madw->h_bind;
+	p_req_madw->status = IB_CANCELED;
+	pthread_mutex_lock(&p_vend->cb_mutex);
+	(*p_bind->send_err_callback) (p_bind->client_context, p_req_madw);
+	pthread_mutex_unlock(&p_vend->cb_mutex);
+	lru->tid = tid;
+	lru->v = p_madw;
+	lru->version =
+	    cl_atomic_inc((atomic32_t *) & p_vend->mtbl.last_version);
+	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
+	OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5402: "
+		"evicting entry %p (tid was 0x%" PRIx64 ")\n", old_lru,
+		cl_ntoh64(old_tid));
+}
+
+static void
+ib_mad_addr_conv(ib_user_mad_t * umad, osm_mad_addr_t * osm_mad_addr,
+		 int is_smi)
+{
+	ib_mad_addr_t *ib_mad_addr = umad_get_mad_addr(umad);
+	osm_mad_addr->dest_lid = ib_mad_addr->lid;
+	osm_mad_addr->path_bits = ib_mad_addr->path_bits;
+	osm_mad_addr->static_rate = 0;
+
+	if (is_smi) {
+		osm_mad_addr->addr_type.smi.source_lid = osm_mad_addr->dest_lid;
+		osm_mad_addr->addr_type.smi.port_num = 255;	/* not used */
+		return;
+	}
+
+	osm_mad_addr->addr_type.gsi.remote_qp = ib_mad_addr->qpn;
+	osm_mad_addr->addr_type.gsi.remote_qkey = ib_mad_addr->qkey;
+	osm_mad_addr->addr_type.gsi.pkey_ix = umad_get_pkey(umad);
+	osm_mad_addr->addr_type.gsi.service_level = ib_mad_addr->sl;
+	osm_mad_addr->addr_type.gsi.global_route = 0;	/* FIXME: handle GRH */
+	memset(&osm_mad_addr->addr_type.gsi.grh_info, 0,
+	       sizeof osm_mad_addr->addr_type.gsi.grh_info);
+}
+
+static void *swap_mad_bufs(osm_madw_t * p_madw, void *umad)
+{
+	void *old;
+
+	old = p_madw->vend_wrap.umad;
+	p_madw->vend_wrap.umad = umad;
+	p_madw->p_mad = umad_get_mad(umad);
+
+	return old;
+}
+
+static void unlock_mutex(void *arg)
+{
+	pthread_mutex_unlock(arg);
+}
+
+static void *umad_receiver(void *p_ptr)
+{
+	umad_receiver_t *const p_ur = (umad_receiver_t *) p_ptr;
+	osm_vendor_t *p_vend = p_ur->p_vend;
+	osm_umad_bind_info_t *p_bind;
+	ib_mad_addr_t *ib_mad_addr;
+	osm_mad_addr_t osm_addr;
+	osm_madw_t *p_madw, *p_req_madw;
+	ib_mad_t *mad;
+	void *umad = 0;
+	int mad_agent, length;
+
+	OSM_LOG_ENTER(p_ur->p_log);
+
+	for (;;) {
+		if (!umad &&
+		    !(umad = umad_alloc(1, umad_size() + MAD_BLOCK_SIZE))) {
+			OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5403: "
+				"can't alloc MAD sized umad\n");
+			break;
+		}
+
+		length = MAD_BLOCK_SIZE;
+		if ((mad_agent = umad_recv(p_vend->umad_port_id, umad,
+					   &length, -1)) < 0) {
+			if (length <= MAD_BLOCK_SIZE) {
+				OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5404: "
+					"recv error on MAD sized umad (%m)\n");
+				continue;
+			} else {
+				umad_free(umad);
+				/* Need a larger buffer for RMPP */
+				umad = umad_alloc(1, umad_size() + length);
+				if (!umad) {
+					OSM_LOG(p_ur->p_log, OSM_LOG_ERROR,
+						"ERR 5405: "
+						"can't alloc umad length %d\n",
+						length);
+					continue;
+				}
+
+				if ((mad_agent = umad_recv(p_vend->umad_port_id,
+							   umad, &length,
+							   -1)) < 0) {
+					OSM_LOG(p_ur->p_log, OSM_LOG_ERROR,
+						"ERR 5406: "
+						"recv error on umad length %d (%m)\n",
+						length);
+					continue;
+				}
+			}
+		}
+
+		if (mad_agent >= UMAD_CA_MAX_AGENTS ||
+		    !(p_bind = p_vend->agents[mad_agent])) {
+			OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5407: "
+				"invalid mad agent %d - dropping\n", mad_agent);
+			continue;
+		}
+
+		mad = (ib_mad_t *) umad_get_mad(umad);
+		ib_mad_addr = umad_get_mad_addr(umad);
+
+		ib_mad_addr_conv(umad, &osm_addr,
+				 mad->mgmt_class == IB_MCLASS_SUBN_LID ||
+				 mad->mgmt_class == IB_MCLASS_SUBN_DIR);
+
+		if (!(p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
+						(osm_bind_handle_t) p_bind,
+						MAX(length, MAD_BLOCK_SIZE),
+						&osm_addr))) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5408: "
+				"request for a new madw failed -- dropping packet\n");
+			continue;
+		}
+
+		/* Need to fix up MAD size if short RMPP packet */
+		if (length < MAD_BLOCK_SIZE)
+			p_madw->mad_size = length;
+
+		/*
+		 * Avoid copying by swapping mad buf pointers.
+		 * Do not use umad after this line of code.
+		 */
+		umad = swap_mad_bufs(p_madw, umad);
+
+		/* if status != 0 then we are handling recv timeout on send */
+		if (umad_status(p_madw->vend_wrap.umad)) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5409: "
+				"send completed with error"
+				" (method=0x%X attr=0x%X trans_id=0x%" PRIx64
+				") -- dropping\n",
+				mad->method, cl_ntoh16(mad->attr_id),
+				cl_ntoh64(mad->trans_id));
+			if (mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
+				/* LID routed */
+				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
+					"ERR 5410: class 0x%x LID 0x%x\n",
+					mad->mgmt_class,
+					cl_ntoh16(ib_mad_addr->lid));
+			} else {
+				ib_smp_t *smp;
+
+				/* Direct routed SMP */
+				smp = (ib_smp_t *) mad;
+				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
+					"ERR 5411: DR SMP Hop Ptr: 0x%X\n",
+					smp->hop_ptr);
+				osm_dump_smp_dr_path(p_vend->p_log, smp,
+						     OSM_LOG_ERROR);
+			}
+
+			if (!(p_req_madw = get_madw(p_vend, &mad->trans_id))) {
+				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
+					"ERR 5412: "
+					"Failed to obtain request madw for timed out MAD"
+					"(method=0x%X attr=0x%X tid=0x%"PRIx64") -- dropping\n",
+					mad->method, cl_ntoh16(mad->attr_id),
+					cl_ntoh64(mad->trans_id));
+			} else {
+				p_req_madw->status = IB_TIMEOUT;
+				/* cb frees req_madw */
+				pthread_mutex_lock(&p_vend->cb_mutex);
+				pthread_cleanup_push(unlock_mutex,
+						     &p_vend->cb_mutex);
+				(*p_bind->send_err_callback) (p_bind->
+							      client_context,
+							      p_req_madw);
+				pthread_cleanup_pop(1);
+			}
+
+			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+			continue;
+		}
+
+		p_req_madw = 0;
+		if (ib_mad_is_response(mad) &&
+		    !(p_req_madw = get_madw(p_vend, &mad->trans_id))) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5413: "
+				"Failed to obtain request madw for received MAD"
+				"(method=0x%X attr=0x%X tid=0x%"PRIx64") -- dropping\n",
+				mad->method, cl_ntoh16((mad)->attr_id),
+				cl_ntoh64(mad->trans_id));
+			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+			continue;
+		}
+#ifndef VENDOR_RMPP_SUPPORT
+		if ((mad->mgmt_class != IB_MCLASS_SUBN_DIR) &&
+		    (mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
+		    (ib_rmpp_is_flag_set((ib_rmpp_mad_t *) mad,
+					 IB_RMPP_FLAG_ACTIVE))) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5414: "
+				"class 0x%x method 0x%x RMPP version %d type "
+				"%d flags 0x%x received -- dropping\n",
+				mad->mgmt_class, mad->method,
+				((ib_rmpp_mad_t *) mad)->rmpp_version,
+				((ib_rmpp_mad_t *) mad)->rmpp_type,
+				((ib_rmpp_mad_t *) mad)->rmpp_flags);
+			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+			continue;
+		}
+#endif
+
+		/* call the CB */
+		pthread_mutex_lock(&p_vend->cb_mutex);
+		pthread_cleanup_push(unlock_mutex, &p_vend->cb_mutex);
+		(*p_bind->mad_recv_callback) (p_madw, p_bind->client_context,
+					      p_req_madw);
+		pthread_cleanup_pop(1);
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return NULL;
+}
+
+static int umad_receiver_start(osm_vendor_t * p_vend)
+{
+	umad_receiver_t *p_ur = p_vend->receiver;
+
+	p_ur->p_vend = p_vend;
+	p_ur->p_log = p_vend->p_log;
+
+	if (pthread_create(&p_ur->tid, NULL, umad_receiver, p_ur) < 0)
+		return -1;
+
+	return 0;
+}
+
+static void umad_receiver_stop(umad_receiver_t * p_ur)
+{
+	pthread_cancel(p_ur->tid);
+	pthread_join(p_ur->tid, NULL);
+	p_ur->tid = 0;
+	p_ur->p_vend = NULL;
+	p_ur->p_log = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_init(IN osm_vendor_t * const p_vend,
+		IN osm_log_t * const p_log, IN const uint32_t timeout)
+{
+	char *max = NULL;
+	int r, n_cas;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_vend->p_log = p_log;
+	p_vend->timeout = timeout;
+	p_vend->max_retries = OSM_DEFAULT_RETRY_COUNT;
+	pthread_mutex_init(&p_vend->cb_mutex, NULL);
+	pthread_mutex_init(&p_vend->match_tbl_mutex, NULL);
+	p_vend->umad_port_id = -1;
+	p_vend->issmfd = -1;
+
+	/*
+	 * Open our instance of UMAD.
+	 */
+	if ((r = umad_init()) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
+			"ERR 5415: Error opening UMAD\n");
+	}
+
+	if ((n_cas = umad_get_cas_names(p_vend->ca_names,
+					OSM_UMAD_MAX_CAS)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
+			"ERR 5416: umad_get_cas_names failed\n");
+		r = n_cas;
+		goto Exit;
+	}
+
+	p_vend->ca_count = n_cas;
+	p_vend->mtbl.max = DEFAULT_OSM_UMAD_MAX_PENDING;
+
+	if ((max = getenv("OSM_UMAD_MAX_PENDING")) != NULL) {
+		int tmp = strtol(max, NULL, 0);
+		if (tmp > 0)
+			p_vend->mtbl.max = tmp;
+		else
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:"
+				"OSM_UMAD_MAX_PENDING=%d is invalid",
+				tmp);
+	}
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_INFO, "%d pending umads specified\n",
+		p_vend->mtbl.max);
+
+	p_vend->mtbl.tbl = calloc(p_vend->mtbl.max, sizeof(*(p_vend->mtbl.tbl)));
+	if (!p_vend->mtbl.tbl) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:"
+			"failed to allocate vendor match table\n");
+		r = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (r);
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
+			     IN const uint32_t timeout)
+{
+	osm_vendor_t *p_vend = NULL;
+
+	OSM_LOG_ENTER(p_log);
+
+	if (!timeout) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5433: "
+			"transaction timeout cannot be 0\n");
+		goto Exit;
+	}
+
+	p_vend = malloc(sizeof(*p_vend));
+	if (p_vend == NULL) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5417: "
+			"Unable to allocate vendor object\n");
+		goto Exit;
+	}
+
+	memset(p_vend, 0, sizeof(*p_vend));
+
+	if (osm_vendor_init(p_vend, p_log, timeout) < 0) {
+		free(p_vend);
+		p_vend = NULL;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (p_vend);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
+{
+	osm_vendor_close_port(*pp_vend);
+
+	clear_madw(*pp_vend);
+	/* make sure all ports are closed */
+	umad_done();
+
+	pthread_mutex_destroy(&(*pp_vend)->cb_mutex);
+	pthread_mutex_destroy(&(*pp_vend)->match_tbl_mutex);
+	free((*pp_vend)->mtbl.tbl);
+	free(*pp_vend);
+	*pp_vend = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+			     IN ib_port_attr_t * const p_attr_array,
+			     IN uint32_t * const p_num_ports)
+{
+	umad_ca_t ca;
+	ib_port_attr_t *attr = p_attr_array;
+	unsigned done = 0;
+	int r, i, j;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend && p_num_ports);
+
+	if (!*p_num_ports) {
+		r = IB_INVALID_PARAMETER;
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5418: "
+			"Ports in should be > 0\n");
+		goto Exit;
+	}
+
+	if (!p_attr_array) {
+		r = IB_INSUFFICIENT_MEMORY;
+		*p_num_ports = 0;
+		goto Exit;
+	}
+
+	for (i = 0; i < p_vend->ca_count && !done; i++) {
+		/*
+		 * For each CA, retrieve the port guids
+		 */
+		if (umad_get_ca(p_vend->ca_names[i], &ca) == 0) {
+			if (ca.node_type < 1 || ca.node_type > 3)
+				continue;
+			for (j = 0; j <= ca.numports; j++) {
+				if (!ca.ports[j])
+					continue;
+				attr->port_guid = ca.ports[j]->port_guid;
+				attr->lid = ca.ports[j]->base_lid;
+				attr->port_num = ca.ports[j]->portnum;
+				attr->sm_lid = ca.ports[j]->sm_lid;
+				attr->link_state = ca.ports[j]->state;
+				attr++;
+				if (attr - p_attr_array > *p_num_ports) {
+					done = 1;
+					break;
+				}
+			}
+			umad_release_ca(&ca);
+		}
+	}
+
+	*p_num_ports = attr - p_attr_array;
+	r = 0;
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return r;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+osm_vendor_open_port(IN osm_vendor_t * const p_vend,
+		     IN const ib_net64_t port_guid)
+{
+	ib_net64_t portguids[OSM_UMAD_MAX_PORTS_PER_CA + 1];
+	umad_ca_t umad_ca;
+	int i = 0, umad_port_id = -1;
+	char *name;
+	int ca, r;
+
+	CL_ASSERT(p_vend);
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	if (p_vend->umad_port_id >= 0) {
+		umad_port_id = p_vend->umad_port_id;
+		goto Exit;
+	}
+
+	if (!port_guid) {
+		name = NULL;
+		i = 0;
+		goto _found;
+	}
+
+	for (ca = 0; ca < p_vend->ca_count; ca++) {
+		if ((r = umad_get_ca_portguids(p_vend->ca_names[ca],
+					       portguids,
+					       OSM_UMAD_MAX_CAS)) < 0) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5421: "
+				"Unable to get CA %s port guids (%s)\n",
+				p_vend->ca_names[ca], strerror(r));
+			goto Exit;
+		}
+		for (i = 0; i < r; i++)
+			if (port_guid == portguids[i]) {
+				name = p_vend->ca_names[ca];
+				goto _found;
+			}
+	}
+
+	/*
+	 * No local CA owns this guid!
+	 */
+	OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5422: "
+		"Unable to find requested CA guid 0x%" PRIx64 "\n",
+		cl_ntoh64(port_guid));
+	goto Exit;
+
+_found:
+	/* Validate that node is an IB node type (not iWARP) */
+	if (umad_get_ca(name, &umad_ca) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542A: "
+			"umad_get_ca() failed\n");
+		goto Exit;
+	}
+
+	if (umad_ca.node_type < 1 || umad_ca.node_type > 3) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542D: "
+			"Type %d of node \'%s\' is not an IB node type\n",
+			umad_ca.node_type, umad_ca.ca_name);
+		fprintf(stderr,
+			"Type %d of node \'%s\' is not an IB node type\n",
+			umad_ca.node_type, umad_ca.ca_name);
+		umad_release_ca(&umad_ca);
+		goto Exit;
+	}
+	umad_release_ca(&umad_ca);
+
+	/* Port found, try to open it */
+	if (umad_get_port(name, i, &p_vend->umad_port) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542B: "
+			"umad_get_port() failed\n");
+		goto Exit;
+	}
+
+	if ((umad_port_id = umad_open_port(p_vend->umad_port.ca_name,
+					   p_vend->umad_port.portnum)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542C: "
+			"umad_open_port() failed\n");
+		goto Exit;
+	}
+
+	p_vend->umad_port_id = umad_port_id;
+
+	/* start receiver thread */
+	if (!(p_vend->receiver = calloc(1, sizeof(umad_receiver_t)))) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5423: "
+			"Unable to alloc receiver struct\n");
+		umad_close_port(umad_port_id);
+		umad_release_port(&p_vend->umad_port);
+		p_vend->umad_port.port_guid = 0;
+		p_vend->umad_port_id = umad_port_id = -1;
+		goto Exit;
+	}
+	if (umad_receiver_start(p_vend) != 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5420: "
+			"umad_receiver_init failed\n");
+		umad_close_port(umad_port_id);
+		umad_release_port(&p_vend->umad_port);
+		p_vend->umad_port.port_guid = 0;
+		p_vend->umad_port_id = umad_port_id = -1;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return umad_port_id;
+}
+
+static void osm_vendor_close_port(osm_vendor_t * const p_vend)
+{
+	umad_receiver_t *p_ur;
+	int i;
+
+	p_ur = p_vend->receiver;
+	p_vend->receiver = NULL;
+	if (p_ur) {
+		umad_receiver_stop(p_ur);
+		free(p_ur);
+	}
+
+	if (p_vend->umad_port_id >= 0) {
+		for (i = 0; i < UMAD_CA_MAX_AGENTS; i++)
+			if (p_vend->agents[i])
+				umad_unregister(p_vend->umad_port_id, i);
+		umad_close_port(p_vend->umad_port_id);
+		umad_release_port(&p_vend->umad_port);
+		p_vend->umad_port.port_guid = 0;
+		p_vend->umad_port_id = -1;
+	}
+}
+
+static int set_bit(int nr, void *method_mask)
+{
+	long mask, *addr = method_mask;
+	int retval;
+
+	addr += nr / (8 * sizeof(long));
+	mask = 1L << (nr % (8 * sizeof(long)));
+	retval = (mask & *addr) != 0;
+	*addr |= mask;
+	return retval;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_bind_handle_t
+osm_vendor_bind(IN osm_vendor_t * const p_vend,
+		IN osm_bind_info_t * const p_user_bind,
+		IN osm_mad_pool_t * const p_mad_pool,
+		IN osm_vend_mad_recv_callback_t mad_recv_callback,
+		IN osm_vend_mad_send_err_callback_t send_err_callback,
+		IN void *context)
+{
+	ib_net64_t port_guid;
+	osm_umad_bind_info_t *p_bind = 0;
+	long method_mask[16 / sizeof(long)];
+	int umad_port_id;
+	uint8_t rmpp_version;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_user_bind);
+	CL_ASSERT(p_mad_pool);
+	CL_ASSERT(mad_recv_callback);
+	CL_ASSERT(send_err_callback);
+
+	port_guid = p_user_bind->port_guid;
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_INFO,
+		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	if ((umad_port_id = osm_vendor_open_port(p_vend, port_guid)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5424: "
+			"Unable to open port 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid));
+		goto Exit;
+	}
+
+	if (umad_get_issm_path(p_vend->umad_port.ca_name,
+			       p_vend->umad_port.portnum,
+			       p_vend->issm_path,
+			       sizeof(p_vend->issm_path)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542E: "
+			"Cannot resolve issm path for port %s:%u\n",
+			p_vend->umad_port.ca_name, p_vend->umad_port.portnum);
+		goto Exit;
+	}
+
+	if (!(p_bind = malloc(sizeof(*p_bind)))) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5425: "
+			"Unable to allocate internal bind object\n");
+		goto Exit;
+	}
+
+	memset(p_bind, 0, sizeof(*p_bind));
+	p_bind->p_vend = p_vend;
+	p_bind->port_id = umad_port_id;
+	p_bind->client_context = context;
+	p_bind->mad_recv_callback = mad_recv_callback;
+	p_bind->send_err_callback = send_err_callback;
+	p_bind->p_mad_pool = p_mad_pool;
+	p_bind->port_guid = port_guid;
+
+	memset(method_mask, 0, sizeof method_mask);
+	if (p_user_bind->is_responder) {
+		set_bit(IB_MAD_METHOD_GET, &method_mask);
+		set_bit(IB_MAD_METHOD_SET, &method_mask);
+		if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM) {
+			set_bit(IB_MAD_METHOD_GETTABLE, &method_mask);
+			set_bit(IB_MAD_METHOD_DELETE, &method_mask);
+#ifdef DUAL_SIDED_RMPP
+			set_bit(IB_MAD_METHOD_GETMULTI, &method_mask);
+#endif
+			/* Add in IB_MAD_METHOD_GETTRACETABLE */
+			/* when supported by OpenSM */
+		}
+	}
+	if (p_user_bind->is_report_processor)
+		set_bit(IB_MAD_METHOD_REPORT, &method_mask);
+	if (p_user_bind->is_trap_processor) {
+		set_bit(IB_MAD_METHOD_TRAP, &method_mask);
+		set_bit(IB_MAD_METHOD_TRAP_REPRESS, &method_mask);
+	}
+#ifndef VENDOR_RMPP_SUPPORT
+	rmpp_version = 0;
+#else
+	/* If SA class, set rmpp_version */
+	if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM)
+		rmpp_version = 1;
+	else
+		rmpp_version = 0;
+#endif
+
+	if ((p_bind->agent_id = umad_register(p_vend->umad_port_id,
+					      p_user_bind->mad_class,
+					      p_user_bind->class_version,
+					      rmpp_version, method_mask)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5426: "
+			"Unable to register class %u version %u\n",
+			p_user_bind->mad_class, p_user_bind->class_version);
+		free(p_bind);
+		p_bind = 0;
+		goto Exit;
+	}
+
+	if (p_bind->agent_id >= UMAD_CA_MAX_AGENTS ||
+	    p_vend->agents[p_bind->agent_id]) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5427: "
+			"bad agent id %u or duplicate agent for class %u vers %u\n",
+			p_bind->agent_id, p_user_bind->mad_class,
+			p_user_bind->class_version);
+		free(p_bind);
+		p_bind = 0;
+		goto Exit;
+	}
+
+	p_vend->agents[p_bind->agent_id] = p_bind;
+
+	/* If Subn Directed Route class, register Subn LID routed class */
+	if (p_user_bind->mad_class == IB_MCLASS_SUBN_DIR) {
+		if ((p_bind->agent_id1 = umad_register(p_vend->umad_port_id,
+						       IB_MCLASS_SUBN_LID,
+						       p_user_bind->
+						       class_version, 0,
+						       method_mask)) < 0) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5428: "
+				"Unable to register class 1 version %u\n",
+				p_user_bind->class_version);
+			free(p_bind);
+			p_bind = 0;
+			goto Exit;
+		}
+
+		if (p_bind->agent_id1 >= UMAD_CA_MAX_AGENTS ||
+		    p_vend->agents[p_bind->agent_id1]) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5429: "
+				"bad agent id %u or duplicate agent for class 1 vers %u\n",
+				p_bind->agent_id1, p_user_bind->class_version);
+			free(p_bind);
+			p_bind = 0;
+			goto Exit;
+		}
+
+		p_vend->agents[p_bind->agent_id1] = p_bind;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return ((osm_bind_handle_t) p_bind);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_vendor_recv_dummy_cb(IN osm_madw_t * p_madw,
+			   IN void *bind_context, IN osm_madw_t * p_req_madw)
+{
+#ifdef _DEBUG_
+	fprintf(stderr,
+		"__osm_vendor_recv_dummy_cb: Ignoring received MAD after osm_vendor_unbind\n");
+#endif
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_vendor_send_err_dummy_cb(IN void *bind_context,
+			       IN osm_madw_t * p_req_madw)
+{
+#ifdef _DEBUG_
+	fprintf(stderr,
+		"__osm_vendor_send_err_dummy_cb: Ignoring send error after osm_vendor_unbind\n");
+#endif
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
+{
+	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
+	osm_vendor_t *p_vend = p_bind->p_vend;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	pthread_mutex_lock(&p_vend->cb_mutex);
+	p_bind->mad_recv_callback = __osm_vendor_recv_dummy_cb;
+	p_bind->send_err_callback = __osm_vendor_send_err_dummy_cb;
+	pthread_mutex_unlock(&p_vend->cb_mutex);
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
+			 IN const uint32_t mad_size,
+			 IN osm_vend_wrap_t * const p_vw)
+{
+	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
+	osm_vendor_t *p_vend = p_bind->p_vend;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG,
+		"Acquiring UMAD for p_madw = %p, size = %u\n", p_vw, mad_size);
+	CL_ASSERT(p_vw);
+	p_vw->size = mad_size;
+	p_vw->umad = umad_alloc(1, mad_size + umad_size());
+
+	/* track locally */
+	p_vw->h_bind = h_bind;
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG,
+		"Acquired UMAD %p, size = %u\n", p_vw->umad, p_vw->size);
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return umad_get_mad(p_vw->umad);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
+{
+	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
+	osm_vendor_t *p_vend = p_bind->p_vend;
+	osm_madw_t *p_madw;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vw);
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Retiring UMAD %p\n", p_vw->umad);
+
+	/*
+	 * We moved the removal of the transaction to immediately after
+	 * it was looked up.
+	 */
+
+	/* free the mad but the wrapper is part of the madw object */
+	umad_free(p_vw->umad);
+	p_vw->umad = 0;
+	p_madw = PARENT_STRUCT(p_vw, osm_madw_t, vend_wrap);
+	p_madw->p_mad = NULL;
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_send(IN osm_bind_handle_t h_bind,
+		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
+{
+	osm_umad_bind_info_t *const p_bind = h_bind;
+	osm_vendor_t *const p_vend = p_bind->p_vend;
+	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
+	osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
+	ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
+	ib_sa_mad_t *const p_sa = (ib_sa_mad_t *) p_mad;
+	int ret = -1;
+	int is_rmpp = 0;
+	uint32_t sent_mad_size;
+#ifndef VENDOR_RMPP_SUPPORT
+	uint32_t paylen = 0;
+#endif
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vw->h_bind == h_bind);
+	CL_ASSERT(p_mad == umad_get_mad(p_vw->umad));
+
+	if (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
+		umad_set_addr_net(p_vw->umad, 0xffff, 0, 0, 0);
+		umad_set_grh(p_vw->umad, 0);
+		goto Resp;
+	}
+	if (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) {
+		umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid, 0, 0, 0);
+		umad_set_grh(p_vw->umad, 0);
+		goto Resp;
+	}
+	/* GSI classes */
+	umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid,
+			  p_mad_addr->addr_type.gsi.remote_qp,
+			  p_mad_addr->addr_type.gsi.service_level,
+			  IB_QP1_WELL_KNOWN_Q_KEY);
+	umad_set_grh(p_vw->umad, 0);	/* FIXME: GRH support */
+	umad_set_pkey(p_vw->umad, p_mad_addr->addr_type.gsi.pkey_ix);
+	if (ib_class_is_rmpp(p_mad->mgmt_class)) {	/* RMPP GSI classes     FIXME: no GRH */
+		if (!ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa,
+					 IB_RMPP_FLAG_ACTIVE)) {
+			/* Clear RMPP header when RMPP not ACTIVE */
+			p_sa->rmpp_version = 0;
+			p_sa->rmpp_type = 0;
+			p_sa->rmpp_flags = 0;
+			p_sa->rmpp_status = 0;
+#ifdef VENDOR_RMPP_SUPPORT
+		} else
+			is_rmpp = 1;
+		OSM_LOG(p_vend->p_log, OSM_LOG_VERBOSE, "RMPP %d length %d\n",
+			ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa,
+					    IB_RMPP_FLAG_ACTIVE),
+			p_madw->mad_size);
+#else
+		} else {
+			p_sa->rmpp_version = 1;
+			p_sa->seg_num = cl_ntoh32(1);	/* first DATA is seg 1 */
+			p_sa->rmpp_flags |= (uint8_t) 0x70;	/* RRespTime of 14 (high 5 bits) */
+			p_sa->rmpp_status = 0;
+			paylen = p_madw->mad_size - IB_SA_MAD_HDR_SIZE;
+			paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE);
+			p_sa->paylen_newwin = cl_ntoh32(paylen);
+		}
+#endif
+	}
+
+Resp:
+	if (resp_expected)
+		put_madw(p_vend, p_madw, p_mad->trans_id);
+
+#ifdef VENDOR_RMPP_SUPPORT
+	sent_mad_size = p_madw->mad_size;
+#else
+	sent_mad_size = is_rmpp ? p_madw->mad_size - IB_SA_MAD_HDR_SIZE :
+	    p_madw->mad_size;
+#endif
+	if ((ret = umad_send(p_bind->port_id, p_bind->agent_id, p_vw->umad,
+			     sent_mad_size,
+			     resp_expected ? p_vend->timeout : 0,
+			     p_vend->max_retries)) < 0) {
+		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5430: "
+			"Send p_madw = %p of size %d failed %d (%m)\n",
+			p_madw, sent_mad_size, ret);
+		if (resp_expected) {
+			get_madw(p_vend, &p_mad->trans_id);	/* remove from aging table */
+			p_madw->status = IB_ERROR;
+			pthread_mutex_lock(&p_vend->cb_mutex);
+			(*p_bind->send_err_callback) (p_bind->client_context, p_madw);	/* cb frees madw */
+			pthread_mutex_unlock(&p_vend->cb_mutex);
+		} else
+			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+		goto Exit;
+	}
+
+	if (!resp_expected)
+		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+
+	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Completed sending %s p_madw = %p\n",
+		resp_expected ? "request" : "response or unsolicited", p_madw);
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (ret);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
+{
+	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
+	osm_vendor_t *p_vend = p_bind->p_vend;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+	;
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (0);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
+{
+	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
+	osm_vendor_t *p_vend = p_bind->p_vend;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+	if (TRUE == is_sm_val) {
+		p_vend->issmfd = open(p_vend->issm_path, O_NONBLOCK);
+		if (p_vend->issmfd < 0) {
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5431: "
+				"setting IS_SM capmask: cannot open file "
+				"\'%s\': %s\n",
+				p_vend->issm_path, strerror(errno));
+			p_vend->issmfd = -1;
+		}
+	} else if (p_vend->issmfd != -1) {
+		if (0 != close(p_vend->issmfd))
+			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5432: "
+				"clearing IS_SM capmask: cannot close: %s\n",
+				strerror(errno));
+		p_vend->issmfd = -1;
+	}
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
+{
+	umad_debug(level);
+}
+
+#endif				/* OSM_VENDOR_INTF_OPENIB */
diff --git a/libvendor/osm_vendor_ibumad_sa.c b/libvendor/osm_vendor_ibumad_sa.c
new file mode 100644
index 0000000..800b308
--- /dev/null
+++ b/libvendor/osm_vendor_ibumad_sa.c
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <complib/cl_event.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;
+	cl_event_t sync_event;
+	time_t last_lids_update_sec;
+} osmv_sa_bind_info_t;
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/*
+  Call back on new mad received:
+
+  We basically only need to set the context of the query.
+  Or report an error.
+
+  A pointer to the actual context of the request (a copy of the oriignal
+  request structure) is attached as the p_madw->context.ni_context.node_guid
+*/
+static void
+__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
+		     IN void *bind_context, IN osm_madw_t * p_req_madw)
+{
+	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
+	osmv_query_req_t *p_query_req_copy = NULL;
+	osmv_query_res_t query_res;
+	ib_sa_mad_t *p_sa_mad;
+	ib_net16_t mad_status;
+
+	OSM_LOG_ENTER(p_bind->p_log);
+
+	if (!p_req_madw) {
+		OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
+			"Ignoring a non-response mad\n");
+		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+		goto Exit;
+	}
+
+	/* obtain the sent context since we store it during send in the ni_ctx */
+	p_query_req_copy =
+	    (osmv_query_req_t *) (long *)(long)(p_req_madw->context.ni_context.
+						node_guid);
+
+	/* provide the context of the original request in the result */
+	query_res.query_context = p_query_req_copy->query_context;
+
+	/* provide the resulting madw */
+	query_res.p_result_madw = p_madw;
+
+	/* update the req fields */
+	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
+
+	/* if we got a remote error track it in the status */
+	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
+	if (mad_status != IB_SUCCESS) {
+		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: "
+			"Remote error:0x%04X\n", cl_ntoh16(mad_status));
+		query_res.status = IB_REMOTE_ERROR;
+	} else
+		query_res.status = IB_SUCCESS;
+
+	/* what if we have got back an empty mad ? */
+	if (!p_madw->mad_size) {
+		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: "
+			"Got an empty mad\n");
+		query_res.status = IB_ERROR;
+	}
+
+	if (IB_SUCCESS == mad_status) {
+
+		/* if we are in not in a method response of an rmpp nature we must get only 1 */
+		/* HACK: in the future we might need to be smarter for other methods... */
+		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
+			query_res.result_cnt = 1;
+		} else {
+#ifndef VENDOR_RMPP_SUPPORT
+			if (mad_status != IB_SUCCESS)
+				query_res.result_cnt = 0;
+			else
+				query_res.result_cnt = 1;
+#else
+			if (ib_get_attr_size(p_sa_mad->attr_offset)) {
+				/* we used the offset value to calculate the
+				   number of records in here */
+				query_res.result_cnt = (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,
+					"Count = %u = %zu / %u (%zu)\n",
+					query_res.result_cnt,
+					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
+					ib_get_attr_size(p_sa_mad->attr_offset),
+					(p_madw->mad_size -
+					 IB_SA_MAD_HDR_SIZE) %
+					ib_get_attr_size(p_sa_mad->attr_offset));
+			} else
+				query_res.result_cnt = 0;
+#endif
+		}
+	}
+
+	query_res.query_type = p_query_req_copy->query_type;
+
+	p_query_req_copy->pfn_query_cb(&query_res);
+
+	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+		cl_event_signal(&p_bind->sync_event);
+
+Exit:
+
+	/* free the copied query request if found */
+	if (p_query_req_copy)
+		free(p_query_req_copy);
+
+	/* put back the request madw */
+	if (p_req_madw)
+		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
+
+	OSM_LOG_EXIT(p_bind->p_log);
+}
+
+/*****************************************************************************
+ ****************************************************************************/
+/*
+  Send Error Callback:
+
+  Only report the error and get rid of the mad wrapper
+*/
+static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
+{
+	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
+	osmv_query_req_t *p_query_req_copy = NULL;
+	osmv_query_res_t query_res;
+
+	OSM_LOG_ENTER(p_bind->p_log);
+
+	/* Obtain the sent context etc */
+	p_query_req_copy =
+	    (osmv_query_req_t *) (long *)(long)(p_madw->context.ni_context.
+						node_guid);
+
+	/* provide the context of the original request in the result */
+	query_res.query_context = p_query_req_copy->query_context;
+
+	query_res.p_result_madw = p_madw;
+
+	query_res.status = IB_TIMEOUT;
+	query_res.result_cnt = 0;
+
+	query_res.query_type = p_query_req_copy->query_type;
+
+	p_query_req_copy->pfn_query_cb(&query_res);
+
+	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+		cl_event_signal(&p_bind->sync_event);
+
+	if (p_query_req_copy)
+		free(p_query_req_copy);
+	OSM_LOG_EXIT(p_bind->p_log);
+}
+
+/*****************************************************************************
+ Update lids of vendor umad_port.
+ *****************************************************************************/
+static ib_api_status_t update_umad_port(osm_vendor_t * p_vend)
+{
+	umad_port_t port;
+	if (umad_get_port(p_vend->umad_port.ca_name,
+			  p_vend->umad_port.portnum, &port) < 0)
+		return IB_ERROR;
+	p_vend->umad_port.base_lid = port.base_lid;
+	p_vend->umad_port.sm_lid = port.sm_lid;
+	umad_release_port(&port);
+	return IB_SUCCESS;
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+osm_bind_handle_t
+osmv_bind_sa(IN osm_vendor_t * const p_vend,
+	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
+{
+	osm_bind_info_t bind_info;
+	osm_log_t *p_log = p_vend->p_log;
+	osmv_sa_bind_info_t *p_sa_bind_info;
+	cl_status_t cl_status;
+
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	bind_info.port_guid = port_guid;
+	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+	bind_info.class_version = 2;
+	bind_info.is_responder = FALSE;
+	bind_info.is_trap_processor = FALSE;
+	bind_info.is_report_processor = FALSE;
+	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
+	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
+
+	/* allocate the new sa bind info */
+	p_sa_bind_info =
+	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
+	if (!p_sa_bind_info) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: "
+			"Failed to allocate new bind structure\n");
+		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+		goto Exit;
+	}
+
+	/* store some important context */
+	p_sa_bind_info->p_log = p_log;
+	p_sa_bind_info->p_mad_pool = p_mad_pool;
+	p_sa_bind_info->p_vendor = p_vend;
+
+	/* Bind to the lower level */
+	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */
+
+	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
+		free(p_sa_bind_info);
+		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: "
+			"Failed to bind to vendor GSI\n");
+		goto Exit;
+	}
+
+	/* update time umad_port is initilized now */
+	p_sa_bind_info->last_lids_update_sec = time(NULL);
+
+	/* initialize the sync_event */
+	cl_event_construct(&p_sa_bind_info->sync_event);
+	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
+	if (cl_status != CL_SUCCESS) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: "
+			"cl_init_event failed: %s\n", ib_get_err_str(cl_status));
+		free(p_sa_bind_info);
+		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (p_sa_bind_info);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/****t* OSM Vendor SA Client/osmv_sa_mad_data
+ * NAME
+ *    osmv_sa_mad_data
+ *
+ * DESCRIPTION
+ * Extra fields required to perform a mad query
+ *  This struct is passed to the actual send method
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmv_sa_mad_data {
+	/* MAD data. */
+	uint8_t method;
+	ib_net16_t attr_id;
+	ib_net16_t attr_offset;
+	ib_net32_t attr_mod;
+	ib_net64_t comp_mask;
+	void *p_attr;
+} osmv_sa_mad_data_t;
+/*
+ * method
+ *    The method of the mad to be sent
+ *
+ *  attr_id
+ *     Attribute ID
+ *
+ *  attr_offset
+ *     Offset as defined by RMPP
+ *
+ *  attr_mod
+ *     Attribute modifier
+ *
+ *  comp_mask
+ *     The component mask of the query
+ *
+ *  p_attr
+ *     A pointer to the record of the attribute to be sent.
+ *
+ *****/
+
+/*****************************************************************************
+ *****************************************************************************/
+/* Send a MAD out on the GSI interface */
+static ib_api_status_t
+__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
+		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
+		   IN const osmv_query_req_t * const p_query_req)
+{
+	ib_api_status_t status;
+	ib_mad_t *p_mad_hdr;
+	ib_sa_mad_t *p_sa_mad;
+	osm_madw_t *p_madw;
+	osm_log_t *p_log = p_bind->p_log;
+	static atomic32_t trans_id;
+	boolean_t sync;
+	osmv_query_req_t *p_query_req_copy;
+
+	OSM_LOG_ENTER(p_log);
+
+	/*
+	   since the sm_lid might change we obtain it every send
+	   (actually it is cached in the bind object and refreshed
+	   every 30sec by this proc)
+	 */
+	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
+		status = update_umad_port(p_bind->p_vendor);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
+				"Failed to obtain the SM lid\n");
+			goto Exit;
+		}
+		p_bind->last_lids_update_sec = time(NULL);
+	}
+
+	/* Get a MAD wrapper for the send */
+	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
+				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
+
+	if (p_madw == NULL) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
+			"Unable to acquire MAD\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	/* Initialize the Sent MAD: */
+
+	/* Initialize the MAD buffer for the send operation. */
+	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	/* Get a new transaction Id */
+	cl_atomic_inc(&trans_id);
+
+	/* Cleanup the MAD from any residue */
+	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
+
+	/* Initialize the standard MAD header. */
+	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
+			IB_MCLASS_SUBN_ADM,	/* class */
+			(uint8_t) 2,	/* version */
+			p_sa_mad_data->method,	/* method */
+			cl_hton64((uint64_t) trans_id),	/* tid */
+			p_sa_mad_data->attr_id,	/* attr id */
+			p_sa_mad_data->attr_mod	/* attr mod */);
+
+	/* Set the query information. */
+	p_sa_mad->sm_key = p_query_req->sm_key;
+	p_sa_mad->attr_offset = 0;
+	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
+#ifdef DUAL_SIDED_RMPP
+	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
+		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+	if (p_sa_mad->comp_mask) {
+		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
+	 */
+	p_madw->mad_addr.dest_lid =
+	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
+	p_madw->mad_addr.addr_type.smi.source_lid =
+	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
+	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
+	p_madw->resp_expected = TRUE;
+	p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+	/*
+	   Provide MAD context such that the call back will know what to do.
+	   We have to keep the entire request structure so we know the CB.
+	   Since we can not rely on the client to keep it around until
+	   the response - we duplicate it and will later dispose it (in CB).
+	   To store on the MADW we cast it into what opensm has:
+	   p_madw->context.ni_context.node_guid
+	 */
+	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
+	*p_query_req_copy = *p_query_req;
+	p_madw->context.ni_context.node_guid =
+	    (ib_net64_t) (long)p_query_req_copy;
+
+	/* we can support async as well as sync calls */
+	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
+
+	/* send the mad asynchronously */
+	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
+				 p_madw, p_madw->resp_expected);
+
+	/* if synchronous - wait on the event */
+	if (sync) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
+		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
+		cl_event_reset(&p_bind->sync_event);
+		status = p_madw->status;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+/*
+ * Query the SA based on the user's request.
+ */
+ib_api_status_t
+osmv_query_sa(IN osm_bind_handle_t h_bind,
+	      IN const osmv_query_req_t * const p_query_req)
+{
+	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;
+#ifdef DUAL_SIDED_RMPP
+	ib_multipath_rec_t multipath_rec;
+	osmv_multipath_req_t *p_mpr_req;
+	int i, j;
+#endif
+	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);
+
+	/* 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, "DBG:001 USER_DEFINED\n");
+		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
+		if (p_user_query->method)
+			sa_mad_data.method = p_user_query->method;
+		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;
+		break;
+
+	case OSMV_QUERY_ALL_SVC_RECS:
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
+		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+		sa_mad_data.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, "DBG:001 SVC_REC_BY_NAME\n");
+		sa_mad_data.method = IB_MAD_METHOD_GET;
+		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+		sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
+		sa_mad_data.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, "DBG:001 SVC_REC_BY_ID\n");
+		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+		sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
+		sa_mad_data.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, "DBG:001 CLASS_PORT_INFO\n");
+		sa_mad_data.method = IB_MAD_METHOD_GET;
+		sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
+		sa_mad_data.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, "DBG:001 NODE_REC_BY_NODE_GUID\n");
+		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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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, "DBG:001 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;
+
+#ifdef DUAL_SIDED_RMPP
+	case OSMV_QUERY_MULTIPATH_REC:
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n");
+		/* Validate sgid/dgid counts against SA client limit */
+		p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input;
+		if (p_mpr_req->sgid_count + p_mpr_req->dgid_count >
+		    IB_MULTIPATH_MAX_GIDS) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC "
+				"SGID count %d DGID count %d max count %d\n",
+				p_mpr_req->sgid_count, p_mpr_req->dgid_count,
+				IB_MULTIPATH_MAX_GIDS);
+			CL_ASSERT(0);
+			return IB_ERROR;
+		}
+		memset(&multipath_rec, 0, sizeof(ib_multipath_rec_t));
+		sa_mad_data.method = IB_MAD_METHOD_GETMULTI;
+		sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD;
+		sa_mad_data.attr_offset =
+		    ib_get_attr_offset(sizeof(ib_multipath_rec_t));
+		sa_mad_data.p_attr = &multipath_rec;
+		sa_mad_data.comp_mask = p_mpr_req->comp_mask;
+		multipath_rec.num_path = p_mpr_req->num_path;
+		if (p_mpr_req->reversible)
+			multipath_rec.num_path |= 0x80;
+		else
+			multipath_rec.num_path &= ~0x80;
+		multipath_rec.pkey = p_mpr_req->pkey;
+		ib_multipath_rec_set_sl(&multipath_rec, p_mpr_req->sl);
+		ib_multipath_rec_set_qos_class(&multipath_rec, 0);
+		multipath_rec.independence = p_mpr_req->independence;
+		multipath_rec.sgid_count = p_mpr_req->sgid_count;
+		multipath_rec.dgid_count = p_mpr_req->dgid_count;
+		j = 0;
+		for (i = 0; i < p_mpr_req->sgid_count; i++, j++)
+			multipath_rec.gids[j] = p_mpr_req->gids[j];
+		for (i = 0; i < p_mpr_req->dgid_count; i++, j++)
+			multipath_rec.gids[j] = p_mpr_req->gids[j];
+		break;
+#endif
+
+	default:
+		OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n");
+		CL_ASSERT(0);
+		return IB_ERROR;
+	}
+
+	status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
+
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
diff --git a/libvendor/osm_vendor_mlx.c b/libvendor/osm_vendor_mlx.c
new file mode 100644
index 0000000..683f56d
--- /dev/null
+++ b/libvendor/osm_vendor_mlx.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <vendor/osm_vendor_mlx.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <vendor/osm_vendor_mlx_sender.h>
+#include <vendor/osm_vendor_mlx_hca.h>
+#include <vendor/osm_pkt_randomizer.h>
+
+/**
+ *      FORWARD REFERENCES
+ */
+static ib_api_status_t
+__osmv_get_send_txn(IN osm_bind_handle_t h_bind,
+		    IN osm_madw_t * const p_madw,
+		    IN boolean_t is_rmpp,
+		    IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn);
+
+static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind);
+
+/*
+ *  NAME            osm_vendor_new
+ *
+ *  DESCRIPTION     Create and Initialize the osm_vendor_t Object
+ */
+
+osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
+			     IN const uint32_t timeout)
+{
+	ib_api_status_t status;
+	osm_vendor_t *p_vend;
+
+	OSM_LOG_ENTER(p_log);
+
+	CL_ASSERT(p_log);
+
+	p_vend = malloc(sizeof(*p_vend));
+	if (p_vend != NULL) {
+		memset(p_vend, 0, sizeof(*p_vend));
+
+		status = osm_vendor_init(p_vend, p_log, timeout);
+		if (status != IB_SUCCESS) {
+			osm_vendor_delete(&p_vend);
+		}
+	} else {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_new: ERR 7301: "
+			"Fail to allocate vendor object.\n");
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return (p_vend);
+}
+
+/*
+ *  NAME            osm_vendor_delete
+ *
+ *  DESCRIPTION     Delete all the binds behind the vendor + free the vendor object
+ */
+
+void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
+{
+	cl_list_item_t *p_item;
+	cl_list_obj_t *p_obj;
+	osm_bind_handle_t bind_h;
+	osm_log_t *p_log;
+
+	OSM_LOG_ENTER((*pp_vend)->p_log);
+	p_log = (*pp_vend)->p_log;
+
+	/* go over the bind handles , unbind them and remove from list */
+	p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles));
+	while (p_item != cl_qlist_end(&((*pp_vend)->bind_handles))) {
+
+		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+		bind_h = (osm_bind_handle_t *) cl_qlist_obj(p_obj);
+		osm_log(p_log, OSM_LOG_DEBUG,
+			"osm_vendor_delete: unbinding bind_h:%p \n", bind_h);
+
+		__osm_vendor_internal_unbind(bind_h);
+
+		free(p_obj);
+		/*removing from list */
+		p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles));
+	}
+
+	if (NULL != ((*pp_vend)->p_transport_info)) {
+		free((*pp_vend)->p_transport_info);
+		(*pp_vend)->p_transport_info = NULL;
+	}
+
+	/* remove the packet randomizer object */
+	if ((*pp_vend)->run_randomizer == TRUE)
+		osm_pkt_randomizer_destroy(&((*pp_vend)->p_pkt_randomizer),
+					   p_log);
+
+	free(*pp_vend);
+	*pp_vend = NULL;
+
+	OSM_LOG_EXIT(p_log);
+}
+
+/*
+ *  NAME            osm_vendor_init
+ *
+ *  DESCRIPTION     Initialize the vendor object
+ */
+
+ib_api_status_t
+osm_vendor_init(IN osm_vendor_t * const p_vend,
+		IN osm_log_t * const p_log, IN const uint32_t timeout)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_vend->p_transport_info = NULL;
+	p_vend->p_log = p_log;
+	p_vend->resp_timeout = timeout;
+	p_vend->ttime_timeout = timeout * OSMV_TXN_TIMEOUT_FACTOR;
+
+	cl_qlist_init(&p_vend->bind_handles);
+
+	/* update the run_randomizer flag */
+	if (getenv("OSM_PKT_DROP_RATE") != NULL
+	    && atol(getenv("OSM_PKT_DROP_RATE")) != 0) {
+		/* if the OSM_PKT_DROP_RATE global variable is defined to a non-zero value -
+		   then the randomizer should be called.
+		   Need to create the packet randomizer object */
+		p_vend->run_randomizer = TRUE;
+		status =
+		    osm_pkt_randomizer_init(&(p_vend->p_pkt_randomizer), p_log);
+		if (status != IB_SUCCESS)
+			return status;
+	} else {
+		p_vend->run_randomizer = FALSE;
+		p_vend->p_pkt_randomizer = NULL;
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return (IB_SUCCESS);
+}
+
+/*
+ *  NAME            osm_vendor_bind
+ *
+ *  DESCRIPTION     Create a new bind object under the vendor object
+ */
+
+osm_bind_handle_t
+osm_vendor_bind(IN osm_vendor_t * const p_vend,
+		IN osm_bind_info_t * const p_bind_info,
+		IN osm_mad_pool_t * const p_mad_pool,
+		IN osm_vend_mad_recv_callback_t mad_recv_callback,
+		IN osm_vend_mad_send_err_callback_t send_err_callback,
+		IN void *context)
+{
+	osmv_bind_obj_t *p_bo;
+	ib_api_status_t status;
+	char hca_id[32];
+	cl_status_t cl_st;
+	cl_list_obj_t *p_obj;
+	uint8_t hca_index;
+
+	if (NULL == p_vend || NULL == p_bind_info || NULL == p_mad_pool
+	    || NULL == mad_recv_callback || NULL == send_err_callback) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7302: "
+			"NULL parameter passed in: p_vend=%p p_bind_info=%p p_mad_pool=%p recv_cb=%p send_err_cb=%p\n",
+			p_vend, p_bind_info, p_mad_pool, mad_recv_callback,
+			send_err_callback);
+
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	p_bo = malloc(sizeof(osmv_bind_obj_t));
+	if (NULL == p_bo) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7303: could not allocate the bind object\n");
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	memset(p_bo, 0, sizeof(osmv_bind_obj_t));
+	p_bo->p_vendor = p_vend;
+	p_bo->recv_cb = mad_recv_callback;
+	p_bo->send_err_cb = send_err_callback;
+	p_bo->cb_context = context;
+	p_bo->p_osm_pool = p_mad_pool;
+
+	/* obtain the hca name and port num from the guid */
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"osm_vendor_bind: "
+		"Finding CA and Port that owns port guid 0x%" PRIx64 ".\n",
+		cl_ntoh64(p_bind_info->port_guid));
+
+	status = osm_vendor_get_guid_ca_and_port(p_bo->p_vendor,
+						 p_bind_info->port_guid,
+						 &(p_bo->hca_hndl),
+						 hca_id,
+						 &hca_index, &(p_bo->port_num));
+	if (status != IB_SUCCESS) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7304: "
+			"Fail to find port number of port guid:0x%016" PRIx64
+			"\n", p_bind_info->port_guid);
+		free(p_bo);
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	/* Initialize the magic_ptr to the pointer of the p_bo info.
+	   This will be used to signal when the object is being destroyed, so no
+	   real action will be done then. */
+	p_bo->magic_ptr = p_bo;
+
+	p_bo->is_closing = FALSE;
+
+	cl_spinlock_construct(&(p_bo->lock));
+	cl_st = cl_spinlock_init(&(p_bo->lock));
+	if (cl_st != CL_SUCCESS) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7305: "
+			"could not initialize the spinlock ...\n");
+		free(p_bo);
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"osm_vendor_bind: osmv_txnmgr_init ... \n");
+	if (osmv_txnmgr_init(&p_bo->txn_mgr, p_vend->p_log, &(p_bo->lock)) !=
+	    IB_SUCCESS) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7306: "
+			"osmv_txnmgr_init failed \n");
+		cl_spinlock_destroy(&p_bo->lock);
+		free(p_bo);
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	/* Do the real job! (Transport-dependent) */
+	if (IB_SUCCESS !=
+	    osmv_transport_init(p_bind_info, hca_id, hca_index, p_bo)) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7307: "
+			"osmv_transport_init failed \n");
+		osmv_txnmgr_done((osm_bind_handle_t) p_bo);
+		cl_spinlock_destroy(&p_bo->lock);
+		free(p_bo);
+		return OSM_BIND_INVALID_HANDLE;
+	}
+
+	/* insert bind handle into db */
+	p_obj = malloc(sizeof(cl_list_obj_t));
+	if (NULL == p_obj) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osm_vendor_bind: ERR 7308: "
+			"osm_vendor_bind: could not allocate the list object\n");
+
+		osmv_transport_done(p_bo->p_transp_mgr);
+		osmv_txnmgr_done((osm_bind_handle_t) p_bo);
+		cl_spinlock_destroy(&p_bo->lock);
+		free(p_bo);
+		return OSM_BIND_INVALID_HANDLE;
+	}
+	memset(p_obj, 0, sizeof(cl_list_obj_t));
+	cl_qlist_set_obj(p_obj, p_bo);
+
+	cl_qlist_insert_head(&p_vend->bind_handles, &p_obj->list_item);
+
+	return (osm_bind_handle_t) p_bo;
+}
+
+/*
+ *  NAME            osm_vendor_unbind
+ *
+ *  DESCRIPTION     Destroy the bind object and remove it from the vendor's list
+ */
+
+void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+	cl_list_obj_t *p_obj = NULL;
+	cl_list_item_t *p_item, *p_item_tmp;
+	cl_qlist_t *const p_bh_list =
+	    (cl_qlist_t * const)&p_bo->p_vendor->bind_handles;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* go over all the items in the list and remove the specific item */
+	p_item = cl_qlist_head(p_bh_list);
+	while (p_item != cl_qlist_end(p_bh_list)) {
+		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+		if (cl_qlist_obj(p_obj) == h_bind) {
+			break;
+		}
+		p_item_tmp = cl_qlist_next(p_item);
+		p_item = p_item_tmp;
+	}
+
+	CL_ASSERT(p_item != cl_qlist_end(p_bh_list));
+
+	cl_qlist_remove_item(p_bh_list, p_item);
+	if (p_obj)
+		free(p_obj);
+
+	if (h_bind != 0) {
+		__osm_vendor_internal_unbind(h_bind);
+	}
+
+	OSM_LOG_EXIT(p_log);
+}
+
+/*
+ *  NAME            osm_vendor_get
+ *
+ *  DESCRIPTION     Allocate the space for a new MAD
+ */
+
+ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
+			 IN const uint32_t mad_size,
+			 IN osm_vend_wrap_t * const p_vw)
+{
+	ib_mad_t *p_mad;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	uint32_t act_mad_size;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vw);
+
+	if (mad_size < MAD_BLOCK_SIZE) {
+		/* Stupid, but the applications want that! */
+		act_mad_size = MAD_BLOCK_SIZE;
+	} else {
+		act_mad_size = mad_size;
+	}
+
+	/* allocate it */
+	p_mad = (ib_mad_t *) malloc(act_mad_size);
+	if (p_mad == NULL) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get: ERR 7309: "
+			"Error Obtaining MAD buffer.\n");
+		goto Exit;
+	}
+
+	memset(p_mad, 0, act_mad_size);
+
+	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
+		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+			"osm_vendor_get: "
+			"Allocated MAD %p, size = %u.\n", p_mad, act_mad_size);
+	}
+	p_vw->p_mad = p_mad;
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (p_mad);
+}
+
+/*
+ *  NAME            osm_vendor_send
+ *
+ *  DESCRIPTION     Send a MAD buffer (RMPP or simple send).
+ *
+ *                  Semantics:
+ *                   (1) The RMPP send completes when every segment
+ *                       is acknowledged (synchronous)
+ *                   (2) The simple send completes when the send completion
+ *                       is received (asynchronous)
+ */
+
+ib_api_status_t
+osm_vendor_send(IN osm_bind_handle_t h_bind,
+		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
+{
+	ib_api_status_t ret = IB_SUCCESS;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	boolean_t is_rmpp = FALSE, is_rmpp_ds = FALSE;
+	osmv_txn_ctx_t *p_txn = NULL;
+	ib_mad_t *p_mad;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+	osm_mad_pool_t *p_mad_pool = p_bo->p_osm_pool;
+	OSM_LOG_ENTER(p_log);
+
+	if (NULL == h_bind || NULL == p_madw ||
+	    NULL == (p_mad = osm_madw_get_mad_ptr(p_madw)) ||
+	    NULL == osm_madw_get_mad_addr_ptr(p_madw)) {
+
+		return IB_INVALID_PARAMETER;
+	}
+
+	is_rmpp = (p_madw->mad_size > MAD_BLOCK_SIZE
+		   || osmv_mad_is_rmpp(p_mad));
+	/* is this rmpp double sided? This means we expect a response that can be
+	   an rmpp or not */
+	is_rmpp_ds = (TRUE == is_rmpp && TRUE == resp_expected);
+
+	/* Make our operations with the send context atomic */
+	osmv_txn_lock(p_bo);
+
+	if (TRUE == p_bo->is_closing) {
+
+		osm_log(p_log, OSM_LOG_ERROR,
+			"osm_vendor_send: ERR 7310: "
+			"The handle %p is being unbound, cannot send.\n",
+			h_bind);
+		ret = IB_INTERRUPTED;
+		/* When closing p_bo could be detroyed or is going to , thus could not refer to it */
+		goto send_done;
+	}
+
+	if (TRUE == resp_expected || TRUE == is_rmpp) {
+
+		/* We must run under a transaction framework.
+		 * Get the transaction object (old or new) */
+		ret = __osmv_get_send_txn(h_bind, p_madw, is_rmpp,
+					  resp_expected, &p_txn);
+		if (IB_SUCCESS != ret) {
+			goto send_done;
+		}
+	}
+
+	if (TRUE == is_rmpp) {
+		/* Do the job - RMPP!
+		 * The call returns as all the packets are ACK'ed/upon error
+		 * The txn lock will be released each time the function sleeps
+		 * and re-acquired when it wakes up
+		 */
+		ret = osmv_rmpp_send_madw(h_bind, p_madw, p_txn, is_rmpp_ds);
+	} else {
+
+		/* Do the job - single MAD!
+		 * The call returns as soon as the MAD is put on the wire
+		 */
+		ret = osmv_simple_send_madw(h_bind, p_madw, p_txn, FALSE);
+	}
+
+	if (IB_SUCCESS == ret) {
+
+		if ((TRUE == is_rmpp) && (FALSE == is_rmpp_ds)) {
+			/* For double-sided sends, the txn continues to live */
+			osmv_txn_done(h_bind, osmv_txn_get_key(p_txn),
+				      FALSE /*not in callback */ );
+		}
+
+		if (FALSE == resp_expected) {
+			osm_mad_pool_put(p_mad_pool, p_madw);
+		}
+	} else if (IB_INTERRUPTED != ret) {
+		if (NULL != p_txn) {
+			osmv_txn_done(h_bind, osmv_txn_get_key(p_txn),
+				      FALSE /*not in callback */ );
+		}
+
+		osm_log(p_log, OSM_LOG_ERROR,
+			"osm_vendor_send: ERR 7311: failed to send MADW %p\n",
+			p_madw);
+
+		if (TRUE == resp_expected) {
+			/* Change the status on the p_madw */
+			p_madw->status = ret;
+			/* Only the requester expects the error callback */
+			p_bo->send_err_cb(p_bo->cb_context, p_madw);
+		} else {
+			/* put back the mad - it is useless ... */
+			osm_mad_pool_put(p_mad_pool, p_madw);
+		}
+	} else {		/* the transaction was aborted due to p_bo exit */
+
+		osm_mad_pool_put(p_mad_pool, p_madw);
+		goto aborted;
+	}
+send_done:
+
+	osmv_txn_unlock(p_bo);
+aborted:
+	OSM_LOG_EXIT(p_log);
+	return ret;
+}
+
+/*
+ *  NAME            osm_vendor_put
+ *
+ *  DESCRIPTION     Free the MAD's memory
+ */
+
+void
+osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
+{
+
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+
+	if (p_bo->is_closing != TRUE) {
+		OSM_LOG_ENTER(p_vend->p_log);
+
+		CL_ASSERT(p_vw);
+		CL_ASSERT(p_vw->p_mad);
+
+		if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
+			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+				"osm_vendor_put: " "Retiring MAD %p.\n",
+				p_vw->p_mad);
+		}
+
+		free(p_vw->p_mad);
+		p_vw->p_mad = NULL;
+
+		OSM_LOG_EXIT(p_vend->p_log);
+	}
+}
+
+/*
+ *  NAME            osm_vendor_local_lid_change
+ *
+ *  DESCRIPTION     Notifies the vendor transport layer that the local address
+ *                  has changed.  This allows the vendor layer to perform
+ *                  housekeeping functions such as address vector updates.
+ */
+
+ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
+{
+	osm_vendor_t const *p_vend = ((osmv_bind_obj_t *) h_bind)->p_vendor;
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"osm_vendor_local_lid_change: " "Change of LID.\n");
+
+	OSM_LOG_EXIT(p_vend->p_log);
+
+	return (IB_SUCCESS);
+
+}
+
+/*
+ *  NAME            osm_vendor_set_sm
+ *
+ *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit
+ *                  according to the value given (TRUE or FALSE).
+ */
+#if !(defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_SIM) || defined(OSM_VENDOR_INTF_TS))
+void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	VAPI_ret_t status;
+	VAPI_hca_attr_t attr_mod;
+	VAPI_hca_attr_mask_t attr_mask;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	memset(&attr_mod, 0, sizeof(attr_mod));
+	memset(&attr_mask, 0, sizeof(attr_mask));
+
+	attr_mod.is_sm = is_sm_val;
+	attr_mask = HCA_ATTR_IS_SM;
+
+	status =
+	    VAPI_modify_hca_attr(p_bo->hca_hndl, p_bo->port_num, &attr_mod,
+				 &attr_mask);
+	if (status != VAPI_OK) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_set_sm: ERR 7312: "
+			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
+			is_sm_val, status);
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+#endif
+
+/*
+ *  NAME            __osm_vendor_internal_unbind
+ *
+ *  DESCRIPTION     Destroying a bind:
+ *                    (1) Wait for the completion of the sends in flight
+ *                    (2) Destroy the associated data structures
+ */
+
+static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* "notifying" all that from now on no new sends can be done */
+	p_bo->txn_mgr.p_event_wheel->closing = TRUE;
+
+	osmv_txn_lock(p_bo);
+
+	/*
+	   the is_closing is set under lock we we know we only need to
+	   check for it after obtaining the lock
+	 */
+	p_bo->is_closing = TRUE;
+
+	/* notifying all sleeping rmpp sends to exit */
+	osmv_txn_abort_rmpp_txns(h_bind);
+
+	/* unlock the bo to allow for any residual mads to be dispatched */
+	osmv_txn_unlock(p_bo);
+	osm_log(p_log, OSM_LOG_DEBUG,
+		"__osm_vendor_internal_unbind: destroying transport mgr.. \n");
+	/* wait for the receiver thread to exit */
+	osmv_transport_done(h_bind);
+
+	/* lock to avoid any collissions while we cleanup the structs */
+	osmv_txn_lock(p_bo);
+	osm_log(p_log, OSM_LOG_DEBUG,
+		"__osm_vendor_internal_unbind: destroying txn mgr.. \n");
+	osmv_txnmgr_done(h_bind);
+	osm_log(p_log, OSM_LOG_DEBUG,
+		"__osm_vendor_internal_unbind: destroying bind lock.. \n");
+	osmv_txn_unlock(p_bo);
+
+	/*
+	   we intentionally let the p_bo and its lock leak -
+	   as we did not implement a way to track active bind handles provided to
+	   the client - and the client might use them
+
+	   cl_spinlock_destroy(&p_bo->lock);
+	   free(p_bo);
+	 */
+
+	OSM_LOG_EXIT(p_log);
+}
+
+/*
+ *  NAME            __osmv_get_send_txn
+ *
+ *  DESCRIPTION     Return a transaction object that corresponds to this MAD.
+ *                  Optionally, create it, if the new request (query) is sent or received.
+ */
+
+static ib_api_status_t
+__osmv_get_send_txn(IN osm_bind_handle_t h_bind,
+		    IN osm_madw_t * const p_madw,
+		    IN boolean_t is_rmpp,
+		    IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	ib_api_status_t ret;
+	uint64_t tid, key;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw);
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+	CL_ASSERT(NULL != pp_txn);
+
+	key = tid = cl_ntoh64(p_mad->trans_id);
+	if (TRUE == resp_expected) {
+		/* Create a unique identifier at the requester side */
+		key = osmv_txn_uniq_key(tid);
+	}
+
+	/* We must run under a transaction framework */
+	ret = osmv_txn_lookup(h_bind, key, pp_txn);
+	if (IB_NOT_FOUND == ret) {
+		/* Generally, we start a new transaction */
+		ret = osmv_txn_init(h_bind, tid, key, pp_txn);
+		if (IB_SUCCESS != ret) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_get_send_txn: ERR 7313: "
+				"The transaction id=0x%llX failed to init.\n",
+				tid);
+			goto get_send_txn_done;
+		}
+	} else {
+		CL_ASSERT(NULL != *pp_txn);
+		/* The transaction context exists.
+		 * This is legal only if I am going to return an
+		 * (RMPP?) reply to an RMPP request sent by the other part
+		 * (double-sided RMPP transfer)
+		 */
+		if (FALSE == is_rmpp
+		    || FALSE == osmv_txn_is_rmpp_init_by_peer(*pp_txn)) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_get_send_txn: ERR 7314: "
+				"The transaction id=0x%llX is not unique. Send failed.\n",
+				tid);
+
+			ret = IB_INVALID_SETTING;
+			goto get_send_txn_done;
+		}
+
+		if (TRUE == resp_expected) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_get_send_txn: ERR 7315: "
+				"The transaction id=%llX can't expect a response. Send failed.\n",
+				tid);
+
+			ret = IB_INVALID_PARAMETER;
+			goto get_send_txn_done;
+		}
+	}
+
+	if (TRUE == is_rmpp) {
+		ret = osmv_txn_init_rmpp_sender(h_bind, *pp_txn, p_madw);
+		if (IB_SUCCESS != ret) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_get_send_txn: ERR 7316: "
+				"The transaction id=%llX failed to init the rmpp mad. Send failed.\n",
+				tid);
+			osmv_txn_done(h_bind, tid, FALSE);
+			goto get_send_txn_done;
+		}
+	}
+
+	/* Save a reference to the MAD in the txn context
+	 * We'll need to match it in two cases:
+	 *  (1) When the response is returned, if I am the requester
+	 *  (2) In RMPP retransmissions
+	 */
+	osmv_txn_set_madw(*pp_txn, p_madw);
+
+get_send_txn_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+
+	return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
+{
+
+}
diff --git a/libvendor/osm_vendor_mlx_dispatcher.c b/libvendor/osm_vendor_mlx_dispatcher.c
new file mode 100644
index 0000000..d476382
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_dispatcher.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <vendor/osm_vendor_mlx.h>
+#include <vendor/osm_vendor_mlx_defs.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_sender.h>
+#include <vendor/osm_pkt_randomizer.h>
+
+typedef enum _osmv_disp_route {
+
+	OSMV_ROUTE_DROP,
+	OSMV_ROUTE_SIMPLE,
+	OSMV_ROUTE_RMPP,
+
+} osmv_disp_route_t;
+
+/**
+ *   FORWARD REFERENCES TO PRIVATE FUNCTIONS
+ */
+
+static osmv_disp_route_t
+__osmv_dispatch_route(IN osm_bind_handle_t h_bind,
+		      IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn);
+
+static void
+__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
+			   IN const ib_mad_t * p_mad,
+			   IN osmv_txn_ctx_t * p_txn,
+			   IN const osm_mad_addr_t * p_mad_addr);
+
+static void
+__osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr);
+
+static void
+__osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr);
+
+static ib_api_status_t
+__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr);
+
+static ib_api_status_t
+__osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind,
+			   IN osmv_txn_ctx_t * p_txn,
+			   IN const ib_mad_t * p_mad);
+static void
+__osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_req_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr);
+
+/*
+ * NAME
+ *   osmv_dispatch_mad
+ *
+ * DESCRIPTION
+ *   Lower-level MAD dispatcher.
+ *   Implements a switch between the following MAD consumers:
+ *   (1) Non-RMPP consumer (DATA)
+ *   (2) RMPP receiver     (DATA/ABORT/STOP)
+ *   (3) RMPP sender       (ACK/ABORT/STOP)
+ *
+ * PARAMETERS
+ *   h_bind                The bind handle
+ *   p_mad_buf             The 256 byte buffer of individual MAD
+ *   p_mad_addr            The MAD originator's address
+ */
+
+ib_api_status_t
+osmv_dispatch_mad(IN osm_bind_handle_t h_bind,
+		  IN const void *p_mad_buf,
+		  IN const osm_mad_addr_t * p_mad_addr)
+{
+	ib_api_status_t ret = IB_SUCCESS;
+	const ib_mad_t *p_mad = (ib_mad_t *) p_mad_buf;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osmv_txn_ctx_t *p_txn = NULL;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	CL_ASSERT(NULL != h_bind && NULL != p_mad && NULL != p_mad_addr);
+
+	osmv_txn_lock(p_bo);
+
+	if (TRUE == p_bo->is_closing) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"The bind handle %p is being closed. "
+			"The MAD will not be dispatched.\n", p_bo);
+
+		ret = IB_INTERRUPTED;
+		goto dispatch_mad_done;
+	}
+
+	/*
+	   Add call for packet drop randomizer.
+	   This is a testing feature. If run_randomizer flag is set to TRUE,
+	   the randomizer will be called, and randomally will drop
+	   a packet. This is used for simulating unstable fabric.
+	 */
+	if (p_bo->p_vendor->run_randomizer == TRUE) {
+		/* Try the randomizer */
+		if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
+						p_bo->p_vendor->
+						p_pkt_randomizer,
+						p_mad) == TRUE) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"The MAD will not be dispatched.\n");
+			goto dispatch_mad_done;
+		}
+	}
+
+	switch (__osmv_dispatch_route(h_bind, p_mad, &p_txn)) {
+
+	case OSMV_ROUTE_DROP:
+		break;		/* Do nothing */
+
+	case OSMV_ROUTE_SIMPLE:
+		__osmv_dispatch_simple_mad(h_bind, p_mad, p_txn, p_mad_addr);
+		break;
+
+	case OSMV_ROUTE_RMPP:
+		__osmv_dispatch_rmpp_mad(h_bind, p_mad, p_txn, p_mad_addr);
+		break;
+
+	default:
+		CL_ASSERT(FALSE);
+	}
+
+dispatch_mad_done:
+	osmv_txn_unlock(p_bo);
+
+	OSM_LOG_EXIT(p_log);
+	return ret;
+}
+
+/*
+ *  NAME            __osmv_dispatch_route()
+ *
+ *  DESCRIPTION     Decide which way to handle the received MAD: simple txn/RMPP/drop
+ */
+
+static osmv_disp_route_t
+__osmv_dispatch_route(IN osm_bind_handle_t h_bind,
+		      IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	ib_api_status_t ret;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	boolean_t is_resp = osmv_mad_is_response(p_mad);
+	boolean_t is_txn;
+	uint64_t key = cl_ntoh64(p_mad->trans_id);
+
+	CL_ASSERT(NULL != pp_txn);
+
+	ret = osmv_txn_lookup(h_bind, key, pp_txn);
+	is_txn = (IB_SUCCESS == ret);
+
+	if (FALSE == is_txn && TRUE == is_resp) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Received a response to a non-started/aged-out transaction (tid=0x%llX). "
+			"Dropping the MAD.\n", key);
+		return OSMV_ROUTE_DROP;
+	}
+
+	if (TRUE == osmv_mad_is_rmpp(p_mad)) {
+		/* An RMPP transaction. The filtering is more delicate there */
+		return OSMV_ROUTE_RMPP;
+	}
+
+	if (TRUE == is_txn && FALSE == is_resp) {
+		/* Does this MAD try to start a transaction with duplicate tid? */
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Duplicate TID 0x%llX received (not a response). "
+			"Dropping the MAD.\n", key);
+
+		return OSMV_ROUTE_DROP;
+	}
+
+	return OSMV_ROUTE_SIMPLE;
+}
+
+/*
+ *  NAME            __osmv_dispatch_simple_mad()
+ *
+ *  DESCRIPTION     Handle a MAD that is part of non-RMPP transfer
+ */
+
+static void
+__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
+			   IN const ib_mad_t * p_mad,
+			   IN osmv_txn_ctx_t * p_txn,
+			   IN const osm_mad_addr_t * p_mad_addr)
+{
+	osm_madw_t *p_madw;
+	ib_mad_t *p_mad_buf;
+	osm_madw_t *p_req_madw = NULL;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	/* Build the MAD wrapper to be returned to the user.
+	 * The actual storage for the MAD is allocated there.
+	 */
+	p_madw =
+	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, MAD_BLOCK_SIZE,
+			     p_mad_addr);
+
+	if (NULL == p_madw) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_simple_mad: ERR 6501: "
+			"Out Of Memory - could not allocate a buffer of size %d\n",
+			MAD_BLOCK_SIZE);
+
+		goto dispatch_simple_mad_done;
+	}
+
+	p_mad_buf = osm_madw_get_mad_ptr(p_madw);
+	/* Copy the payload to the MAD buffer */
+	memcpy((void *)p_mad_buf, (void *)p_mad, MAD_BLOCK_SIZE);
+
+	if (NULL != p_txn) {
+		/* This is a RESPONSE MAD. Pair it with the REQUEST MAD, pass upstream */
+		p_req_madw = p_txn->p_madw;
+		CL_ASSERT(NULL != p_req_madw);
+
+		p_mad_buf->trans_id = cl_hton64(osmv_txn_get_tid(p_txn));
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Restoring the original TID to 0x%llX\n",
+			cl_ntoh64(p_mad_buf->trans_id));
+
+		/* Reply matched, transaction complete */
+		osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
+	} else {
+		/* This is a REQUEST  MAD. Don't create a context, pass upstream */
+	}
+
+	/* Do the job ! */
+	p_bo->recv_cb(p_madw, p_bo->cb_context, p_req_madw);
+
+dispatch_simple_mad_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+/*
+ *  NAME            __osmv_dispatch_rmpp_mad()
+ *
+ *  DESCRIPTION     Handle a MAD that is part of RMPP transfer
+ */
+
+static void
+__osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint64_t key = cl_ntoh64(p_mad->trans_id);
+	boolean_t is_init_by_peer = FALSE;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_madw_t *p_madw;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	if (NULL == p_txn) {
+		if (FALSE == osmv_rmpp_is_data(p_mad)
+		    || FALSE == osmv_rmpp_is_first(p_mad)) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"The MAD does not match any transaction "
+				"and does not start a sender-initiated RMPP transfer.\n");
+			goto dispatch_rmpp_mad_done;
+		}
+
+		/* IB Spec 13.6.2.2. This is a Sender Initiated Transfer.
+		   My peer is the requester and RMPP Sender. I am the RMPP Receiver.
+		 */
+		status = osmv_txn_init(h_bind, /*tid==key */ key, key, &p_txn);
+		if (IB_SUCCESS != status) {
+			goto dispatch_rmpp_mad_done;
+		}
+
+		is_init_by_peer = TRUE;
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"A new sender-initiated transfer (TID=0x%llX) started\n",
+			key);
+	}
+
+	if (OSMV_TXN_RMPP_NONE == osmv_txn_get_rmpp_state(p_txn)) {
+		/* Case 1: Fall through from above.
+		 * Case 2: When the transaction was initiated by me
+		 *         (a single request MAD), there was an uncertainty
+		 *         whether the reply will be RMPP. Now it's resolved,
+		 *         since the reply is RMPP!
+		 */
+		status =
+		    osmv_txn_init_rmpp_receiver(h_bind, p_txn, is_init_by_peer);
+		if (IB_SUCCESS != status) {
+			goto dispatch_rmpp_mad_done;
+		}
+	}
+
+	switch (osmv_txn_get_rmpp_state(p_txn)) {
+
+	case OSMV_TXN_RMPP_RECEIVER:
+		status =
+		    __osmv_dispatch_rmpp_rcv(h_bind, p_mad, p_txn, p_mad_addr);
+		if (IB_SUCCESS != status) {
+			if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) {
+				/* This is a requester, still waiting for the reply. Apply the callback */
+				/* update the status of the p_madw */
+				p_madw = osmv_txn_get_madw(p_txn);
+				p_madw->status = status;
+				p_bo->send_err_cb(p_bo->cb_context, p_madw);
+			}
+
+			/* ABORT/STOP/LOCAL ERROR */
+			osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
+		}
+		break;
+
+	case OSMV_TXN_RMPP_SENDER:
+		__osmv_dispatch_rmpp_snd(h_bind, p_mad, p_txn, p_mad_addr);
+		/* If an error happens here, it's the sender thread to cleanup the txn */
+		break;
+
+	default:
+		CL_ASSERT(FALSE);
+	}
+
+dispatch_rmpp_mad_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+/*
+ *  NAME            __osmv_dispatch_rmpp_snd()
+ *
+ *  DESCRIPTION     MAD handling by an RMPP sender (ACK/ABORT/STOP)
+ */
+
+static void
+__osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr)
+{
+	osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
+
+	uint32_t old_wl = p_send_ctx->window_last;
+	uint32_t total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
+	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
+	uint32_t new_wl = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->paylen_newwin);
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_rmpp_snd: ERR 6502: "
+			"The remote side sent an ABORT/STOP indication.\n");
+		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
+		goto dispatch_rmpp_snd_done;
+	}
+
+	if (FALSE == osmv_rmpp_is_ack(p_mad)) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Not supposed to receive DATA packets --> dropping the MAD\n");
+		goto dispatch_rmpp_snd_done;
+	}
+
+	/* Continue processing the ACK */
+	if (seg_num > old_wl) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_rmpp_snd: ERR 6503: "
+			"ACK received for a non-sent segment %d\n", seg_num);
+
+		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
+				   IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_S2B);
+
+		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
+		goto dispatch_rmpp_snd_done;
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"__osmv_dispatch_rmpp_snd: "
+		"New WL = %u Old WL = %u Total Segs = %u\n",
+		new_wl, old_wl, total_segs);
+
+	if (new_wl < old_wl) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_rmpp_snd: ERR 6508: "
+			"The receiver requests a smaller WL (%d) than before (%d)\n",
+			new_wl, old_wl);
+
+		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
+				   IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_W2S);
+
+		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
+		goto dispatch_rmpp_snd_done;
+	}
+
+	/* Update the sender's window, and optionally wake up the sender thread
+	 * Note! A single ACK can acknowledge a whole range of segments: [WF..SEG_NUM]
+	 */
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"ACK for seg_num #%d accepted.\n", seg_num);
+
+	if (seg_num == old_wl) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"The send window [%d:%d] is totally acknowledged.\n",
+			p_send_ctx->window_first, old_wl);
+
+		p_send_ctx->window_first = seg_num + 1;
+		p_send_ctx->window_last =
+		    (new_wl < total_segs) ? new_wl : total_segs;
+
+		/* Remove the response timeout event for the window */
+		osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));
+
+		/* Wake up the sending thread */
+		cl_event_signal(&p_send_ctx->event);
+	}
+
+dispatch_rmpp_snd_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+/*
+ *  NAME           __osmv_dispatch_rmpp_rcv()
+ *
+ *  DESCRIPTION    MAD handling by an RMPP receiver (DATA/ABORT/STOP)
+ */
+
+static ib_api_status_t
+__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	boolean_t is_last1 = FALSE, is_last2 = FALSE;
+	osm_madw_t *p_new_madw = NULL, *p_req_madw = NULL;
+	ib_mad_t *p_mad_buf;
+	uint32_t size = 0;
+	uint64_t key = osmv_txn_get_key(p_txn);
+	uint64_t tid = osmv_txn_get_tid(p_txn);
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	if (TRUE == osmv_rmpp_is_ack(p_mad)) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Not supposed to receive ACK's --> dropping the MAD\n");
+
+		goto dispatch_rmpp_rcv_done;
+	}
+
+	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"__osmv_dispatch_rmpp_rcv: ERR 6504: "
+			"The Remote Side stopped sending\n");
+
+		status = IB_REMOTE_ERROR;
+		goto dispatch_rmpp_rcv_done;
+	}
+
+	status = __osmv_dispatch_accept_seg(h_bind, p_txn, p_mad);
+	switch (status) {
+
+	case IB_SUCCESS:
+
+		/* Check wheter this is the legal last MAD */
+		/* Criteria #1: the received MAD is marked last */
+		is_last1 = osmv_rmpp_is_last(p_mad);
+
+		/* Criteria #2: the total accumulated length hits the advertised one */
+		is_last2 = is_last1;
+
+		size = osmv_rmpp_recv_ctx_get_byte_num_from_first(p_recv_ctx);
+		if (size > 0) {
+			is_last2 =
+			    (osmv_rmpp_recv_ctx_get_cur_byte_num(p_recv_ctx) >=
+			     size);
+		}
+
+		if (is_last1 != is_last2) {
+
+			osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
+					   IB_RMPP_TYPE_ABORT,
+					   IB_RMPP_STATUS_BAD_LEN);
+
+			status = IB_ERROR;
+			goto dispatch_rmpp_rcv_done;
+		}
+
+		/* TBD Consider an optimization - sending an ACK
+		 * only for the last segment in the window
+		 */
+		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
+		break;
+
+	case IB_INSUFFICIENT_RESOURCES:
+		/* An out-of-order segment received. Send the ACK anyway */
+		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
+		status = IB_SUCCESS;
+		goto dispatch_rmpp_rcv_done;
+
+	case IB_INSUFFICIENT_MEMORY:
+		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
+				   IB_RMPP_TYPE_STOP, IB_RMPP_STATUS_RESX);
+		goto dispatch_rmpp_rcv_done;
+
+	default:
+		/* Illegal return code */
+		CL_ASSERT(FALSE);
+	}
+
+	if (TRUE != is_last1) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"RMPP MADW assembly continues, TID=0x%llX\n", tid);
+		goto dispatch_rmpp_rcv_done;
+	}
+
+	/* This is the last packet. */
+	if (0 == size) {
+		/* The total size was not advertised in the first packet */
+		size = osmv_rmpp_recv_ctx_get_byte_num_from_last(p_recv_ctx);
+	}
+
+	/*
+	   NOTE: the received mad might not be >= 256 bytes.
+	   some MADs might contain several SA records but still be
+	   less then a full MAD.
+	   We have to use RMPP to send them over since on a regular
+	   "simple" MAD there is no way to know how many records were sent
+	 */
+
+	/* Build the MAD wrapper to be returned to the user.
+	 * The actual storage for the MAD is allocated there.
+	 */
+	p_new_madw =
+	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, size, p_mad_addr);
+	if (NULL == p_new_madw) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_rmpp_rcv: ERR 6506: "
+			"Out Of Memory - could not allocate %d bytes for the MADW\n",
+			size);
+
+		status = IB_INSUFFICIENT_MEMORY;
+		goto dispatch_rmpp_rcv_done;
+	}
+
+	p_req_madw = osmv_txn_get_madw(p_txn);
+	p_mad_buf = osm_madw_get_mad_ptr(p_new_madw);
+	status = osmv_rmpp_recv_ctx_reassemble_arbt_mad(p_recv_ctx, size,
+							(uint8_t *) p_mad_buf);
+	if (IB_SUCCESS != status) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"__osmv_dispatch_rmpp_rcv: ERR 6507: "
+			"Internal error - could not reassemble the result MAD\n");
+		goto dispatch_rmpp_rcv_done;	/* What can happen here? */
+	}
+
+	/* The MAD is assembled, we are about to apply the callback.
+	 * Delete the transaction context, unless the transaction is double sided */
+	if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)
+	    || FALSE == osmv_mad_is_multi_resp(p_mad)) {
+
+		osmv_txn_done(h_bind, key, FALSE);
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"RMPP MADW %p assembly complete, TID=0x%llX\n", p_new_madw,
+		tid);
+
+	p_mad_buf->trans_id = cl_hton64(tid);
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"Restoring the original TID to 0x%llX\n",
+		cl_ntoh64(p_mad_buf->trans_id));
+
+	/* Finally, do the job! */
+	p_bo->recv_cb(p_new_madw, p_bo->cb_context, p_req_madw);
+
+dispatch_rmpp_rcv_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return status;
+}
+
+/*
+ *  NAME            __osmv_dispatch_accept_seg()
+ *
+ *  DESCRIPTION     Store a DATA segment at the RMPP receiver side,
+ *                  if one is received in order.
+ */
+
+static ib_api_status_t
+__osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind,
+			   IN osmv_txn_ctx_t * p_txn, IN const ib_mad_t * p_mad)
+{
+	ib_api_status_t ret = IB_SUCCESS;
+	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
+	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	uint64_t tid = osmv_txn_get_tid(p_txn);
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	if (seg_num != p_recv_ctx->expected_seg) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"TID 0x%llX: can't accept this segment (%d) - "
+			"this is a Go-Back-N implementation\n", tid, seg_num);
+		return IB_INSUFFICIENT_RESOURCES;
+	}
+
+	/* Store the packet's copy in the reassembly list.
+	 * Promote the expected segment counter.
+	 */
+	ret = osmv_rmpp_recv_ctx_store_mad_seg(p_recv_ctx, (uint8_t *) p_mad);
+	if (IB_SUCCESS != ret) {
+		return ret;
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"TID 0x%llX: segment %d accepted\n", tid, seg_num);
+	p_recv_ctx->expected_seg = seg_num + 1;
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return IB_SUCCESS;
+}
+
+/*
+ *  NAME              __osmv_dispatch_send_ack()
+ *
+ *  DESCRIPTION
+ *
+ *  ISSUES
+ *    Consider sending the ACK from an async thread
+ *    if problems with the receiving side processing arise.
+ */
+
+static void
+__osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind,
+			 IN const ib_mad_t * p_req_mad,
+			 IN osmv_txn_ctx_t * p_txn,
+			 IN const osm_mad_addr_t * p_mad_addr)
+{
+	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
+
+	/* ACK the segment # that was accepted */
+	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_req_mad)->seg_num);
+
+	/* NOTE! The receiver can publish the New Window Last (NWL) value
+	 * that is greater than the total number of segments to be sent.
+	 * It's the sender's responsibility to compute the correct number
+	 * of segments to send in the next burst.
+	 */
+	uint32_t nwl = p_recv_ctx->expected_seg + OSMV_RMPP_RECV_WIN - 1;
+
+	osmv_rmpp_send_ack(h_bind, p_req_mad, seg_num, nwl, p_mad_addr);
+}
diff --git a/libvendor/osm_vendor_mlx_hca.c b/libvendor/osm_vendor_mlx_hca.c
new file mode 100644
index 0000000..e98e272
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_hca.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS)
+#undef IN
+#undef OUT
+#include <vapi_types.h>
+#include <evapi.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/********************************************************************************
+ *
+ * Provide the functionality for selecting an HCA Port and Obtaining it's guid.
+ *
+ ********************************************************************************/
+
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+} osm_ca_info_t;
+
+/**********************************************************************
+ * Convert the given GID to GUID by copy of it's upper 8 bytes
+ **********************************************************************/
+ib_api_status_t
+__osm_vendor_gid_to_guid(IN u_int8_t * gid, OUT VAPI_gid_t * guid)
+{
+	memcpy(guid, gid + 8, 8);
+	return (IB_SUCCESS);
+}
+
+/**********************************************************************
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ ************************************************************************/
+static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
+						       const p_ca_info,
+						       IN const uint8_t index)
+{
+	return (&p_ca_info->p_attr->p_port_attr[index]);
+}
+
+/********************************************************************************
+ * get the CA names available on the system
+ * NOTE: user of this function needs to deallocate p_hca_ids after usage.
+ ********************************************************************************/
+static ib_api_status_t
+__osm_vendor_get_ca_ids(IN osm_vendor_t * const p_vend,
+			IN VAPI_hca_id_t ** const p_hca_ids,
+			IN uint32_t * const p_num_guids)
+{
+	ib_api_status_t status;
+	VAPI_ret_t vapi_res;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_hca_ids);
+	CL_ASSERT(p_num_guids);
+
+	/* first call is just to get the number */
+	vapi_res = EVAPI_list_hcas(0, p_num_guids, NULL);
+
+	/* fail ? */
+	if (vapi_res == VAPI_EINVAL_PARAM) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_vendor_get_ca_ids: ERR 3D08: : "
+			"Bad parameter in calling: EVAPI_list_hcas. (%d)\n",
+			vapi_res);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* NO HCA ? */
+	if (*p_num_guids == 0) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_vendor_get_ca_ids: ERR 3D09: "
+			"No available channel adapters.\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	/* allocate and really call - user of this function needs to deallocate it */
+	*p_hca_ids =
+	    (VAPI_hca_id_t *) malloc(*p_num_guids * sizeof(VAPI_hca_id_t));
+
+	/* now call it really */
+	vapi_res = EVAPI_list_hcas(*p_num_guids, p_num_guids, *p_hca_ids);
+
+	/* too many ? */
+	if (vapi_res == VAPI_EAGAIN) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_vendor_get_ca_ids: ERR 3D10: "
+			"More CA GUIDs than allocated array (%d).\n",
+			*p_num_guids);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* fail ? */
+	if (vapi_res != VAPI_OK) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_vendor_get_ca_ids: ERR 3D11: : "
+			"Bad parameter in calling: EVAPI_list_hcas.\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
+		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+			"__osm_vendor_get_ca_ids: "
+			"Detected %u local channel adapters.\n", *p_num_guids);
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ * Initialize an Info Struct for the Given HCA by its Id
+ **********************************************************************/
+static ib_api_status_t
+__osm_ca_info_init(IN osm_vendor_t * const p_vend,
+		   IN VAPI_hca_id_t ca_id, OUT osm_ca_info_t * const p_ca_info)
+{
+	ib_api_status_t status = IB_ERROR;
+	VAPI_ret_t vapi_res;
+	VAPI_hca_hndl_t hca_hndl;
+	VAPI_hca_vendor_t hca_vendor;
+	VAPI_hca_cap_t hca_cap;
+	VAPI_hca_port_t hca_port;
+	uint8_t port_num;
+	IB_gid_t *p_port_gid;
+	uint16_t maxNumGids;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	/* get the HCA handle */
+	vapi_res = EVAPI_get_hca_hndl(ca_id, &hca_hndl);
+	if (vapi_res != VAPI_OK) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_ca_info_init: ERR 3D05: "
+			"Fail to get HCA handle (%u).\n", vapi_res);
+		goto Exit;
+	}
+
+	if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
+		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+			"__osm_ca_info_init: " "Querying CA %s.\n", ca_id);
+	}
+
+	/* query and get the HCA capability */
+	vapi_res = VAPI_query_hca_cap(hca_hndl, &hca_vendor, &hca_cap);
+	if (vapi_res != VAPI_OK) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__osm_ca_info_init: ERR 3D06: "
+			"Fail to get HCA Capabilities (%u).\n", vapi_res);
+		goto Exit;
+	}
+
+	/* get the guid of the HCA */
+	memcpy(&(p_ca_info->guid), hca_cap.node_guid, 8 * sizeof(u_int8_t));
+	p_ca_info->attr_size = 1;
+	p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
+	memcpy(&(p_ca_info->p_attr->ca_guid), hca_cap.node_guid,
+	       8 * sizeof(u_int8_t));
+
+	/* now obtain the attributes of the ports */
+	p_ca_info->p_attr->num_ports = hca_cap.phys_port_num;
+	p_ca_info->p_attr->p_port_attr =
+	    (ib_port_attr_t *) malloc(hca_cap.phys_port_num *
+				      sizeof(ib_port_attr_t));
+
+	for (port_num = 0; port_num < p_ca_info->p_attr->num_ports; port_num++) {
+
+		/* query the port attributes */
+		vapi_res =
+		    VAPI_query_hca_port_prop(hca_hndl, port_num + 1, &hca_port);
+		if (vapi_res != VAPI_OK) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"__osm_ca_info_init: ERR 3D07: "
+				"Fail to get HCA Port Attributes (%d).\n",
+				vapi_res);
+			goto Exit;
+		}
+
+		/* first call to know the size of the gid table */
+		vapi_res =
+		    VAPI_query_hca_gid_tbl(hca_hndl, port_num + 1, 0,
+					   &maxNumGids, NULL);
+		p_port_gid = (IB_gid_t *) malloc(maxNumGids * sizeof(IB_gid_t));
+
+		vapi_res =
+		    VAPI_query_hca_gid_tbl(hca_hndl, port_num + 1, maxNumGids,
+					   &maxNumGids, p_port_gid);
+		if (vapi_res != VAPI_OK) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"__osm_ca_info_init: ERR 3D12: "
+				"Fail to get HCA Port GID (%d).\n", vapi_res);
+			goto Exit;
+		}
+
+		__osm_vendor_gid_to_guid(p_port_gid[0],
+					 (IB_gid_t *) & p_ca_info->p_attr->
+					 p_port_attr[port_num].port_guid);
+		p_ca_info->p_attr->p_port_attr[port_num].lid = hca_port.lid;
+		p_ca_info->p_attr->p_port_attr[port_num].link_state =
+		    hca_port.state;
+		p_ca_info->p_attr->p_port_attr[port_num].sm_lid =
+		    hca_port.sm_lid;
+
+		free(p_port_gid);
+	}
+
+	status = IB_SUCCESS;
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
+		    IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
+{
+	osm_ca_info_t *p_ca;
+	uint8_t i;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	for (i = 0; i < num_ca; i++) {
+		p_ca = &p_ca_info[i];
+
+		if (NULL != p_ca->p_attr) {
+			if (0 != p_ca->p_attr->num_ports) {
+				free(p_ca->p_attr->p_port_attr);
+			}
+
+			free(p_ca->p_attr);
+		}
+	}
+
+	free(p_ca_info);
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+/**********************************************************************
+ * Fill in the array of port_attr with all available ports on ALL the
+ * avilable CAs on this machine.
+ * ALSO -
+ * Update the vendor object list of ca_info structs
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+			     IN ib_port_attr_t * const p_attr_array,
+			     IN uint32_t * const p_num_ports)
+{
+	ib_api_status_t status;
+
+	uint32_t ca;
+	uint32_t ca_count = 0;
+	uint32_t port_count = 0;
+	uint8_t port_num;
+	uint32_t total_ports = 0;
+	VAPI_hca_id_t *p_ca_ids = NULL;
+	osm_ca_info_t *p_ca_infos = NULL;
+	uint32_t attr_array_sz = *p_num_ports;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend);
+
+	/* determine the number of CA's */
+	status = __osm_vendor_get_ca_ids(p_vend, &p_ca_ids, &ca_count);
+	if (status != IB_SUCCESS) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_all_port_attr: ERR 3D13: "
+			"Fail to get CA Ids.\n");
+		goto Exit;
+	}
+
+	/* Allocate an array big enough to hold the ca info objects */
+	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
+	if (p_ca_infos == NULL) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_all_port_attr: ERR 3D14: "
+			"Unable to allocate CA information array.\n");
+		goto Exit;
+	}
+
+	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
+
+	/*
+	 * For each CA, retrieve the CA info attributes
+	 */
+	for (ca = 0; ca < ca_count; ca++) {
+		status =
+		    __osm_ca_info_init(p_vend, p_ca_ids[ca], &p_ca_infos[ca]);
+		if (status != IB_SUCCESS) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"osm_vendor_get_all_port_attr: ERR 3D15: "
+				"Unable to initialize CA Info object (%s).\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		total_ports += p_ca_infos[ca].p_attr->num_ports;
+	}
+
+	*p_num_ports = total_ports;
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
+
+	/*
+	 * If the user supplied enough storage, return the port guids,
+	 * otherwise, return the appropriate error.
+	 */
+	if (attr_array_sz >= total_ports) {
+		for (ca = 0; ca < ca_count; ca++) {
+			uint32_t num_ports;
+
+			num_ports = p_ca_infos[ca].p_attr->num_ports;
+
+			for (port_num = 0; port_num < num_ports; port_num++) {
+				p_attr_array[port_count] =
+				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
+								     [ca],
+								     port_num);
+				port_count++;
+			}
+		}
+	} else {
+		status = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	if (p_ca_ids)
+		free(p_ca_ids);
+
+	if (p_ca_infos) {
+		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ * Given the vendor obj and a guid
+ * return the ca id and port number that have that guid
+ **********************************************************************/
+
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
+				IN ib_net64_t const guid,
+				OUT VAPI_hca_hndl_t * p_hca_hndl,
+				OUT VAPI_hca_id_t * p_hca_id,
+				OUT uint8_t * p_hca_idx,
+				OUT uint32_t * p_port_num)
+{
+
+	ib_api_status_t status;
+	VAPI_hca_id_t *p_ca_ids = NULL;
+	VAPI_ret_t vapi_res;
+	VAPI_hca_hndl_t hca_hndl;
+	VAPI_hca_vendor_t hca_vendor;
+	VAPI_hca_cap_t hca_cap;
+	IB_gid_t *p_port_gid = NULL;
+	uint16_t maxNumGids;
+	ib_net64_t port_guid;
+	uint32_t ca, portIdx, ca_count;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend);
+
+	/*
+	 * 1) Determine the number of CA's
+	 * 2) Allocate an array big enough to hold the ca info objects.
+	 * 3) Call again to retrieve the guids.
+	 */
+	status = __osm_vendor_get_ca_ids(p_vend, &p_ca_ids, &ca_count);
+	if (status != IB_SUCCESS) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_guid_ca_and_port: ERR 3D16: "
+			"Fail to get CA Ids.\n");
+		goto Exit;
+	}
+
+	/*
+	 * For each CA, retrieve the CA info attributes
+	 */
+	for (ca = 0; ca < ca_count; ca++) {
+		/* get the HCA handle */
+		vapi_res = EVAPI_get_hca_hndl(p_ca_ids[ca], &hca_hndl);
+		if (vapi_res != VAPI_OK) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"osm_vendor_get_guid_ca_and_port: ERR 3D17: "
+				"Fail to get HCA handle (%u).\n", vapi_res);
+			goto Exit;
+		}
+
+		/* get the CA attributes - to know how many ports it has: */
+		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
+			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+				"osm_vendor_get_guid_ca_and_port: "
+				"Querying CA %s.\n", p_ca_ids[ca]);
+		}
+
+		/* query and get the HCA capability */
+		vapi_res = VAPI_query_hca_cap(hca_hndl, &hca_vendor, &hca_cap);
+		if (vapi_res != VAPI_OK) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"osm_vendor_get_guid_ca_and_port: ERR 3D18: "
+				"Fail to get HCA Capabilities (%u).\n",
+				vapi_res);
+			goto Exit;
+		}
+
+		/* go over all ports - to obtail their guids */
+		for (portIdx = 0; portIdx < hca_cap.phys_port_num; portIdx++) {
+			vapi_res =
+			    VAPI_query_hca_gid_tbl(hca_hndl, portIdx + 1, 0,
+						   &maxNumGids, NULL);
+			p_port_gid =
+			    (IB_gid_t *) malloc(maxNumGids * sizeof(IB_gid_t));
+
+			/* get the port guid */
+			vapi_res =
+			    VAPI_query_hca_gid_tbl(hca_hndl, portIdx + 1,
+						   maxNumGids, &maxNumGids,
+						   p_port_gid);
+			if (vapi_res != VAPI_OK) {
+				osm_log(p_vend->p_log, OSM_LOG_ERROR,
+					"osm_vendor_get_guid_ca_and_port: ERR 3D19: "
+					"Fail to get HCA Port GID (%d).\n",
+					vapi_res);
+				goto Exit;
+			}
+
+			/* convert to SF style */
+			__osm_vendor_gid_to_guid(p_port_gid[0],
+						 (VAPI_gid_t *) & port_guid);
+
+			/* finally did we find it ? */
+			if (port_guid == guid) {
+				*p_hca_hndl = hca_hndl;
+				memcpy(p_hca_id, p_ca_ids[ca],
+				       sizeof(VAPI_hca_id_t));
+				*p_hca_idx = ca;
+				*p_port_num = portIdx + 1;
+				status = IB_SUCCESS;
+				goto Exit;
+			}
+
+			free(p_port_gid);
+			p_port_gid = NULL;
+		}		/*  ALL PORTS  */
+	}			/*  all HCAs */
+
+	osm_log(p_vend->p_log, OSM_LOG_ERROR,
+		"osm_vendor_get_guid_ca_and_port: ERR 3D20: "
+		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
+		cl_ntoh64(guid));
+	status = IB_INVALID_GUID;
+
+Exit:
+	if (p_ca_ids != NULL)
+		free(p_ca_ids);
+	if (p_port_gid != NULL)
+		free(p_port_gid);
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+#endif
diff --git a/libvendor/osm_vendor_mlx_hca_sim.c b/libvendor/osm_vendor_mlx_hca_sim.c
new file mode 100644
index 0000000..b6c0193
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_hca_sim.c
@@ -0,0 +1,864 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#if defined(OSM_VENDOR_INTF_SIM)
+#undef IN
+#undef OUT
+
+#include <unistd.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <fcntl.h>
+
+/******************************************************************************
+*
+* Provides the functionality for selecting an HCA Port and Obtaining it's guid.
+* This version is based on $IBMGTSIM_DIR/$IBMGTSIM_NODE file system.
+* This is a mimic of the OpenIB gen1 file system
+*
+******************************************************************************/
+
+char *__get_simulator_dir(void)
+{
+	static char *ibmgtSimDir = NULL;
+	static char *defaultIbmgtSimDir = "/tmp/ibmgtsim";
+	static char *ibmgtSimNode = NULL;
+	static char dirName[1024];
+
+	/* we use the first pointer to know if we were here */
+	if (ibmgtSimDir == NULL) {
+		/* obtain the simulator directory */
+		ibmgtSimDir = getenv("IBMGTSIM_DIR");
+		if (ibmgtSimDir == NULL) {
+			printf
+			    ("-W- Environment variable: IBMGTSIM_DIR does not exist.\n");
+			printf
+			    ("    Please create one used by the simulator.\n");
+			printf("    Using /tmp/ibmgtsim as default.\n");
+			ibmgtSimDir = defaultIbmgtSimDir;
+		}
+
+		/* obtain the node name we simulate */
+		ibmgtSimNode = getenv("IBMGTSIM_NODE");
+		if (ibmgtSimNode == NULL) {
+			printf
+			    ("-W- Environment variable: IBMGTSIM_NODE does not exist.\n");
+			printf
+			    ("    This variable should be the name of the node you wish to simulate.\n");
+			printf("    Using H-1 as default.\n");
+			ibmgtSimNode = "H-1";
+		}
+		sprintf(dirName, "%s/%s", ibmgtSimDir, ibmgtSimNode);
+	}
+
+	return dirName;
+}
+
+typedef struct _osm_ca_info {
+	ib_net64_t guid;
+	size_t attr_size;
+	ib_ca_attr_t *p_attr;
+
+} osm_ca_info_t;
+
+/**********************************************************************
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ ************************************************************************/
+static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
+						       const p_ca_info,
+						       IN const uint8_t index)
+{
+	return (&p_ca_info->p_attr->p_port_attr[index]);
+}
+
+/**********************************************************************
+ * Obtain the number of local CAs by scanning /proc/infiniband/core
+ **********************************************************************/
+int __hca_sim_get_num_cas(void)
+{
+	int num_cas = 0;
+	DIR *dp;
+	struct dirent *ep;
+
+	dp = opendir(__get_simulator_dir());
+
+	if (dp != NULL) {
+		while ((ep = readdir(dp))) {
+			/* CAs are directories with the format ca[1-9][0-9]* */
+			/*  if ((ep->d_type == DT_DIR) && !strncmp(ep->d_name, "ca", 2)) */
+			if (!strncmp(ep->d_name, "ca", 2)) {
+				num_cas++;
+			}
+		}
+		closedir(dp);
+	} else {
+		printf("__hca_sim_get_num_cas: ERROR : ail to open dir %s\n",
+		       __get_simulator_dir());
+		exit(1);
+	}
+
+	if (!num_cas)
+		exit(1);
+	return num_cas;
+}
+
+/*
+  name:          InfiniHost0
+  provider:      tavor
+  node GUID:     0002:c900:0120:3470
+  ports:         2
+  vendor ID:     0x2c9
+  device ID:     0x5a44
+  HW revision:   0xa1
+  FW revision:   0x300020080
+*/
+typedef struct _sim_ca_info {
+	char name[32];
+	char provider[32];
+	uint64_t guid;
+	uint8_t num_ports;
+	uint32_t vend_id;
+	uint16_t dev_id;
+	uint16_t rev_id;
+	uint64_t fw_rev;
+} sim_ca_info_t;
+
+/**********************************************************************
+ * Parse the CA Info file available in ibmgtSimDir/caN/info
+ **********************************************************************/
+static ib_api_status_t
+__parse_ca_info_file(IN osm_vendor_t * const p_vend,
+		     IN uint32_t idx, OUT sim_ca_info_t * sim_ca_info)
+{
+	ib_api_status_t status = IB_ERROR;
+	int info_file;
+	char file_name[256];
+	char file_buffer[3200];
+	char *p_ch;
+	int g1, g2, g3, g4;
+	int num_ports;
+	uint32_t len;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"__parse_ca_info_file: " "Querying CA %d.\n", idx);
+
+	/* we use the proc file system so we must be able to open the info file .. */
+	sprintf(file_name, "%s/ca%d/info", __get_simulator_dir(), idx);
+	info_file = open(file_name, O_RDONLY);
+	if (!info_file) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5105: "
+			"Fail to open HCA:%d info file:(%s).\n", idx,
+			file_name);
+		goto Exit;
+	}
+
+	/* read in the file */
+	len = read(info_file, file_buffer, 3200);
+	close(info_file);
+	file_buffer[len] = '\0';
+
+	/*
+	   parse the file ...
+	   name:          InfiniHost0
+	   provider:      tavor
+	   node GUID:     0002:c900:0120:3470
+	   ports:         2
+	   vendor ID:     0x2c9
+	   device ID:     0x5a44
+	   HW revision:   0xa1
+	   FW revision:   0x300020080
+	 */
+	if (!(p_ch = strstr(file_buffer, "name:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5106: "
+			"Fail to obtain HCA name. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "name: %s", sim_ca_info->name) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5107: "
+			"Fail to parse name in info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+
+	/* get the guid of the HCA */
+	if (!(p_ch = strstr(file_buffer, "node GUID:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5108: "
+			"Fail to obtain GUID in info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5109: "
+			"Fail to parse GUID in info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32
+	    | (uint64_t) g1 << 16 | (uint64_t) g3;
+
+	/* obtain number of ports */
+	if (!(p_ch = strstr(file_buffer, "ports:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5110: "
+			"Fail to obtain number of ports in info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "ports: %d", &num_ports) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_ca_info_file: ERR 5111: "
+			"Fail to parse num ports in info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_ca_info->num_ports = num_ports;
+
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"__parse_ca_info_file: "
+		"CA1 = name:%s guid:0x%016llx ports:%d\n",
+		sim_ca_info->name, sim_ca_info->guid, sim_ca_info->num_ports);
+
+	status = IB_SUCCESS;
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return status;
+}
+
+/*
+  state:         ACTIVE
+  LID:           0x0001
+  LMC:           0x0000
+  SM LID:        0x0001
+  SM SL:         0x0000
+  Capabilities:  IsSM
+  IsTrapSupported
+  IsAutomaticMigrationSupported
+  IsSLMappingSupported
+  IsLEDInfoSupported
+  IsSystemImageGUIDSupported
+  IsVendorClassSupported
+  IsCapabilityMaskNoticeSupported
+*/
+typedef struct _sim_port_info {
+	uint8_t state;
+	uint16_t lid;
+	uint8_t lmc;
+	uint16_t sm_lid;
+	uint8_t sm_sl;
+} sim_port_info_t;
+
+/**********************************************************************
+ * Parse the Port Info file available in ibmgtSimDir/caN/portM/info
+ * Port num is 1..N
+ **********************************************************************/
+static ib_api_status_t
+__parse_port_info_file(IN osm_vendor_t * const p_vend,
+		       IN uint32_t hca_idx,
+		       IN uint8_t port_num, OUT sim_port_info_t * sim_port_info)
+{
+	ib_api_status_t status = IB_ERROR;
+	int info_file;
+	char file_name[256];
+	char file_buffer[3200];
+	char state[12];
+	char *p_ch;
+	int lid, sm_lid, lmc, sm_sl;
+	uint32_t len;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"__parse_port_info_file: "
+		"Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx,
+		port_num);
+
+	/* we use the proc file system so we must be able to open the info file .. */
+	sprintf(file_name, "%s/ca%d/port%d/info", __get_simulator_dir(),
+		hca_idx, port_num);
+	info_file = open(file_name, O_RDONLY);
+	if (!info_file) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5112: "
+			"Fail to open HCA:%d Port:%d info file:(%s).\n",
+			hca_idx, port_num, file_name);
+		goto Exit;
+	}
+
+	/* read in the file */
+	len = read(info_file, file_buffer, 3200);
+	close(info_file);
+	file_buffer[len] = '\0';
+
+	/*
+	   parse the file ...
+	   state:         ACTIVE
+	   LID:           0x0001
+	   LMC:           0x0000
+	   SM LID:        0x0001
+	   SM SL:         0x0000
+	   ...
+	 */
+	if (!(p_ch = strstr(file_buffer, "state:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5113: "
+			"Fail to obtain port state. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "state: %s", state) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5114: "
+			"Fail to parse state from info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+
+	if (!strcmp(state, "ACTIVE"))
+		sim_port_info->state = IB_LINK_ACTIVE;
+	else if (!strcmp(state, "DOWN"))
+		sim_port_info->state = IB_LINK_DOWN;
+	else if (!strcmp(state, "INIT"))
+		sim_port_info->state = IB_LINK_INIT;
+	else if (!strcmp(state, "ARMED"))
+		sim_port_info->state = IB_LINK_ARMED;
+	else
+		sim_port_info->state = 0;
+
+	/* get lid */
+	if (!(p_ch = strstr(file_buffer, "LID:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5115: "
+			"Fail to obtain port lid. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "LID: %x", &lid) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5116: "
+			"Fail to parse lid from info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_port_info->lid = lid;
+	/* get LMC */
+	if (!(p_ch = strstr(file_buffer, "LMC:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5117: "
+			"Fail to obtain port LMC. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "LMC: %x", &lmc) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5118: "
+			"Fail to parse LMC from info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_port_info->lmc = lmc;
+
+	/* get SM LID */
+	if (!(p_ch = strstr(file_buffer, "SM LID:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5119: "
+			"Fail to obtain port SM LID. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5120: "
+			"Fail to parse SM LID from info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_port_info->sm_lid = sm_lid;
+
+	/* get SM LID */
+	if (!(p_ch = strstr(file_buffer, "SM SL:"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5121: "
+			"Fail to obtain port SM SL. In info file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__parse_port_info_file: ERR 5122: "
+			"Fail to parse SM SL from info file:(%s).\n", p_ch);
+		goto Exit;
+	}
+	sim_port_info->sm_sl = sm_sl;
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"__parse_port_info_file:  "
+		"Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n",
+		port_num, sim_port_info->state, sim_port_info->lid,
+		sim_port_info->lmc, sim_port_info->sm_lid,
+		sim_port_info->sm_sl);
+
+	status = IB_SUCCESS;
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return status;
+}
+
+/**********************************************************************
+ * Parse the port guid_tbl file to obtain the port guid.
+ * File format is:
+ * [  0] fe80:0000:0000:0000:0002:c900:0120:3472
+ **********************************************************************/
+static ib_api_status_t
+__get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,
+				  IN uint32_t hca_idx,
+				  IN uint8_t port_num, OUT uint64_t * port_guid)
+{
+	ib_api_status_t status = IB_ERROR;
+	int info_file;
+	char file_name[256];
+	char file_buffer[3200];
+	char *p_ch;
+	int g[8];
+	uint32_t len;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"__get_port_guid_from_port_gid_tbl: "
+		"Parsing Proc File System Port Guid Table CA %d Port %d.\n",
+		hca_idx, port_num);
+
+	/* we use the proc file system so we must be able to open the info file .. */
+	sprintf(file_name, "%s/ca%d/port%d/gid_table",
+		__get_simulator_dir(), hca_idx, port_num);
+	info_file = open(file_name, O_RDONLY);
+	if (!info_file) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__get_port_guid_from_port_gid_tbl: ERR 5123: "
+			"Fail to open HCA:%d Port:%d gid_table file:(%s).\n",
+			hca_idx, port_num, file_name);
+		goto Exit;
+	}
+
+	/* read in the file */
+	len = read(info_file, file_buffer, 3200);
+	close(info_file);
+	file_buffer[len] = '\0';
+
+	/*
+	   parse the file ...
+	   [  0] fe80:0000:0000:0000:0002:c900:0120:3472
+	   ...
+	 */
+	if (!(p_ch = strstr(file_buffer, "[  0]"))) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__get_port_guid_from_port_gid_tbl: ERR 5124: "
+			"Fail to obtain first gid index. In gid_table file:(%s).\n",
+			file_buffer);
+		goto Exit;
+	}
+	if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x",
+		   &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8)
+	{
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"__get_port_guid_from_port_gid_tbl: ERR 5125: "
+			"Fail to parse gid from gid_table file:(%s).\n", p_ch);
+		goto Exit;
+	}
+
+	*port_guid =
+	    (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] <<
+	    16 | g[0];
+	status = IB_SUCCESS;
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return status;
+}
+
+/**********************************************************************
+ * Initialize an Info Struct for the Given HCA by its index 1..N
+ **********************************************************************/
+static ib_api_status_t
+__osm_ca_info_init(IN osm_vendor_t * const p_vend,
+		   IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
+{
+	ib_api_status_t status = IB_ERROR;
+	uint8_t port_num;
+	uint64_t port_guid;
+
+	sim_ca_info_t sim_ca_info;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	/* parse the CA info file */
+	if (__parse_ca_info_file(p_vend, idx, &sim_ca_info) != IB_SUCCESS)
+		goto Exit;
+
+	p_ca_info->guid = cl_hton64(sim_ca_info.guid);
+
+	/* set size of attributes and allocate them */
+	p_ca_info->attr_size = 1;
+	p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
+
+	p_ca_info->p_attr->ca_guid = p_ca_info->guid;
+	p_ca_info->p_attr->num_ports = sim_ca_info.num_ports;
+
+	/* now obtain the attributes of the ports */
+	p_ca_info->p_attr->p_port_attr =
+	    (ib_port_attr_t *) malloc(sim_ca_info.num_ports *
+				      sizeof(ib_port_attr_t));
+
+	/* get all the ports info */
+	for (port_num = 1; port_num <= sim_ca_info.num_ports; port_num++) {
+		sim_port_info_t sim_port_info;
+		/* query the port attributes */
+		if (__parse_port_info_file
+		    (p_vend, idx, port_num, &sim_port_info)) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"__osm_ca_info_init: ERR 5126: "
+				"Fail to get HCA:%d Port:%d Attributes.\n", idx,
+				port_num);
+			goto Exit;
+		}
+
+		/* HACK: the lids should have been converted to network but the rest of the code
+		   is wrong and provdes them as is (host order) - so we stick with it. */
+		p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
+		    sim_port_info.lid;
+		p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
+		    sim_port_info.state;
+		p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
+		    sim_port_info.sm_lid;
+
+		/* get the port guid */
+		if (__get_port_guid_from_port_gid_tbl
+		    (p_vend, idx, port_num, &port_guid)) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"__osm_ca_info_init: ERR 5127: "
+				"Fail to get HCA:%d Port:%d Guid.\n", idx,
+				port_num);
+			goto Exit;
+		}
+		p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
+		    cl_hton64(port_guid);
+	}
+
+	status = IB_SUCCESS;
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
+		    IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
+{
+	osm_ca_info_t *p_ca;
+	uint8_t i;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	for (i = 0; i < num_ca; i++) {
+		p_ca = &p_ca_info[i];
+
+		if (NULL != p_ca->p_attr) {
+			if (0 != p_ca->p_attr->num_ports) {
+				free(p_ca->p_attr->p_port_attr);
+			}
+
+			free(p_ca->p_attr);
+		}
+	}
+
+	free(p_ca_info);
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+/**********************************************************************
+ * Fill in the array of port_attr with all available ports on ALL the
+ * avilable CAs on this machine.
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
+			     IN ib_port_attr_t * const p_attr_array,
+			     IN uint32_t * const p_num_ports)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	uint32_t caIdx;
+	uint32_t ca_count = 0;
+	uint32_t port_count = 0;
+	uint8_t port_num;
+	uint32_t total_ports = 0;
+	osm_ca_info_t *p_ca_infos = NULL;
+	uint32_t attr_array_sz = *p_num_ports;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend);
+
+	/* determine the number of CA's */
+	ca_count = __hca_sim_get_num_cas();
+	if (!ca_count) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_all_port_attr: ERR 5128: "
+			"Fail to get Any CA Ids.\n");
+		goto Exit;
+	}
+
+	/* Allocate an array big enough to hold the ca info objects */
+	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
+	if (p_ca_infos == NULL) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_all_port_attr: ERR 5129: "
+			"Unable to allocate CA information array.\n");
+		goto Exit;
+	}
+
+	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
+
+	/*
+	 * For each CA, retrieve the CA info attributes
+	 */
+	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
+		status =
+		    __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
+		if (status != IB_SUCCESS) {
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"osm_vendor_get_all_port_attr: ERR 5130: "
+				"Unable to initialize CA Info object (%s).\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
+	}
+
+	*p_num_ports = total_ports;
+	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
+
+	/*
+	 * If the user supplied enough storage, return the port guids,
+	 * otherwise, return the appropriate error.
+	 */
+	if (attr_array_sz >= total_ports) {
+		for (caIdx = 1; caIdx <= ca_count; caIdx++) {
+			uint32_t num_ports;
+
+			num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
+
+			for (port_num = 0; port_num < num_ports; port_num++) {
+				p_attr_array[port_count] =
+				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
+								     [caIdx -
+								      1],
+								     port_num);
+				port_count++;
+			}
+		}
+	} else {
+		status = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	if (p_ca_infos) {
+		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ * Given the vendor obj and a port guid
+ * return the ca id and port number that have that guid
+ **********************************************************************/
+
+ib_api_status_t
+osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
+				IN ib_net64_t const guid,
+				OUT uint32_t * p_hca_hndl,
+				OUT char *p_hca_id,
+				OUT uint8_t * p_hca_idx,
+				OUT uint32_t * p_port_num)
+{
+	uint32_t caIdx;
+	uint32_t ca_count = 0;
+	uint8_t port_num;
+	ib_api_status_t status = IB_ERROR;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend);
+
+	/* determine the number of CA's */
+	ca_count = __hca_sim_get_num_cas();
+	if (!ca_count) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_guid_ca_and_port: ERR 5131: "
+			"Fail to get Any CA Ids.\n");
+		goto Exit;
+	}
+
+	/*
+	 * For each CA, retrieve the CA info attributes
+	 */
+	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
+		sim_ca_info_t sim_ca_info;
+		if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
+		    IB_SUCCESS) {
+			/* get all the ports info */
+			for (port_num = 1; port_num <= sim_ca_info.num_ports;
+			     port_num++) {
+				uint64_t port_guid;
+				if (!__get_port_guid_from_port_gid_tbl
+				    (p_vend, caIdx, port_num, &port_guid)) {
+					if (cl_hton64(port_guid) == guid) {
+						osm_log(p_vend->p_log,
+							OSM_LOG_DEBUG,
+							"osm_vendor_get_guid_ca_and_port: "
+							"Found Matching guid on HCA:%d Port:%d.\n",
+							caIdx, port_num);
+						strcpy(p_hca_id,
+						       sim_ca_info.name);
+						*p_port_num = port_num;
+						*p_hca_idx = caIdx - 1;
+						*p_hca_hndl = 0;
+						status = IB_SUCCESS;
+						goto Exit;
+					}
+				}
+			}
+		}
+	}
+
+	osm_log(p_vend->p_log, OSM_LOG_ERROR,
+		"osm_vendor_get_guid_ca_and_port: ERR 5132: "
+		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
+		cl_ntoh64(guid));
+	status = IB_INVALID_GUID;
+
+Exit:
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ * Given the vendor obj HCA ID and Port Num
+ * update the given port guid if found. Return 0 on success.
+ **********************************************************************/
+
+ib_api_status_t
+osm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend,
+				   IN char *hca_id,
+				   IN uint32_t port_num,
+				   OUT uint64_t * p_port_guid)
+{
+	uint32_t caIdx;
+	uint32_t ca_count = 0;
+	ib_api_status_t status = IB_ERROR;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_vend);
+
+	/* determine the number of CA's */
+	ca_count = __hca_sim_get_num_cas();
+	if (!ca_count) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_get_guid_by_ca_and_port: ERR 5133: "
+			"Fail to get Any CA Ids.\n");
+		goto Exit;
+	}
+
+	/*
+	 * For each CA, retrieve the CA info attributes
+	 */
+	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
+		sim_ca_info_t sim_ca_info;
+		if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
+		    IB_SUCCESS) {
+			/* if not identical by id - go to next one */
+			if (strcmp(sim_ca_info.name, hca_id))
+				continue;
+
+			if ((port_num < 1)
+			    || (port_num > sim_ca_info.num_ports)) {
+				return 1;
+			}
+
+			if (!__get_port_guid_from_port_gid_tbl
+			    (p_vend, caIdx, port_num, p_port_guid)) {
+				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+					"osm_vendor_get_guid_by_ca_and_port: "
+					"Found Matching guid on HCA:%d Port:%d.\n",
+					caIdx, port_num);
+				status = IB_SUCCESS;
+				goto Exit;
+			}
+		}
+	}
+
+	osm_log(p_vend->p_log, OSM_LOG_ERROR,
+		"osm_vendor_get_guid_by_ca_and_port: ERR 5134: "
+		"Fail to find HCA:%s\n", hca_id);
+	status = IB_INVALID_GUID;
+
+Exit:
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+#endif
diff --git a/libvendor/osm_vendor_mlx_ibmgt.c b/libvendor/osm_vendor_mlx_ibmgt.c
new file mode 100644
index 0000000..9df6624
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_ibmgt.c
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*  AUTHOR                 Edward Bortnikov
+ *
+ *  DESCRIPTION
+ *     The lower-level MAD transport interface implementation
+ *     that allows sending a single MAD/receiving a callback
+ *     when a single MAD is received.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ib_mgt.h>
+#include <complib/cl_event.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_dispatcher.h>
+#include <opensm/osm_log.h>
+
+typedef struct _osmv_IBMGT_transport_mgr_ {
+	IB_MGT_mad_type_t mad_type;
+	uint8_t mgmt_class;	/* for gsi */
+	/* for communication between send call back and send mad */
+	boolean_t is_send_ok;
+	cl_event_t send_done;
+} osmv_IBMGT_transport_mgr_t;
+
+typedef struct _osmv_IBMGT_transport_info_ {
+	IB_MGT_mad_hndl_t smi_h;
+	cl_qlist_t *p_smi_list;
+
+	IB_MGT_mad_hndl_t gsi_h;
+	/* holds bind object list for every binded mgmt class */
+	cl_qlist_t *gsi_mgmt_lists[15];
+} osmv_IBMGT_transport_info_t;
+
+static void
+__osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
+				  IN uint8_t is_smi,
+				  OUT osm_mad_addr_t * p_mad_addr);
+
+static void
+__osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
+				    IN uint8_t is_smi, OUT IB_ud_av_t * p_av);
+
+void
+__osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
+		     IN u_int64_t wrid,
+		     IN IB_comp_status_t status, IN void *private_ctx_p);
+
+void
+__osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
+		    IN void *private_ctx_p,
+		    IN void *payload_p,
+		    IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p);
+
+/*
+ * NAME
+ *   osmv_transport_init
+ *
+ * DESCRIPTION
+ *   Setup the MAD transport infrastructure (filters, callbacks etc).
+ */
+
+ib_api_status_t
+osmv_transport_init(IN osm_bind_info_t * p_info,
+		    IN char hca_id[VENDOR_HCA_MAXNAMES],
+		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
+{
+	ib_api_status_t st = IB_SUCCESS;
+	IB_MGT_ret_t ret;
+	IB_MGT_mad_type_t mad_type;
+	osmv_IBMGT_transport_mgr_t *p_mgr;
+	osmv_IBMGT_transport_info_t *p_tpot_info;
+	cl_list_obj_t *p_obj = NULL;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+	int i;
+
+	UNUSED_PARAM(hca_idx);
+
+	/* if first bind, allocate tranport_info at vendor */
+	if (NULL == p_bo->p_vendor->p_transport_info) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"osmv_transport_init: first bind() for the vendor\n");
+		p_bo->p_vendor->p_transport_info
+		    = (osmv_IBMGT_transport_info_t *)
+		    malloc(sizeof(osmv_IBMGT_transport_info_t));
+		if (NULL == p_bo->p_vendor->p_transport_info) {
+			return IB_INSUFFICIENT_MEMORY;
+		}
+		memset(p_bo->p_vendor->p_transport_info, 0,
+		       sizeof(osmv_IBMGT_transport_info_t));
+		p_tpot_info =
+		    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
+						     p_transport_info);
+
+		p_tpot_info->smi_h = 0xffffffff;
+		p_tpot_info->p_smi_list = NULL;
+
+		p_tpot_info->gsi_h = 0xffffffff;
+		for (i = 0; i < 15; i++) {
+
+			p_tpot_info->gsi_mgmt_lists[i] = NULL;
+		}
+
+	} else {
+
+		p_tpot_info =
+		    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
+						     p_transport_info);
+	}
+
+	/* Initialize the magic_ptr to the pointer of the p_bo info.
+	   This will be used to signal when the object is being destroyed, so no
+	   real action will be done then. */
+	p_bo->magic_ptr = p_bo;
+
+	/* allocate transport mgr */
+	p_mgr = malloc(sizeof(osmv_IBMGT_transport_mgr_t));
+	if (NULL == p_mgr) {
+		free(p_tpot_info);
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osmv_transport_init: ERR 7201: " "alloc failed \n");
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_mgr, 0, sizeof(osmv_IBMGT_transport_mgr_t));
+
+	p_bo->p_transp_mgr = p_mgr;
+
+	switch (p_info->mad_class) {
+	case IB_MCLASS_SUBN_LID:
+	case IB_MCLASS_SUBN_DIR:
+		mad_type = IB_MGT_SMI;
+		break;
+
+	case IB_MCLASS_SUBN_ADM:
+	default:
+		mad_type = IB_MGT_GSI;
+		break;
+	}
+
+	/* we only support one class registration per SMI/GSI !!! */
+	switch (mad_type) {
+	case IB_MGT_SMI:
+		/* we do not need to bind the handle if already available */
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"osmv_transport_init: SMI bind\n");
+
+		if (p_tpot_info->smi_h == 0xffffffff) {
+			ret = IB_MGT_get_handle(hca_id,
+						p_bo->port_num,
+						IB_MGT_SMI,
+						&(p_tpot_info->smi_h));
+			if (IB_MGT_OK != ret) {
+				osm_log(p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7202: "
+					"IB_MGT_get_handle for smi failed \n");
+				st = IB_ERROR;
+				free(p_mgr);
+				goto Exit;
+			}
+
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"osmv_transport_init: got smi handle:%d \n",
+				p_tpot_info->smi_h);
+
+			ret = IB_MGT_bind_sm(p_tpot_info->smi_h);
+			if (IB_MGT_OK != ret) {
+				osm_log(p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7203: "
+					"IB_MGT_bind_sm failed \n");
+				st = IB_ERROR;
+				free(p_mgr);
+				goto Exit;
+			}
+
+			/* init smi list */
+			p_tpot_info->p_smi_list = malloc(sizeof(cl_qlist_t));
+			if (NULL == p_tpot_info->p_smi_list) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7204: "
+					"alloc failed \n");
+				IB_MGT_unbind_sm(p_tpot_info->smi_h);
+				IB_MGT_release_handle(p_tpot_info->smi_h);
+				free(p_mgr);
+				return IB_INSUFFICIENT_MEMORY;
+			}
+			memset(p_tpot_info->p_smi_list, 0, sizeof(cl_qlist_t));
+			cl_qlist_init(p_tpot_info->p_smi_list);
+
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"osmv_transport_init: before reg_cb\n");
+			ret = IB_MGT_reg_cb(p_tpot_info->smi_h,
+					    &__osmv_IBMGT_rcv_cb,
+					    p_bo,
+					    &__osmv_IBMGT_send_cb,
+					    p_tpot_info->p_smi_list,
+					    IB_MGT_RCV_CB_MASK |
+					    IB_MGT_SEND_CB_MASK);
+			if (ret != IB_SUCCESS) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7205: "
+					"reg_cb failed with return code:%x \n",
+					ret);
+				IB_MGT_unbind_sm(p_tpot_info->smi_h);
+				IB_MGT_release_handle(p_tpot_info->smi_h);
+				free(p_tpot_info->p_smi_list);
+				free(p_mgr);
+				st = IB_ERROR;
+				goto Exit;
+			}
+
+		}
+		/* insert to list of smi's - for raising callbacks later on */
+		p_obj = malloc(sizeof(cl_list_obj_t));
+		if (p_obj)
+			memset(p_obj, 0, sizeof(cl_list_obj_t));
+		cl_qlist_set_obj(p_obj, p_bo);
+		cl_qlist_insert_tail(p_tpot_info->p_smi_list,
+				     &p_obj->list_item);
+
+		break;
+
+	case IB_MGT_GSI:
+		/* we do not need to bind the handle if already available */
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"osmv_transport_init: ERR 7206: GSI bind\n");
+		if (p_tpot_info->gsi_h == 0xffffffff) {
+			ret = IB_MGT_get_handle(hca_id,
+						p_bo->port_num,
+						IB_MGT_GSI,
+						&(p_tpot_info->gsi_h));
+			if (IB_MGT_OK != ret) {
+				osm_log(p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7207: "
+					"IB_MGT_get_handle for gsi failed \n");
+				st = IB_ERROR;
+				free(p_mgr);
+				goto Exit;
+			}
+		}
+
+		/* this mgmt class was not binded yet */
+		if (p_tpot_info->gsi_mgmt_lists[p_info->mad_class] == NULL) {
+			ret =
+			    IB_MGT_bind_gsi_class(p_tpot_info->gsi_h,
+						  p_info->mad_class);
+			if (IB_MGT_OK != ret) {
+				osm_log(p_log, OSM_LOG_ERROR,
+					"osmv_transport_init: ERR 7208: "
+					"IB_MGT_bind_gsi_class failed \n");
+				st = IB_ERROR;
+				free(p_mgr);
+				goto Exit;
+			}
+
+			p_tpot_info->gsi_mgmt_lists[p_info->mad_class] =
+			    malloc(sizeof(cl_qlist_t));
+			if (NULL ==
+			    p_tpot_info->gsi_mgmt_lists[p_info->mad_class]) {
+				IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
+							p_info->mad_class);
+				free(p_mgr);
+				return IB_INSUFFICIENT_MEMORY;
+			}
+			memset(p_tpot_info->gsi_mgmt_lists[p_info->mad_class],
+			       0, sizeof(cl_qlist_t));
+			cl_qlist_init(p_tpot_info->
+				      gsi_mgmt_lists[p_info->mad_class]);
+		}
+		/* insert to list of smi's - for raising callbacks later on */
+		p_obj = malloc(sizeof(cl_list_obj_t));
+		if (p_obj)
+			memset(p_obj, 0, sizeof(cl_list_obj_t));
+		cl_qlist_set_obj(p_obj, p_bo);
+		cl_qlist_insert_tail(p_tpot_info->
+				     gsi_mgmt_lists[p_info->mad_class],
+				     &p_obj->list_item);
+
+		p_mgr->mgmt_class = p_info->mad_class;
+		ret = IB_MGT_reg_cb(p_tpot_info->gsi_h,
+				    &__osmv_IBMGT_rcv_cb,
+				    p_bo,
+				    &__osmv_IBMGT_send_cb,
+				    p_bo,
+				    IB_MGT_RCV_CB_MASK | IB_MGT_SEND_CB_MASK);
+
+		if (ret != IB_SUCCESS) {
+			IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
+						p_mgr->mgmt_class);
+			free(p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class]);
+			free(p_mgr);
+			st = IB_ERROR;
+			goto Exit;
+		}
+
+		break;
+
+	default:
+		osm_log(p_log, OSM_LOG_ERROR,
+			"osmv_transport_init: ERR 7209: unrecognized mgmt class \n");
+		st = IB_ERROR;
+		free(p_mgr);
+		goto Exit;
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"osmv_transport_init: GSI bind\n");
+	cl_event_construct(&p_mgr->send_done);
+	cl_event_init(&p_mgr->send_done, TRUE);
+	p_mgr->is_send_ok = FALSE;
+	p_mgr->mad_type = mad_type;
+
+Exit:
+	/* OSM_LOG_EXIT(p_log ); */
+	return (ib_api_status_t) st;
+}
+
+/*
+ * NAME
+ *   osmv_transport_send_mad
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 byte)
+ */
+
+ib_api_status_t
+osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
+			IN void *p_ib_mad, IN const osm_mad_addr_t * p_mad_addr)
+{
+
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osmv_IBMGT_transport_info_t *p_tpot_info =
+	    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	ib_api_status_t status;
+	IB_ud_av_t av;
+	IB_MGT_ret_t ret;
+	ib_mad_t *p_mad = p_ib_mad;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	CL_ASSERT(p_bo->p_vendor->p_transport_info);
+
+	/*
+	 * For all sends other than directed route SM MADs,
+	 * acquire an address vector for the destination.
+	 */
+	if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
+		__osmv_IBMGT_osm_addr_to_ibmgt_addr(p_mad_addr,
+						    p_mad->mgmt_class ==
+						    IB_MCLASS_SUBN_LID, &av);
+	} else {
+		/* is a directed route - we need to construct a permissive address */
+		memset(&av, 0, sizeof(av));
+		/* we do not need port number since it is part of the mad_hndl */
+		av.dlid = IB_LID_PERMISSIVE;
+	}
+
+	/* send it */
+	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
+	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
+
+		/* SMI CASE */
+		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
+			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+				"osmv_transport_mad_send: "
+				"av.dlid:0x%X, "
+				"av.static_rate:%d, "
+				"av.path_bits:%d.\n",
+				cl_ntoh16(av.dlid), av.static_rate,
+				av.src_path_bits);
+		}
+
+		ret = IB_MGT_send_mad(p_tpot_info->smi_h, p_mad,	/*  actual payload */
+				      &av,	/*  address vector */
+				      (u_int64_t) CAST_P2LONG(p_bo),
+				      IB_MGT_DEFAULT_SEND_TIME);
+	} else {
+		/* GSI CASE - Support Remote QP */
+		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
+			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+				"osmv_transport_mad_send: "
+				"av.dlid:0x%X, av.static_rate:%d, av.path_bits:%d, remote qp:%d \n",
+				cl_ntoh16(av.dlid), av.static_rate,
+				av.src_path_bits,
+				cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp)
+			    );
+		}
+
+		ret = IB_MGT_send_mad_to_qp(p_tpot_info->gsi_h, p_mad,	/*  actual payload */
+					    &av,	/*  address vector */
+					    (u_int64_t) CAST_P2LONG(p_bo),
+					    IB_MGT_DEFAULT_SEND_TIME,
+					    cl_ntoh32(p_mad_addr->addr_type.gsi.
+						      remote_qp));
+
+	}
+
+	status = IB_SUCCESS;
+	if (ret != IB_MGT_OK) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osmv_transport_mad_send: ERR 7210: "
+			"Error sending mad (%d).\n", ret);
+		status = IB_ERROR;
+	} else {
+		osmv_IBMGT_transport_mgr_t *p_mgr =
+		    (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
+
+		/* Let the others work when I am sleeping ... */
+		osmv_txn_unlock(p_bo);
+
+		cl_event_wait_on(&(p_mgr->send_done), 0xffffffff, TRUE);
+
+		/* Re-acquire the lock */
+		osmv_txn_lock(p_bo);
+
+		if (TRUE == p_bo->is_closing) {
+
+			osm_log(p_vend->p_log, OSM_LOG_ERROR,
+				"osmv_transport_mad_send: ERR 7211: "
+				"The handle %p is being unbound, cannot send.\n",
+				h_bind);
+			status = IB_ERROR;
+		}
+
+		if (p_mgr->is_send_ok == FALSE) {
+			status = IB_ERROR;
+		}
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+void osmv_transport_done(IN const osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+	osmv_IBMGT_transport_mgr_t *p_mgr;
+	osmv_IBMGT_transport_info_t *p_tpot_info;
+	IB_MGT_ret_t ret;
+	cl_list_obj_t *p_obj = NULL;
+	cl_list_item_t *p_item, *p_item_tmp;
+	int i;
+	cl_qlist_t *p_list = NULL;
+
+	OSM_LOG_ENTER(p_log);
+
+	CL_ASSERT(p_bo);
+
+	/* First of all - zero out the magic_ptr, so if a callback is called -
+	   it'll know that we are currently closing down, and will not handle the
+	   mad. */
+	p_bo->magic_ptr = 0;
+
+	p_mgr = (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
+	p_tpot_info =
+	    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
+
+	switch (p_mgr->mad_type) {
+	case IB_MGT_SMI:
+		p_list = p_tpot_info->p_smi_list;
+
+		/* remove from the bindings list */
+		p_item = cl_qlist_head(p_list);
+		while (p_item != cl_qlist_end(p_list)) {
+			p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+			if (cl_qlist_obj(p_obj) == h_bind) {
+				break;
+			}
+			p_item_tmp = cl_qlist_next(p_item);
+			p_item = p_item_tmp;
+		}
+
+		CL_ASSERT(p_item != cl_qlist_end(p_list));
+		cl_qlist_remove_item(p_list, p_item);
+		if (p_obj)
+			free(p_obj);
+
+		/* no one is binded to smi anymore - we can free the list, unbind & realease the hndl */
+		if (cl_is_qlist_empty(p_list) == TRUE) {
+			free(p_list);
+			p_list = NULL;
+
+			ret = IB_MGT_unbind_sm(p_tpot_info->smi_h);
+			if (ret != IB_MGT_OK) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_done: ERR 7212: "
+					"Failed to unbind sm\n");
+			}
+
+			ret = IB_MGT_release_handle(p_tpot_info->smi_h);
+			if (ret != IB_MGT_OK) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_done: ERR 7213: "
+					"Failed to release smi handle\n");
+			}
+			p_tpot_info->smi_h = 0xffffffff;
+		}
+		break;
+
+	case IB_MGT_GSI:
+		p_list = p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class];
+		/* remove from the bindings list */
+		p_item = cl_qlist_head(p_list);
+		while (p_item != cl_qlist_end(p_list)) {
+			p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+			if (cl_qlist_obj(p_obj) == h_bind) {
+				break;
+			}
+			p_item_tmp = cl_qlist_next(p_item);
+			p_item = p_item_tmp;
+		}
+
+		CL_ASSERT(p_item != cl_qlist_end(p_list));
+		cl_qlist_remove_item(p_list, p_item);
+		if (p_obj)
+			free(p_obj);
+
+		/* no one is binded to this class anymore - we can free the list and unbind this class */
+		if (cl_is_qlist_empty(p_list) == TRUE) {
+			free(p_list);
+			p_list = NULL;
+
+			ret =
+			    IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
+						    p_mgr->mgmt_class);
+			if (ret != IB_MGT_OK) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_done: ERR 7214: "
+					"Failed to unbind gsi class\n");
+			}
+		}
+
+		/* all the mgmt classes are unbinded - release gsi handle */
+		for (i = 0; i < 15; i++) {
+			if (p_tpot_info->gsi_mgmt_lists[i] != NULL) {
+				break;
+			}
+		}
+
+		if (i == 15) {
+			ret = IB_MGT_release_handle(p_tpot_info->gsi_h);
+			if (ret != IB_MGT_OK) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"osmv_transport_done: ERR 7215: "
+					"Failed to release gsi handle\n");
+			}
+			p_tpot_info->gsi_h = 0xffffffff;
+		}
+	}			/* end switch */
+
+	free(p_mgr);
+}
+
+/**********************************************************************
+ * IB_MGT Receive callback : invoked after each receive
+ **********************************************************************/
+void
+__osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
+		    IN void *private_ctx_p,
+		    IN void *payload_p,
+		    IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p)
+{
+	osmv_bind_obj_t *p_bo;
+	osm_mad_addr_t mad_addr;
+	cl_list_item_t *p_item;
+	cl_list_obj_t *p_obj;
+	cl_qlist_t *p_list;
+	ib_mad_t *p_mad = (ib_mad_t *) payload_p;
+	osm_vendor_t *p_vendor;
+	osmv_IBMGT_transport_info_t *p_tinfo;
+
+	__osmv_IBMGT_rcv_desc_to_osm_addr(rcv_remote_info_p,
+					  ((p_mad->mgmt_class ==
+					    IB_MCLASS_SUBN_LID)
+					   || (p_mad->mgmt_class ==
+					       IB_MCLASS_SUBN_DIR)), &mad_addr);
+
+	/* different handling of SMI and GSI */
+	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
+	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
+		/* SMI CASE */
+		p_bo = (osmv_bind_obj_t *) private_ctx_p;
+		/* Make sure the p_bo object is still relevant */
+		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+			return;
+
+		p_vendor = p_bo->p_vendor;
+		p_tinfo =
+		    (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
+		p_list = p_tinfo->p_smi_list;
+	} else {
+		/* GSI CASE */
+		p_bo = (osmv_bind_obj_t *) private_ctx_p;
+		/* Make sure the p_bo object is still relevant */
+		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+			return;
+
+		p_vendor = p_bo->p_vendor;
+		p_tinfo =
+		    (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
+		p_list = p_tinfo->gsi_mgmt_lists[p_mad->mgmt_class];
+	}
+
+	/* go over the bindings list and send the mad, one of them will accept it,
+	   the others will drope
+	 */
+	p_item = cl_qlist_head(p_list);
+	while (p_item != cl_qlist_end(p_list)) {
+		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+		p_bo = cl_qlist_obj(p_obj);
+		/* give upper layer the mad */
+		osmv_dispatch_mad((osm_bind_handle_t) p_bo, payload_p,
+				  &mad_addr);
+		/* Make sure the p_bo object is still relevant */
+		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+			return;
+
+		p_item = cl_qlist_next(p_item);
+	}
+}
+
+/**********************************************************************
+ * IB_MGT Send callback : invoked after each send
+ **********************************************************************/
+void
+__osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
+		     IN u_int64_t wrid,
+		     IN IB_comp_status_t status, IN void *private_ctx_p)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) CAST_P2LONG(wrid);
+
+	osmv_IBMGT_transport_mgr_t *p_mgr =
+	    (osmv_IBMGT_transport_mgr_t *) p_bo->p_transp_mgr;
+
+	/* Make sure the p_bo object is still relevant */
+	if (p_bo->magic_ptr != p_bo)
+		return;
+
+	/* we assume that each send on a bind object is synchronized, and no paralel sends
+	   from diffrent threads with same object can be made */
+	if (status == IB_COMP_SUCCESS) {
+		p_mgr->is_send_ok = TRUE;
+	} else
+		p_mgr->is_send_ok = FALSE;
+	cl_event_signal(&p_mgr->send_done);
+
+}
+
+/**********************************************************************
+ * IB_MGT to OSM ADDRESS VECTOR
+ **********************************************************************/
+static void
+__osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
+				  IN uint8_t is_smi,
+				  OUT osm_mad_addr_t * p_mad_addr)
+{
+	/*  p_mad_addr->dest_lid = p_osm->subn.sm_base_lid; - for resp we use the dest lid ... */
+	p_mad_addr->dest_lid = cl_hton16(p_rcv_desc->remote_lid);
+	p_mad_addr->static_rate = 0;	/*  HACK - we do not  know the rate ! */
+	p_mad_addr->path_bits = p_rcv_desc->local_path_bits;
+	/* Clear the grh any way to avoid unset fields */
+	memset(&p_mad_addr->addr_type.gsi.grh_info, 0,
+	       sizeof(p_mad_addr->addr_type.gsi.grh_info));
+
+	if (is_smi) {
+		/* SMI */
+		p_mad_addr->addr_type.smi.source_lid =
+		    cl_hton16(p_rcv_desc->remote_lid);
+		p_mad_addr->addr_type.smi.port_num = 99;	/*  HACK - if used - should fail */
+	} else {
+		/* GSI */
+		/* seems to me there is a IBMGT bug reversing the QPN ... */
+		/* Does IBMGT supposed to provide the QPN is network or HOST ? */
+		p_mad_addr->addr_type.gsi.remote_qp = cl_hton32(p_rcv_desc->qp);
+
+		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+		/*  we do have the p_mad_addr->pkey_ix but how to get the PKey by index ? */
+		/*  the only way seems to be to use VAPI_query_hca_pkey_tbl and obtain */
+		/*  the full PKey table - than go by the index. */
+		/*  since this does not seem reasonable to me I simply use the default */
+		/*  There is a TAVOR limitation that only one P_KEY is supported per  */
+		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
+		p_mad_addr->addr_type.gsi.pkey_ix = 0;
+		p_mad_addr->addr_type.gsi.service_level = p_rcv_desc->sl;
+
+		p_mad_addr->addr_type.gsi.global_route = p_rcv_desc->grh_flag;
+		/* copy the GRH data if relevant */
+		if (p_mad_addr->addr_type.gsi.global_route) {
+			p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
+			    ib_grh_set_ver_class_flow(p_rcv_desc->grh.
+						      IP_version,
+						      p_rcv_desc->grh.
+						      traffic_class,
+						      p_rcv_desc->grh.
+						      flow_label);
+			p_mad_addr->addr_type.gsi.grh_info.hop_limit =
+			    p_rcv_desc->grh.hop_limit;
+			memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
+			       &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
+			memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
+			       p_rcv_desc->grh.dgid, sizeof(ib_net64_t));
+		}
+	}
+}
+
+/**********************************************************************
+ * OSM ADDR VECTOR TO IB_MGT
+ **********************************************************************/
+void
+__osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
+				    IN uint8_t is_smi, OUT IB_ud_av_t * p_av)
+{
+
+	/* For global destination or Multicast address: */
+	u_int8_t ver;
+
+	memset(p_av, 0, sizeof(IB_ud_av_t));
+
+	p_av->src_path_bits = p_mad_addr->path_bits;
+	p_av->static_rate = p_mad_addr->static_rate;
+	p_av->dlid = cl_ntoh16(p_mad_addr->dest_lid);
+
+	if (is_smi) {
+		p_av->sl = 0;	/*  Just to note we use 0 here. */
+	} else {
+		p_av->sl = p_mad_addr->addr_type.gsi.service_level;
+		p_av->grh_flag = p_mad_addr->addr_type.gsi.global_route;
+
+		if (p_mad_addr->addr_type.gsi.global_route) {
+			ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.
+						  grh_info.ver_class_flow, &ver,
+						  &p_av->traffic_class,
+						  &p_av->flow_label);
+			p_av->hop_limit =
+			    p_mad_addr->addr_type.gsi.grh_info.hop_limit;
+			p_av->sgid_index = 0;	/*  we always use source GID 0 */
+			memcpy(&p_av->dgid,
+			       &p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
+			       sizeof(ib_net64_t));
+
+		}
+	}
+}
diff --git a/libvendor/osm_vendor_mlx_rmpp_ctx.c b/libvendor/osm_vendor_mlx_rmpp_ctx.c
new file mode 100644
index 0000000..bbd42c3
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_rmpp_ctx.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+
+#include <vendor/osm_vendor_mlx_rmpp_ctx.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+
+ib_api_status_t
+osmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *p_arbt_mad,
+			uint32_t mad_sz, osm_log_t * p_log)
+{
+	ib_api_status_t st = IB_SUCCESS;
+	cl_status_t cl_st;
+
+	CL_ASSERT(p_ctx);
+	if (NULL == p_arbt_mad) {
+		return IB_INVALID_PARAMETER;
+	}
+
+	if (osmv_mad_is_sa((ib_mad_t *) p_arbt_mad)) {
+		p_ctx->is_sa_mad = TRUE;
+	} else
+		p_ctx->is_sa_mad = FALSE;
+
+	p_ctx->mad_sz = mad_sz;
+
+	cl_event_construct(&p_ctx->event);
+	cl_st = cl_event_init(&p_ctx->event, FALSE);
+	if (cl_st != CL_SUCCESS) {
+		return IB_ERROR;
+	}
+
+	st = osmv_rmpp_sar_init(&p_ctx->sar, p_arbt_mad, p_ctx->mad_sz,
+				p_ctx->is_sa_mad);
+	if (st == IB_SUCCESS) {
+		p_ctx->window_first = 1;
+		p_ctx->window_last = 1;
+	}
+
+	p_ctx->p_log = p_log;
+	return st;
+}
+
+void osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * p_ctx)
+{
+	CL_ASSERT(p_ctx);
+	cl_event_destroy(&p_ctx->event);
+	osmv_rmpp_sar_done(&p_ctx->sar);
+	free(p_ctx);
+}
+
+uint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx)
+{
+	uint32_t data_len, data_sz, num;
+
+	CL_ASSERT(p_send_ctx);
+
+	if (p_send_ctx->is_sa_mad) {
+		data_len = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE;
+		data_sz = IB_SA_DATA_SIZE;
+	} else {
+		data_len = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE;
+		data_sz = MAD_RMPP_DATA_SIZE;
+	}
+
+	num = data_len / data_sz;
+	if (0 == data_len || (data_len % data_sz) > 0) {
+		num++;
+	}
+
+	return num;
+}
+
+ib_api_status_t
+osmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx,
+			   IN uint32_t seg_idx,
+			   IN uint32_t resp_timeout, OUT void *p_buf)
+{
+	ib_api_status_t st = IB_SUCCESS;
+	uint32_t num_segs, paylen = 0;
+	ib_rmpp_mad_t *p_rmpp_mad;
+
+	OSM_LOG_ENTER(p_send_ctx->p_log);
+	CL_ASSERT(p_send_ctx);
+
+	st = osmv_rmpp_sar_get_mad_seg(&p_send_ctx->sar, seg_idx, p_buf);
+	if (st != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	p_rmpp_mad = (ib_rmpp_mad_t *) p_buf;
+	/* Set the relevant bits in the RMPP hdr */
+	p_rmpp_mad->rmpp_status = IB_RMPP_STATUS_SUCCESS;
+	p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_ACTIVE;
+	p_rmpp_mad->rmpp_flags |= resp_timeout << 3;
+
+	num_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
+
+	if (1 == seg_idx) {
+		p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_FIRST;
+
+		/* This is the first segment -
+		   the reported paylen is the total amount of data.
+		 */
+		if (p_send_ctx->is_sa_mad) {
+			/* sa mad hdr sz */
+			paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE;
+			paylen +=
+			    num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE);
+		} else {
+			/* mad hdr sz */
+			paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE;
+		}
+	}
+
+	if (seg_idx == num_segs) {
+		p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_LAST;
+
+		/*
+		   This is the last segment -
+		   the reported paylen is only the amount of data left on this segment.
+		 */
+		if (p_send_ctx->is_sa_mad) {
+			paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE;
+			paylen -= (num_segs - 1) * IB_SA_DATA_SIZE;
+			paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE);
+		} else {
+			paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE;
+			paylen -=
+			    (num_segs - 1) * (MAD_BLOCK_SIZE -
+					      MAD_RMPP_HDR_SIZE);
+		}
+	}
+
+	p_rmpp_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+	p_rmpp_mad->rmpp_version = 1;
+	p_rmpp_mad->paylen_newwin = cl_ntoh32(paylen);
+	p_rmpp_mad->seg_num = cl_ntoh32(seg_idx);
+
+Exit:
+	OSM_LOG_EXIT(p_send_ctx->p_log);
+	return st;
+}
+
+ib_api_status_t
+osmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log)
+{
+	ib_api_status_t st = IB_SUCCESS;
+
+	CL_ASSERT(p_ctx);
+
+	p_ctx->is_sa_mad = FALSE;
+
+	p_ctx->p_rbuf = malloc(sizeof(cl_qlist_t));
+	if (p_ctx->p_rbuf) {
+		memset(p_ctx->p_rbuf, 0, sizeof(cl_qlist_t));
+		cl_qlist_init(p_ctx->p_rbuf);
+		p_ctx->expected_seg = 1;
+	} else
+		st = IB_INSUFFICIENT_MEMORY;
+
+	p_ctx->p_log = p_log;
+
+	return st;
+}
+
+void osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx)
+{
+	cl_list_item_t *p_list_item;
+	cl_list_obj_t *p_obj;
+
+	CL_ASSERT(p_ctx);
+
+	/* go over all the items in the list and remove them */
+	p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf);
+	while (p_list_item != cl_qlist_end(p_ctx->p_rbuf)) {
+
+		p_obj = PARENT_STRUCT(p_list_item, cl_list_obj_t, list_item);
+
+		free(cl_qlist_obj(p_obj));
+		free(p_obj);
+
+		p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf);
+	}
+
+	osmv_rmpp_sar_done(&p_ctx->sar);
+
+	free(p_ctx->p_rbuf);
+	free(p_ctx);
+}
+
+ib_api_status_t
+osmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx,
+				 IN void *p_mad)
+{
+	cl_list_obj_t *p_obj = NULL;
+	void *p_list_mad;
+
+	OSM_LOG_ENTER(p_recv_ctx->p_log);
+
+	CL_ASSERT(p_recv_ctx);
+	p_list_mad = malloc(MAD_BLOCK_SIZE);
+	if (NULL == p_list_mad) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+	memset(p_list_mad, 0, MAD_BLOCK_SIZE);
+	memcpy(p_list_mad, p_mad, MAD_BLOCK_SIZE);
+
+	p_obj = malloc(sizeof(cl_list_obj_t));
+	if (NULL == p_obj) {
+		free(p_list_mad);
+		return IB_INSUFFICIENT_MEMORY;
+	}
+	memset(p_obj, 0, sizeof(cl_list_obj_t));
+	cl_qlist_set_obj(p_obj, p_list_mad);
+
+	cl_qlist_insert_tail(p_recv_ctx->p_rbuf, &p_obj->list_item);
+
+	if (osmv_mad_is_sa((ib_mad_t *) p_mad)) {
+		p_recv_ctx->is_sa_mad = TRUE;
+	}
+
+	return IB_SUCCESS;
+
+}
+
+uint32_t
+osmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx)
+{
+	uint32_t num_segs;
+
+	num_segs = cl_qlist_count(p_recv_ctx->p_rbuf);
+	if (p_recv_ctx->is_sa_mad)
+		return ((num_segs * IB_SA_DATA_SIZE) + IB_SA_MAD_HDR_SIZE);
+	else
+		return ((num_segs * MAD_RMPP_DATA_SIZE) + MAD_RMPP_HDR_SIZE);
+}
+
+uint32_t
+osmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t * p_recv_ctx)
+{
+	cl_list_item_t *p_item;
+	cl_list_obj_t *p_obj;
+	void *p_list_mad;
+	uint32_t num_bytes, num_segs;
+
+	p_item = cl_qlist_head(p_recv_ctx->p_rbuf);
+	p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+	p_list_mad = cl_qlist_obj(p_obj);
+
+	/* mad data sz */
+	num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin);
+	if (0 != num_bytes) {
+		if (p_recv_ctx->is_sa_mad) {
+			/* sa mad hdr sz */
+			num_segs = cl_qlist_count(p_recv_ctx->p_rbuf);
+			num_bytes -=
+			    num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE);
+			num_bytes += IB_SA_MAD_HDR_SIZE;
+		} else {
+			/* mad hdr sz */
+			num_bytes += MAD_RMPP_HDR_SIZE;
+		}
+	}
+
+	return num_bytes;
+}
+
+uint32_t
+osmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx)
+{
+	cl_list_item_t *p_item;
+	cl_list_obj_t *p_obj;
+	void *p_list_mad;
+	uint32_t num_bytes, num_segs;
+
+	p_item = cl_qlist_tail(p_recv_ctx->p_rbuf);
+	p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+	p_list_mad = cl_qlist_obj(p_obj);
+
+	/* mad data sz */
+	num_segs = cl_qlist_count(p_recv_ctx->p_rbuf);
+	num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin);
+
+	if (0 != num_bytes) {
+		if (p_recv_ctx->is_sa_mad) {
+			/* sa mad hdr sz */
+			num_bytes += MAD_RMPP_HDR_SIZE;
+			num_bytes += (num_segs - 1) * IB_SA_DATA_SIZE;
+		} else {
+			/* mad hdr sz */
+			num_bytes += MAD_RMPP_HDR_SIZE;
+			num_bytes += (num_segs - 1) * MAD_RMPP_DATA_SIZE;
+		}
+	}
+
+	return num_bytes;
+}
+
+/* assuming that the last rmpp pkt arrived so that data member: total_bytes has the right value */
+ib_api_status_t
+osmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx,
+				       IN uint32_t size, IN void *p_arbt_mad)
+{
+	ib_api_status_t st = IB_SUCCESS;
+
+	CL_ASSERT(p_recv_ctx);
+
+	st = osmv_rmpp_sar_init(&p_recv_ctx->sar, p_arbt_mad, size,
+				p_recv_ctx->is_sa_mad);
+	if (st != IB_SUCCESS) {
+		return st;
+	}
+
+	st = osmv_rmpp_sar_reassemble_arbt_mad(&p_recv_ctx->sar,
+					       p_recv_ctx->p_rbuf);
+
+	osmv_rmpp_sar_done(&p_recv_ctx->sar);
+
+	return st;
+}
diff --git a/libvendor/osm_vendor_mlx_sa.c b/libvendor/osm_vendor_mlx_sa.c
new file mode 100644
index 0000000..0257f32
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_sa.c
@@ -0,0 +1,834 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_event.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);
+
+	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 */
+			if (ib_get_attr_size(p_sa_mad->attr_offset) == 0) {
+				query_res.result_cnt = 0;
+				osm_log(p_bind->p_log, OSM_LOG_DEBUG,
+					"__osmv_sa_mad_rcv_cb: Count = 0\n");
+			}
+			else {
+				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 = %zu / %u (%zu)\n",
+					query_res.result_cnt,
+					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
+					ib_get_attr_size(p_sa_mad->attr_offset),
+					(p_madw->mad_size - IB_SA_MAD_HDR_SIZE) %
+					ib_get_attr_size(p_sa_mad->attr_offset));
+			}
+#endif
+		}
+	}
+
+	query_res.query_type = p_query_req_copy->query_type;
+
+	p_query_req_copy->pfn_query_cb(&query_res);
+
+	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+		cl_event_signal(&p_bind->sync_event);
+
+Exit:
+
+	/* free the copied query request if found */
+	if (p_query_req_copy)
+		free(p_query_req_copy);
+
+	/* put back the request madw */
+	if (p_req_madw)
+		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
+
+	OSM_LOG_EXIT(p_bind->p_log);
+}
+
+/*****************************************************************************
+ ****************************************************************************/
+/*
+  Send Error Callback:
+
+  Only report the error and get rid of the mad wrapper
+*/
+void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
+{
+	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
+	osmv_query_req_t *p_query_req_copy = NULL;
+	osmv_query_res_t query_res;
+
+	OSM_LOG_ENTER(p_bind->p_log);
+
+	/* Obtain the sent context etc */
+	p_query_req_copy =
+	    (osmv_query_req_t *) (p_madw->context.arb_context.context1);
+
+	/* provide the context of the original request in the result */
+	query_res.query_context = p_query_req_copy->query_context;
+
+	query_res.p_result_madw = p_madw;
+
+	query_res.status = IB_TIMEOUT;
+	query_res.result_cnt = 0;
+	query_res.p_result_madw->status = IB_TIMEOUT;
+	p_madw->status = IB_TIMEOUT;
+	query_res.query_type = p_query_req_copy->query_type;
+
+	p_query_req_copy->pfn_query_cb(&query_res);
+
+	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+		cl_event_signal(&p_bind->sync_event);
+
+	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);
+
+	/* 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);
+
+	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);
+
+	/*
+	   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_ix = 0;
+	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);
+
+	/* 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;
+		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;
+}
+
+/*****************************************************************************
+ *****************************************************************************/
diff --git a/libvendor/osm_vendor_mlx_sar.c b/libvendor/osm_vendor_mlx_sar.c
new file mode 100644
index 0000000..5523284
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_sar.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <vendor/osm_vendor_mlx_sar.h>
+
+ib_api_status_t
+osmv_rmpp_sar_init(osmv_rmpp_sar_t * p_sar, void *p_arbt_mad,
+		   uint32_t mad_size, boolean_t is_sa_mad)
+{
+	CL_ASSERT(p_sar);
+	p_sar->p_arbt_mad = p_arbt_mad;
+	if (is_sa_mad) {
+		p_sar->data_len = mad_size - IB_SA_MAD_HDR_SIZE;
+		p_sar->hdr_sz = IB_SA_MAD_HDR_SIZE;
+		p_sar->data_sz = IB_SA_DATA_SIZE;
+	} else {
+		p_sar->data_len = mad_size - MAD_RMPP_HDR_SIZE;
+		p_sar->hdr_sz = MAD_RMPP_HDR_SIZE;
+		p_sar->data_sz = MAD_RMPP_DATA_SIZE;
+	}
+	return IB_SUCCESS;
+}
+
+void osmv_rmpp_sar_done(osmv_rmpp_sar_t * p_sar)
+{
+	p_sar->p_arbt_mad = NULL;
+}
+
+/* the big mad should be with mad header, rmpp header ( &sa hdr) space */
+ib_api_status_t
+osmv_rmpp_sar_get_mad_seg(IN osmv_rmpp_sar_t * p_sar,
+			  IN uint32_t seg_idx, OUT void *p_buf)
+{
+	void *p_seg;
+	uint32_t sz_left;
+	uint32_t num_segs;
+
+	CL_ASSERT(p_sar);
+
+	num_segs = p_sar->data_len / p_sar->data_sz;
+	if ((p_sar->data_len % p_sar->data_sz) > 0) {
+		num_segs++;
+	}
+
+	if ((seg_idx > num_segs) && (seg_idx != 1)) {
+		return IB_NOT_FOUND;
+	}
+
+	/* cleanup */
+	memset(p_buf, 0, MAD_BLOCK_SIZE);
+
+	/* attach header */
+	memcpy(p_buf, p_sar->p_arbt_mad, p_sar->hdr_sz);
+
+	/* fill data */
+	p_seg =
+	    (char *)p_sar->p_arbt_mad + p_sar->hdr_sz +
+	    ((seg_idx - 1) * p_sar->data_sz);
+	sz_left = p_sar->data_len - ((seg_idx - 1) * p_sar->data_sz);
+	if (sz_left > p_sar->data_sz)
+		memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg,
+		       p_sar->data_sz);
+	else
+		memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg, sz_left);
+
+	return IB_SUCCESS;
+}
+
+/* turns a list of mads to one big mad - including header */
+/* ALSO - deallocates the list                              */
+ib_api_status_t
+osmv_rmpp_sar_reassemble_arbt_mad(osmv_rmpp_sar_t * p_sar, cl_qlist_t * p_bufs)
+{
+	void *buf_tmp, *p_mad;
+	cl_list_item_t *p_item;
+	cl_list_obj_t *p_obj;
+	uint32_t space_left = p_sar->data_len + p_sar->hdr_sz;
+
+	CL_ASSERT(p_sar);
+	CL_ASSERT(FALSE == cl_is_qlist_empty(p_bufs));
+
+	/* attach header */
+	p_mad = p_sar->p_arbt_mad;
+	p_item = cl_qlist_head(p_bufs);
+	p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+	buf_tmp = cl_qlist_obj(p_obj);
+	memcpy(p_mad, buf_tmp, p_sar->hdr_sz);
+	p_mad = (char *)p_mad + p_sar->hdr_sz;
+	space_left -= p_sar->hdr_sz;
+
+	/* reassemble data */
+	while (FALSE == cl_is_qlist_empty(p_bufs)) {
+
+		p_item = cl_qlist_remove_head(p_bufs);
+		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
+		buf_tmp = cl_qlist_obj(p_obj);
+
+		if (FALSE == cl_is_qlist_empty(p_bufs)) {
+			memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz,
+			       p_sar->data_sz);
+			p_mad = (char *)p_mad + p_sar->data_sz;
+			space_left -= p_sar->data_sz;
+		} else {
+			/* the last mad on the list */
+			memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz,
+			       space_left);
+			p_mad = (char *)p_mad + space_left;
+		}
+
+		free(buf_tmp);
+		free(p_obj);
+	}
+
+	return IB_SUCCESS;
+}
diff --git a/libvendor/osm_vendor_mlx_sender.c b/libvendor/osm_vendor_mlx_sender.c
new file mode 100644
index 0000000..a0bdef8
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_sender.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <vendor/osm_vendor_mlx_sender.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <vendor/osm_pkt_randomizer.h>
+
+static ib_api_status_t
+__osmv_rmpp_send_segment(IN osm_bind_handle_t h_bind,
+			 IN osmv_txn_ctx_t * p_txn, IN uint32_t seg_num);
+
+/****d* OSM Vendor/osmv_simple_send_madw
+ * NAME
+ *   osmv_simple_send_madw
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 bytes).
+ *
+ *   If this MAD requires a response, set the timeout event.
+ *   The function call returns when the MAD's send completion is received.
+ *
+ */
+
+ib_api_status_t
+osmv_simple_send_madw(IN osm_bind_handle_t h_bind,
+		      IN osm_madw_t * const p_madw,
+		      IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry)
+{
+	ib_api_status_t ret;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_mad_addr_t *p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
+	uint8_t mad_buf[MAD_BLOCK_SIZE];
+	ib_mad_t *p_mad = (ib_mad_t *) mad_buf;
+	uint64_t key = 0;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	CL_ASSERT(p_madw->mad_size <= MAD_BLOCK_SIZE);
+
+	memset(p_mad, 0, MAD_BLOCK_SIZE);
+	memcpy(p_mad, osm_madw_get_mad_ptr(p_madw), p_madw->mad_size);
+
+	if (NULL != p_txn) {
+		/* Push a fake txn id to the MAD */
+		key = osmv_txn_get_key(p_txn);
+		p_mad->trans_id = cl_hton64(key);
+	}
+
+	/*
+	   Add call for packet drop randomizer.
+	   This is a testing feature. If run_randomizer flag is set to TRUE,
+	   the randomizer will be called, and randomally will drop
+	   a packet. This is used for simulating unstable fabric.
+	 */
+	if (p_bo->p_vendor->run_randomizer == TRUE) {
+		/* Try the randomizer */
+		if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
+						p_bo->p_vendor->
+						p_pkt_randomizer,
+						p_mad) == TRUE) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"The MAD will not be sent. \n");
+			ret = IB_SUCCESS;
+		} else {
+			ret =
+			    osmv_transport_mad_send(h_bind, p_mad, p_mad_addr);
+		}
+	} else {
+		ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr);
+	}
+
+	if ((IB_SUCCESS == ret) && (NULL != p_txn) && (!is_retry)) {
+		/* Set the timeout for receiving the response MAD */
+		ret = osmv_txn_set_timeout_ev(h_bind, key,
+					      p_bo->p_vendor->resp_timeout);
+	}
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return ret;
+}
+
+/***** OSM Vendor/osmv_rmpp_send_madw
+ * NAME
+ *   osmv_rmpp_send_madw
+ *
+ * DESCRIPTION
+ * Send a single message (MAD wrapper of arbitrary length).
+ *      Follow the RMPP semantics
+ *      (segmentation, send window, timeouts etc).
+ *
+ *      The function call returns either when the whole message
+ *      has been acknowledged, or upon error.
+ *
+ *  ASSUMPTIONS
+ *      The RMPP sender context is set up
+ */
+
+ib_api_status_t
+osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind,
+		    IN osm_madw_t * const p_madw,
+		    IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds)
+{
+	ib_api_status_t ret = IB_SUCCESS;
+	uint32_t i, total_segs;
+
+	osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
+	CL_ASSERT(total_segs >= 1);
+
+	/* In the double-sided transfer, wait for ACK 0 */
+
+	for (;;) {
+
+		if (p_send_ctx->window_first > total_segs) {
+
+			/* Every segment is acknowledged */
+			break;
+		}
+
+		/* Send the next burst. */
+		for (i = p_send_ctx->window_first; i <= p_send_ctx->window_last;
+		     i++) {
+
+			/* Send a segment and setup a timeout timer */
+			ret = __osmv_rmpp_send_segment(h_bind, p_txn, i);
+			if (IB_SUCCESS != ret) {
+				goto send_done;
+			}
+		}
+
+		/* Set the Response Timeout for the ACK on the last DATA segment */
+		ret = osmv_txn_set_timeout_ev(h_bind, osmv_txn_get_key(p_txn),
+					      p_bo->p_vendor->resp_timeout);
+		if (IB_SUCCESS != ret) {
+			goto send_done;
+		}
+
+		/* Going to sleep. Let the others access the transaction DB */
+		osmv_txn_unlock(p_bo);
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"RMPP Sender thread (madw=%p) going to sleep ...\n",
+			p_madw);
+
+		/* Await the next event to happen */
+		cl_event_wait_on(&p_send_ctx->event,
+				 EVENT_NO_TIMEOUT, TRUE /* interruptible */ );
+
+		/* Got a signal from the MAD dispatcher/timeout handler */
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"RMPP Sender thread (madw=%p) waking up on a signal ...\n",
+			p_madw);
+
+		/* Let's see what changed... Make this atomic - re-acquire the lock. */
+		osmv_txn_lock(p_bo);
+
+		if (TRUE == p_bo->is_closing) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"osmv_rmpp_send_madw: ERR 6601: "
+				"The bind handle %p is being closed. "
+				"Stopping the RMPP Send of MADW %p\n",
+				h_bind, p_madw);
+
+			ret = IB_TIMEOUT;
+			return IB_INTERRUPTED;
+		}
+
+		/* STOP? ABORT? TIMEOUT? */
+		if (IB_SUCCESS != p_send_ctx->status) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"osmv_rmpp_send_madw: ERR 6602: "
+				"An error (%s) happened during the RMPP send of %p. Bailing out.\n",
+				ib_get_err_str(p_send_ctx->status), p_madw);
+			ret = p_send_ctx->status;
+			goto send_done;
+		}
+	}
+
+	if (TRUE == is_rmpp_ds) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Double-sided RMPP - switching to be the receiver.\n");
+
+		ret = osmv_txn_init_rmpp_receiver(h_bind, p_txn, FALSE
+						  /*Send was initiated by me */
+						  );
+
+		if (IB_SUCCESS == ret) {
+			/* Send ACK on the 0 segment */
+			ret = __osmv_rmpp_send_segment(h_bind, p_txn, 0);
+		}
+	}
+
+send_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return ret;
+}
+
+/*
+ *  NAME                osmv_rmpp_send_ack
+ *
+ *  DESCRIPTION
+ *
+ */
+
+ib_api_status_t
+osmv_rmpp_send_ack(IN osm_bind_handle_t h_bind,
+		   IN const ib_mad_t * p_req_mad,
+		   IN uint32_t seg_num,
+		   IN uint32_t nwl, IN const osm_mad_addr_t * p_mad_addr)
+{
+	uint8_t resp_mad[MAD_BLOCK_SIZE];
+	ib_rmpp_mad_t *p_resp_mad = (ib_rmpp_mad_t *) resp_mad;
+
+#ifdef OSMV_RANDOM_DROP
+	if (TRUE == osmv_random_drop()) {
+		osm_log(((osmv_bind_obj_t *) h_bind)->p_vendor->p_log,
+			OSM_LOG_DEBUG,
+			"Error injection - dropping the RMPP ACK\n");
+		return IB_SUCCESS;
+	}
+#endif
+
+	memcpy(p_resp_mad, p_req_mad, MAD_BLOCK_SIZE);
+
+	p_resp_mad->common_hdr.method = osmv_invert_method(p_req_mad->method);
+	p_resp_mad->rmpp_type = IB_RMPP_TYPE_ACK;
+	p_resp_mad->seg_num = cl_hton32(seg_num);
+	p_resp_mad->paylen_newwin = cl_hton32(nwl);
+	p_resp_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+
+	return osmv_transport_mad_send(h_bind, p_resp_mad, p_mad_addr);
+}
+
+/*
+ *  NAME            osmv_rmpp_send_nak
+ *
+ *  DESCRIPTION     Send the RMPP ABORT or STOP packet
+ */
+
+ib_api_status_t
+osmv_rmpp_send_nak(IN osm_bind_handle_t h_bind,
+		   IN const ib_mad_t * p_req_mad,
+		   IN const osm_mad_addr_t * p_mad_addr,
+		   IN uint8_t nak_type, IN uint8_t status)
+{
+	uint8_t resp_mad[MAD_BLOCK_SIZE];
+	ib_rmpp_mad_t *p_resp_mad = (ib_rmpp_mad_t *) resp_mad;
+
+	memcpy(p_resp_mad, p_req_mad, MAD_BLOCK_SIZE);
+
+	p_resp_mad->common_hdr.method = osmv_invert_method(p_req_mad->method);
+	p_resp_mad->rmpp_type = nak_type;
+	p_resp_mad->rmpp_status = status;
+
+	return osmv_transport_mad_send(h_bind, p_resp_mad, p_mad_addr);
+}
+
+/*
+ *  NAME              __osmv_rmpp_send_segment
+ *
+ *  DESCRIPTION       Build a MAD for a specific segment and send it
+ */
+
+static ib_api_status_t
+__osmv_rmpp_send_segment(IN osm_bind_handle_t h_bind,
+			 IN osmv_txn_ctx_t * p_txn, IN uint32_t seg_num)
+{
+	ib_api_status_t ret;
+	osmv_rmpp_send_ctx_t *p_send_ctx;
+	uint8_t mad_buf[MAD_BLOCK_SIZE];
+	ib_mad_t *p_mad = (ib_mad_t *) mad_buf;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_mad_addr_t *p_mad_addr =
+	    osm_madw_get_mad_addr_ptr(osmv_txn_get_madw(p_txn));
+	uint32_t timeout = p_bo->p_vendor->resp_timeout;
+	uint64_t key;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+#ifdef OSMV_RANDOM_DROP
+	if (TRUE == osmv_random_drop()) {
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Error injection - simulating the RMPP segment drop\n");
+		return IB_SUCCESS;
+	}
+#endif
+
+	p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
+	key = osmv_txn_get_key(p_txn);
+
+	if (0 != seg_num) {
+		ret =
+		    osmv_rmpp_send_ctx_get_seg(p_send_ctx, seg_num, timeout,
+					       p_mad);
+		CL_ASSERT(IB_SUCCESS == ret);
+
+		/* Put the segment to the wire ! */
+		p_mad->trans_id = cl_hton64(key);
+
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Sending RMPP segment #%d, on-wire TID=0x%llX\n",
+			seg_num, p_mad->trans_id);
+
+		/*
+		   Add call for packet drop randomizer.
+		   This is a testing feature. If run_randomizer flag is set to TRUE,
+		   the randomizer will be called, and randomally will drop
+		   a packet. This is used for simulating unstable fabric.
+		 */
+		if (p_bo->p_vendor->run_randomizer == TRUE) {
+			/* Try the randomizer */
+			if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log,
+							p_bo->p_vendor->
+							p_pkt_randomizer,
+							p_mad) == TRUE) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+					"The MAD will not be sent. \n");
+				ret = IB_SUCCESS;
+			} else {
+				ret =
+				    osmv_transport_mad_send((osm_bind_handle_t)
+							    p_bo, p_mad,
+							    p_mad_addr);
+			}
+		} else {
+			ret =
+			    osmv_transport_mad_send((osm_bind_handle_t) p_bo,
+						    p_mad, p_mad_addr);
+		}
+	} else {
+		/* This is an ACK for double-sided handshake. Give it a special treatment. */
+
+		/* It doesn't really matter which data to put. Only the header matters. */
+		ret = osmv_rmpp_send_ctx_get_seg(p_send_ctx, 1, timeout, p_mad);
+		CL_ASSERT(IB_SUCCESS == ret);
+
+		p_mad->trans_id = cl_hton64(key);
+		ret =
+		    osmv_rmpp_send_ack((osm_bind_handle_t) p_bo, p_mad,
+				       0 /* segnum */ ,
+				       OSMV_RMPP_RECV_WIN /* NWL */ ,
+				       p_mad_addr);
+	}
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return ret;
+}
diff --git a/libvendor/osm_vendor_mlx_sim.c b/libvendor/osm_vendor_mlx_sim.c
new file mode 100644
index 0000000..c02c4de
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_sim.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*  AUTHOR                 Eitan Zahavi
+ *
+ *  DESCRIPTION
+ *     The lower-level MAD transport interface implementation
+ *     that allows sending a single MAD/receiving a callback
+ *     when a single MAD is received.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_dispatcher.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <complib/cl_thread.h>
+
+/* the simulator messages definition */
+#include <ibmgtsim/ibms_client_api.h>
+
+typedef struct _osmv_ibms_transport_mgr {
+	ibms_conn_handle_t conHdl;	/* the connection handle we talk to */
+	ibms_bind_msg_t filter;	/* the bind message defining the filtering */
+	cl_thread_t receiver;	/* the thread waiting for incomming messages */
+} osmv_ibms_transport_mgr_t;
+
+static void
+__osmv_ibms_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
+				 IN struct _ibms_mad_addr *p_ibms_addr,
+				 IN uint8_t is_smi,
+				 OUT osm_mad_addr_t * p_osm_addr);
+
+static void
+__osmv_ibms_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_osm_addr,
+				 IN uint8_t is_smi,
+				 OUT struct _ibms_mad_addr *p_ibms_addr);
+
+/* this is the callback function the "server" will call on incoming
+   messages */
+void __osmv_ibms_receiver_callback(void *p_ctx, ibms_mad_msg_t * p_mad)
+{
+	osm_mad_addr_t mad_addr;
+	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx;
+	ib_api_status_t status = IB_SUCCESS;
+
+	/* Make sure the p_bo object is still relevant */
+	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+		return;
+
+	{
+		OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+		/* some logging */
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"__osmv_ibms_receiver_callback: "
+			"MAD QPN:%d SLID:0x%04x class:0x%02x "
+			"method:0x%02x attr:0x%04x status:0x%04x "
+			"tid:0x%016" PRIx64 "\n",
+			p_mad->addr.dqpn,
+			cl_ntoh16(p_mad->addr.slid),
+			p_mad->header.mgmt_class,
+			p_mad->header.method,
+			cl_ntoh16(p_mad->header.attr_id),
+			cl_ntoh16(p_mad->header.status),
+			cl_ntoh64(p_mad->header.trans_id));
+
+		/* first arrange an address */
+		__osmv_ibms_mad_addr_to_osm_addr(p_bo->p_vendor,
+						 &p_mad->addr,
+						 (((ib_mad_t *) & p_mad->
+						   header)->mgmt_class ==
+						  IB_MCLASS_SUBN_LID)
+						 ||
+						 (((ib_mad_t *) & p_mad->
+						   header)->mgmt_class ==
+						  IB_MCLASS_SUBN_DIR),
+						 &mad_addr);
+
+		/* call the receiver callback */
+
+		status =
+		    osmv_dispatch_mad((osm_bind_handle_t) p_bo,
+				      (void *)&p_mad->header, &mad_addr);
+
+		OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	}
+}
+
+ib_api_status_t
+osm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend,
+				   IN char *hca_id,
+				   IN uint32_t port_num,
+				   OUT uint64_t * p_port_guid);
+
+/*
+ * NAME
+ *   osmv_transport_init
+ *
+ * DESCRIPTION
+ *   Setup the MAD transport infrastructure (filters, callbacks etc).
+ */
+
+ib_api_status_t
+osmv_transport_init(IN osm_bind_info_t * p_info,
+		    IN char hca_id[VENDOR_HCA_MAXNAMES],
+		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
+{
+	ibms_conn_handle_t conHdl;	/* the connection we talk to the simulator through */
+	osmv_ibms_transport_mgr_t *p_mgr =
+	    malloc(sizeof(osmv_ibms_transport_mgr_t));
+	int qpn;
+	int ibms_status;
+	uint64_t port_guid;
+
+	if (!p_mgr) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_mgr, 0, sizeof(osmv_ibms_transport_mgr_t));
+
+	/* create the client socket connected to the simulator */
+	/* also perform the "connect" message - such that we
+	   validate the target guid */
+	if (osm_vendor_get_guid_by_ca_and_port
+	    (p_bo->p_vendor, hca_id, p_bo->port_num, &port_guid)) {
+		return IB_INVALID_GUID;
+	}
+
+	conHdl =
+	    ibms_connect(port_guid, __osmv_ibms_receiver_callback,
+			 (void *)p_bo);
+	if (!conHdl) {
+		printf("fail to connect to the server.\n");
+		exit(1);
+	}
+
+	/*
+	 * Create the MAD filter on this file handle.
+	 */
+
+	p_mgr->filter.port = p_bo->port_num;
+	p_mgr->filter.only_input = 1;
+	p_mgr->filter.mask =
+	    IBMS_BIND_MASK_PORT |
+	    IBMS_BIND_MASK_INPUT | IBMS_BIND_MASK_QP | IBMS_BIND_MASK_CLASS;
+
+	switch (p_info->mad_class) {
+	case IB_MCLASS_SUBN_LID:
+	case IB_MCLASS_SUBN_DIR:
+		qpn = 0;
+		p_mgr->filter.qpn = qpn;
+		p_mgr->filter.mgt_class = IB_MCLASS_SUBN_LID;
+		ibms_status = ibms_bind(conHdl, &p_mgr->filter);
+		if (ibms_status) {
+			return IB_ERROR;
+		}
+
+		p_mgr->filter.mgt_class = IB_MCLASS_SUBN_DIR;
+		ibms_status = ibms_bind(conHdl, &p_mgr->filter);
+		if (ibms_status) {
+			return IB_ERROR;
+		}
+
+		break;
+
+	case IB_MCLASS_SUBN_ADM:
+	default:
+		qpn = 1;
+		p_mgr->filter.qpn = qpn;
+		p_mgr->filter.mgt_class = p_info->mad_class;
+		ibms_status = ibms_bind(conHdl, &p_mgr->filter);
+		if (ibms_status) {
+			return IB_ERROR;
+		}
+		break;
+	}
+
+	p_mgr->conHdl = conHdl;
+
+	p_bo->p_transp_mgr = p_mgr;
+
+	/* Initialize the magic_ptr to the pointer of the p_bo info.
+	   This will be used to signal when the object is being destroyed, so no
+	   real action will be done then. */
+	p_bo->magic_ptr = p_bo;
+
+	return IB_SUCCESS;
+}
+
+/*
+ * NAME
+ *   osmv_transport_send_mad
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 byte)
+ */
+
+ib_api_status_t
+osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
+			IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr)
+{
+
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	int ret;
+	ibms_mad_msg_t mad_msg;
+	ib_api_status_t status;
+
+	const ib_mad_t *p_mad_hdr = p_mad;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	memset(&mad_msg, 0, sizeof(mad_msg));
+
+	/* Make sure the p_bo object is still relevant */
+	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+		return IB_INVALID_CALLBACK;
+
+	/*
+	 * Copy the MAD over to the sent mad
+	 */
+	memcpy(&mad_msg.header, p_mad_hdr, MAD_BLOCK_SIZE);
+
+	/*
+	 * For all sends other than directed route SM MADs,
+	 * acquire an address vector for the destination.
+	 */
+	if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) {
+
+		__osmv_ibms_osm_addr_to_mad_addr(p_mad_addr,
+						 p_mad_hdr->mgmt_class ==
+						 IB_MCLASS_SUBN_LID,
+						 &mad_msg.addr);
+	} else {
+		/* is a directed route - we need to construct a permissive address */
+		/* we do not need port number since it is part of the mad_hndl */
+		mad_msg.addr.dlid = IB_LID_PERMISSIVE;
+		mad_msg.addr.slid = IB_LID_PERMISSIVE;
+		mad_msg.addr.sqpn = 0;
+		mad_msg.addr.dqpn = 0;
+	}
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"osmv_transport_mad_send: "
+		"Sending QPN:%d DLID:0x%04x class:0x%02x "
+		"method:0x%02x attr:0x%04x status:0x%04x "
+		"tid:0x%016" PRIx64 "\n",
+		mad_msg.addr.dqpn,
+		cl_ntoh16(mad_msg.addr.dlid),
+		mad_msg.header.mgmt_class,
+		mad_msg.header.method,
+		cl_ntoh16(mad_msg.header.attr_id),
+		cl_ntoh16(mad_msg.header.status),
+		cl_ntoh64(mad_msg.header.trans_id)
+	    );
+
+	/* send it */
+	ret =
+	    ibms_send(((osmv_ibms_transport_mgr_t *) (p_bo->p_transp_mgr))->
+		      conHdl, &mad_msg);
+	if (ret) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osmv_transport_mad_send: ERR 5304: "
+			"Error sending mad (%d).\n", ret);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+void osmv_transport_done(IN const osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osmv_ibms_transport_mgr_t *p_tpot_mgr =
+	    (osmv_ibms_transport_mgr_t *) (p_bo->p_transp_mgr);
+
+	CL_ASSERT(p_bo);
+
+	/* First of all - zero out the magic_ptr, so if a callback is called -
+	   it'll know that we are currently closing down, and will not handle the
+	   mad. */
+	p_bo->magic_ptr = 0;
+	/* usleep(3000000); */
+
+	ibms_disconnect(p_tpot_mgr->conHdl);
+
+	/* seems the only way to abort a blocking read is to make it read something */
+	free(p_tpot_mgr);
+}
+
+static void
+__osmv_ibms_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_osm_addr,
+				 IN uint8_t is_smi,
+				 OUT struct _ibms_mad_addr *p_ibms_addr)
+{
+
+	/* For global destination or Multicast address: */
+	p_ibms_addr->dlid = cl_ntoh16(p_osm_addr->dest_lid);
+	p_ibms_addr->sl = p_osm_addr->addr_type.gsi.service_level;
+	if (is_smi) {
+		p_ibms_addr->sqpn = 0;
+		p_ibms_addr->dqpn = 0;
+	} else {
+		p_ibms_addr->sqpn = 1;
+		p_ibms_addr->dqpn =
+		    cl_ntoh32(p_osm_addr->addr_type.gsi.remote_qp);
+	}
+	/*
+	   HACK we limit to the first PKey Index assuming it will
+	   always be the default PKey
+	 */
+	p_ibms_addr->pkey_index = 0;
+}
+
+static void
+__osmv_ibms_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
+				 IN struct _ibms_mad_addr *p_ibms_addr,
+				 IN uint8_t is_smi,
+				 OUT osm_mad_addr_t * p_osm_addr)
+{
+	memset(p_osm_addr, 0, sizeof(osm_mad_addr_t));
+	p_osm_addr->dest_lid = cl_hton16(p_ibms_addr->slid);
+	p_osm_addr->static_rate = 0;
+	p_osm_addr->path_bits = 0;
+	if (is_smi) {
+		/* SMI */
+		p_osm_addr->addr_type.smi.source_lid =
+		    cl_hton16(p_ibms_addr->slid);
+		p_osm_addr->addr_type.smi.port_num = 1;	/* TODO add if required p_ibms_addr->port; */
+	} else {
+		/* GSI */
+		p_osm_addr->addr_type.gsi.remote_qp =
+		    cl_ntoh32(p_ibms_addr->sqpn);
+		p_osm_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+		p_osm_addr->addr_type.gsi.pkey_ix = p_ibms_addr->pkey_index;
+		p_osm_addr->addr_type.gsi.service_level = p_ibms_addr->sl;
+
+		p_osm_addr->addr_type.gsi.global_route = FALSE;
+		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
+		/*
+		   if (p_osm_addr->addr_type.gsi.global_route)
+		   {
+		   p_osm_addr->addr_type.gsi.grh_info.ver_class_flow =
+		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
+		   p_rcv_desc->grh.traffic_class,
+		   p_rcv_desc->grh.flow_label);
+		   p_osm_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
+		   memcpy(&p_osm_addr->addr_type.gsi.grh_info.src_gid.raw,
+		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
+		   memcpy(&p_osm_addr->addr_type.gsi.grh_info.dest_gid.raw,
+		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
+		   }
+		 */
+	}
+}
+
+/*
+ *  NAME            osm_vendor_set_sm
+ *
+ *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit
+ *                  according to the value given (TRUE or FALSE).
+ */
+
+void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	int ret;
+	ibms_cap_msg_t cap_msg;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	cap_msg.mask = IB_PORT_CAP_IS_SM;
+	if (is_sm_val)
+		cap_msg.capabilities = IB_PORT_CAP_IS_SM;
+	else
+		cap_msg.capabilities = 0;
+
+	ret = ibms_set_cap(((osmv_ibms_transport_mgr_t *) (p_bo->
+							   p_transp_mgr))->
+			   conHdl, &cap_msg);
+
+	if (ret) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_set_sm: ERR 5312: "
+			"Unable set 'IS_SM' bit to:%u in port attributes.\n",
+			is_sm_val);
+	}
+	OSM_LOG_EXIT(p_vend->p_log);
+}
diff --git a/libvendor/osm_vendor_mlx_ts.c b/libvendor/osm_vendor_mlx_ts.c
new file mode 100644
index 0000000..d7ab3b3
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_ts.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*  AUTHOR                 Edward Bortnikov
+ *
+ *  DESCRIPTION
+ *     The lower-level MAD transport interface implementation
+ *     that allows sending a single MAD/receiving a callback
+ *     when a single MAD is received.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_mlx_transport.h>
+#include <vendor/osm_vendor_mlx_dispatcher.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <vendor/osm_ts_useraccess.h>
+
+typedef struct _osmv_TOPSPIN_transport_mgr_ {
+	int device_fd;
+	osm_ts_user_mad_filter filter;
+	cl_thread_t receiver;
+} osmv_TOPSPIN_transport_mgr_t;
+
+static void
+__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
+				    IN struct ib_mad *p_mad,
+				    IN uint8_t is_smi,
+				    OUT osm_mad_addr_t * p_mad_addr);
+
+static void
+__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
+				    IN uint8_t is_smi,
+				    OUT struct ib_mad *p_mad);
+
+void __osmv_TOPSPIN_receiver_thr(void *p_ctx)
+{
+	int ts_ret_code;
+	struct ib_mad mad;
+	osm_mad_addr_t mad_addr;
+	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	/* Make sure the p_bo object is still relevant */
+	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+		return;
+
+	/* we set the type of cancelation for this thread */
+	/* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */
+
+	while (1) {
+		/* Make sure the p_bo object is still relevant */
+		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+			return;
+
+		/* we read one mad at a time and pass it to the read callback function */
+		ts_ret_code =
+		    read(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->
+							    p_transp_mgr))->
+			 device_fd, &mad, sizeof(mad));
+		/* Make sure the p_bo object is still relevant */
+		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+			return;
+
+		if (ts_ret_code != sizeof(mad)) {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_TOPSPIN_receiver_thr: ERR 6803: "
+				"error with read, bytes = %d, errno = %d\n",
+				ts_ret_code, errno);
+			break;
+		} else {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"__osmv_TOPSPIN_receiver_thr: "
+				"MAD QPN:%d SLID:0x%04x class:0x%02x "
+				"method:0x%02x attr:0x%04x status:0x%04x "
+				"tid:0x%016" PRIx64 "\n",
+				mad.dqpn,
+				cl_ntoh16(mad.slid),
+				mad.mgmt_class,
+				mad.r_method,
+				cl_ntoh16(mad.attribute_id),
+				cl_ntoh16(mad.status),
+				cl_ntoh64(mad.transaction_id));
+
+			/* first arrange an address */
+			__osmv_TOPSPIN_mad_addr_to_osm_addr(p_bo->p_vendor,
+							    &mad,
+							    (((ib_mad_t *) &
+							      mad)->
+							     mgmt_class ==
+							     IB_MCLASS_SUBN_LID)
+							    ||
+							    (((ib_mad_t *) &
+							      mad)->
+							     mgmt_class ==
+							     IB_MCLASS_SUBN_DIR),
+							    &mad_addr);
+
+			/* call the receiver callback */
+
+			status =
+			    osmv_dispatch_mad((osm_bind_handle_t) p_bo,
+					      (void *)&mad, &mad_addr);
+
+			/* Make sure the p_bo object is still relevant */
+			if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+				return;
+
+			if (IB_INTERRUPTED == status) {
+
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+					"__osmv_TOPSPIN_receiver_thr: "
+					"The bind handle %p is being closed. "
+					"Breaking the loop.\n", p_bo);
+				break;
+			}
+		}
+	}
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+/*
+ * NAME
+ *   osmv_transport_init
+ *
+ * DESCRIPTION
+ *   Setup the MAD transport infrastructure (filters, callbacks etc).
+ */
+
+ib_api_status_t
+osmv_transport_init(IN osm_bind_info_t * p_info,
+		    IN char hca_id[VENDOR_HCA_MAXNAMES],
+		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
+{
+	cl_status_t cl_st;
+	char device_file[16];
+	int device_fd;
+	int ts_ioctl_ret;
+	osmv_TOPSPIN_transport_mgr_t *p_mgr =
+	    malloc(sizeof(osmv_TOPSPIN_transport_mgr_t));
+	int qpn;
+
+	if (!p_mgr) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_mgr, 0, sizeof(osmv_TOPSPIN_transport_mgr_t));
+
+	/* open TopSpin file device */
+	/* HACK: assume last char in hostid is the HCA index */
+	sprintf(device_file, "/dev/ts_ua%u", hca_idx);
+	device_fd = open(device_file, O_RDWR);
+	if (device_fd < 0) {
+		fprintf(stderr, "Fatal: Fail to open the file:%s err:%d\n",
+			device_file, errno);
+		return IB_ERROR;
+	}
+
+	/*
+	 * Create the MAD filter on this file handle.
+	 */
+
+	p_mgr->filter.port = p_bo->port_num;
+	p_mgr->filter.direction = TS_IB_MAD_DIRECTION_IN;
+	p_mgr->filter.mask =
+	    TS_IB_MAD_FILTER_DIRECTION |
+	    TS_IB_MAD_FILTER_PORT |
+	    TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
+
+	switch (p_info->mad_class) {
+	case IB_MCLASS_SUBN_LID:
+	case IB_MCLASS_SUBN_DIR:
+		qpn = 0;
+		p_mgr->filter.qpn = qpn;
+		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_LID;
+		ts_ioctl_ret =
+		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
+		if (ts_ioctl_ret < 0) {
+			return IB_ERROR;
+		}
+
+		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_DIR;
+		ts_ioctl_ret =
+		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
+		if (ts_ioctl_ret < 0) {
+			return IB_ERROR;
+		}
+
+		break;
+
+	case IB_MCLASS_SUBN_ADM:
+	default:
+		qpn = 1;
+		p_mgr->filter.qpn = qpn;
+		p_mgr->filter.mgmt_class = p_info->mad_class;
+		ts_ioctl_ret =
+		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
+		if (ts_ioctl_ret < 0) {
+			return IB_ERROR;
+		}
+		break;
+	}
+
+	p_mgr->device_fd = device_fd;
+
+	p_bo->p_transp_mgr = p_mgr;
+
+	/* Initialize the magic_ptr to the pointer of the p_bo info.
+	   This will be used to signal when the object is being destroyed, so no
+	   real action will be done then. */
+	p_bo->magic_ptr = p_bo;
+
+	/* init receiver thread */
+	cl_st =
+	    cl_thread_init(&p_mgr->receiver, __osmv_TOPSPIN_receiver_thr,
+			   (void *)p_bo, "osmv TOPSPIN rcv thr");
+
+	return (ib_api_status_t) cl_st;
+}
+
+/*
+ * NAME
+ *   osmv_transport_send_mad
+ *
+ * DESCRIPTION
+ *   Send a single MAD (256 byte)
+ */
+
+ib_api_status_t
+osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
+			IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr)
+{
+
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	struct ib_mad ts_mad;
+	int ret;
+	ib_api_status_t status;
+
+	const ib_mad_t *p_mad_hdr = p_mad;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	memset(&ts_mad, 0, sizeof(ts_mad));
+
+	/* Make sure the p_bo object is still relevant */
+	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
+		return IB_INVALID_CALLBACK;
+
+	/*
+	 * Copy the MAD over to the sent mad
+	 */
+	memcpy(&ts_mad, p_mad_hdr, MAD_BLOCK_SIZE);
+
+	/*
+	 * For all sends other than directed route SM MADs,
+	 * acquire an address vector for the destination.
+	 */
+	if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) {
+
+		__osmv_TOPSPIN_osm_addr_to_mad_addr(p_mad_addr,
+						    p_mad_hdr->mgmt_class ==
+						    IB_MCLASS_SUBN_LID,
+						    &ts_mad);
+	} else {
+		/* is a directed route - we need to construct a permissive address */
+		/* we do not need port number since it is part of the mad_hndl */
+		ts_mad.dlid = IB_LID_PERMISSIVE;
+		ts_mad.slid = IB_LID_PERMISSIVE;
+		ts_mad.sqpn = 0;
+		ts_mad.dqpn = 0;
+	}
+
+	ts_mad.port = p_bo->port_num;
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"osmv_transport_mad_send: "
+		"Sending QPN:%d DLID:0x%04x class:0x%02x "
+		"method:0x%02x attr:0x%04x status:0x%04x "
+		"tid:0x%016" PRIx64 "\n",
+		ts_mad.dqpn,
+		cl_ntoh16(ts_mad.dlid),
+		ts_mad.mgmt_class,
+		ts_mad.r_method,
+		cl_ntoh16(ts_mad.attribute_id),
+		cl_ntoh16(ts_mad.status), cl_ntoh64(ts_mad.transaction_id)
+	    );
+
+	/* send it */
+	ret =
+	    write(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->
+		  device_fd, &ts_mad, sizeof(ts_mad));
+
+	if (ret != sizeof(ts_mad)) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osmv_transport_mad_send: ERR 6804: "
+			"Error sending mad (%d).\n", ret);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	OSM_LOG_EXIT(p_vend->p_log);
+	return (status);
+}
+
+/*
+   register a new mad type to the opened device file
+   and send a mad through - the main idea is to make
+   the filter catch it such that the read unblocks
+*/
+void __osm_transport_gen_dummy_mad(osmv_bind_obj_t * p_bo)
+{
+	struct ib_mad ts_mad;
+	osmv_TOPSPIN_transport_mgr_t *p_mgr =
+	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
+	struct ib_get_port_info_ioctl port_data;
+	int ts_ioctl_ret;
+
+	/* prepare the mad fields following the stored filter on the bind */
+	memset(&ts_mad, 0, sizeof(ts_mad));
+	ts_mad.format_version = 1;
+	ts_mad.mgmt_class = p_mgr->filter.mgmt_class;
+	ts_mad.attribute_id = 0x2;
+	ts_mad.class_version = 1;
+	ts_mad.r_method = cl_ntoh16(0x2);
+	ts_mad.port = p_bo->port_num;
+	ts_mad.sqpn = p_mgr->filter.qpn;
+	ts_mad.dqpn = p_mgr->filter.qpn;
+	ts_mad.slid = 0xffff;
+	/* we must send to our local lid ... */
+	port_data.port = p_bo->port_num;
+	ts_ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCGPORTINFO, &port_data);
+	ts_mad.dlid = port_data.port_info.lid;
+	ts_mad.transaction_id = 0x9999;
+	write(p_mgr->device_fd, &ts_mad, sizeof(ts_mad));
+}
+
+void osmv_transport_done(IN const osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osmv_TOPSPIN_transport_mgr_t *p_tpot_mgr =
+	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
+
+	CL_ASSERT(p_bo);
+
+	/* First of all - zero out the magic_ptr, so if a callback is called -
+	   it'll know that we are currently closing down, and will not handle the
+	   mad. */
+	p_bo->magic_ptr = 0;
+	/* usleep(3000000); */
+
+	/* seems the only way to abort a blocking read is to make it read something */
+	__osm_transport_gen_dummy_mad(p_bo);
+	cl_thread_destroy(&(p_tpot_mgr->receiver));
+	free(p_tpot_mgr);
+}
+
+static void
+__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
+				    IN uint8_t is_smi, OUT struct ib_mad *p_mad)
+{
+
+	/* For global destination or Multicast address: */
+	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
+	p_mad->sl = p_mad_addr->addr_type.gsi.service_level;
+	if (is_smi) {
+		p_mad->sqpn = 0;
+		p_mad->dqpn = 0;
+	} else {
+		p_mad->sqpn = 1;
+		p_mad->dqpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp);
+	}
+	/*
+	   HACK we limit to the first PKey Index assuming it will
+	   always be the default PKey
+	 */
+	p_mad->pkey_index = 0;
+}
+
+static void
+__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
+				    IN struct ib_mad *p_mad,
+				    IN uint8_t is_smi,
+				    OUT osm_mad_addr_t * p_mad_addr)
+{
+	p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
+	p_mad_addr->static_rate = 0;
+	p_mad_addr->path_bits = 0;
+	if (is_smi) {
+		/* SMI */
+		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
+		p_mad_addr->addr_type.smi.port_num = p_mad->port;
+	} else {
+		/* GSI */
+		p_mad_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_mad->sqpn);
+		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+		/*  There is a TAVOR limitation that only one P_KEY is supported per */
+		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
+		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
+		p_mad_addr->addr_type.gsi.service_level = p_mad->sl;
+
+		p_mad_addr->addr_type.gsi.global_route = FALSE;
+		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
+		/*
+		   if (p_mad_addr->addr_type.gsi.global_route)
+		   {
+		   p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
+		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
+		   p_rcv_desc->grh.traffic_class,
+		   p_rcv_desc->grh.flow_label);
+		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
+		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
+		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
+		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
+		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
+		   }
+		 */
+	}
+}
+
+/*
+ *  NAME            osm_vendor_set_sm
+ *
+ *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit
+ *                  according to the value given (TRUE or FALSE).
+ */
+#if (defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_TS))
+
+void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	osm_vendor_t const *p_vend = p_bo->p_vendor;
+	int ts_ioctl_ret;
+	int device_fd =
+	    ((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->device_fd;
+	struct ib_set_port_info_ioctl set_port_data;
+
+	OSM_LOG_ENTER(p_vend->p_log);
+
+	memset(&set_port_data, 0, sizeof(set_port_data));
+
+	set_port_data.port = p_bo->port_num;
+	set_port_data.port_info.valid_fields = IB_PORT_IS_SM;
+	set_port_data.port_info.is_sm = is_sm_val;
+	ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSPORTINFO, &set_port_data);
+	if (ts_ioctl_ret < 0) {
+		osm_log(p_vend->p_log, OSM_LOG_ERROR,
+			"osm_vendor_set_sm: ERR 6805: "
+			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
+			is_sm_val, ts_ioctl_ret);
+	}
+
+	OSM_LOG_EXIT(p_vend->p_log);
+}
+
+#endif
diff --git a/libvendor/osm_vendor_mlx_txn.c b/libvendor/osm_vendor_mlx_txn.c
new file mode 100644
index 0000000..a2da75a
--- /dev/null
+++ b/libvendor/osm_vendor_mlx_txn.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+
+#include <vendor/osm_vendor_mlx.h>
+#include <vendor/osm_vendor_mlx_defs.h>
+#include <vendor/osm_vendor_mlx_txn.h>
+#include <vendor/osm_vendor_mlx_svc.h>
+#include <vendor/osm_vendor_mlx_sender.h>
+
+static ib_api_status_t
+__osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
+		     IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
+
+static ib_api_status_t
+__osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
+			 IN osmv_txn_ctx_t * p_txn, IN uint64_t key);
+
+static ib_api_status_t
+__osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
+			 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn);
+
+static void __osmv_txn_all_done(osm_bind_handle_t h_bind);
+
+static uint64_t
+__osmv_txn_timeout_cb(IN uint64_t key,
+		      IN uint32_t num_regs, IN void *cb_context);
+
+ib_api_status_t
+osmv_txn_init(IN osm_bind_handle_t h_bind,
+	      IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	ib_api_status_t st;
+	osmv_txn_ctx_t *p_txn;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	CL_ASSERT(NULL != h_bind && NULL != pp_txn);
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"Starting transaction 0x%llX (key=0x%llX)\n", tid, key);
+
+	p_txn = malloc(sizeof(osmv_txn_ctx_t));
+	if (!p_txn) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_txn, 0, sizeof(osmv_txn_ctx_t));
+	p_txn->p_log = p_bo->txn_mgr.p_log;
+	p_txn->tid = tid;
+	p_txn->key = key;
+	p_txn->p_madw = NULL;
+	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_NONE;
+
+	/* insert into transaction manager DB */
+	st = __osmv_txnmgr_insert_txn(&p_bo->txn_mgr, p_txn, key);
+	if (IB_SUCCESS != st) {
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+			"osmv_txn_init: ERR 6703: "
+			"Failed to insert to transaction 0x%llX (key=0x%llX) to manager DB\n",
+			tid, key);
+		goto insert_txn_failed;
+	}
+
+	*pp_txn = p_txn;
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return IB_SUCCESS;
+
+insert_txn_failed:
+	free(p_txn);
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return st;
+}
+
+ib_api_status_t
+osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,
+			  IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw)
+{
+	ib_api_status_t st;
+
+	CL_ASSERT(p_txn);
+
+	/* Double-Sided RMPP Direction Switch */
+	osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));
+
+	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER;
+	p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t));
+
+	if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0,
+	       sizeof(osmv_rmpp_send_ctx_t));
+
+	st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx,
+				     (void *)p_madw->p_mad,
+				     p_madw->mad_size, p_txn->p_log);
+	return st;
+}
+
+ib_api_status_t
+osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,
+			    IN osmv_txn_ctx_t * p_txn,
+			    IN boolean_t is_init_by_peer)
+{
+	ib_api_status_t st;
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	uint64_t key = osmv_txn_get_key(p_txn);
+
+	CL_ASSERT(p_txn);
+
+	/* Double-Sided RMPP Direction Switch */
+	osmv_txn_remove_timeout_ev(h_bind, key);
+
+	/* Set the Transaction Timeout value */
+	st = osmv_txn_set_timeout_ev(h_bind, key,
+				     p_bo->p_vendor->ttime_timeout);
+	if (IB_SUCCESS != st) {
+
+		return st;
+	}
+
+	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER;
+	p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer;
+
+	p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t));
+
+	if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) {
+
+		osmv_txn_remove_timeout_ev(h_bind, key);
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0,
+	       sizeof(osmv_rmpp_recv_ctx_t));
+
+	st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx,
+				     p_txn->p_log);
+
+	return st;
+}
+
+/*
+ * NAME
+ *  osmv_txn_set_timeout_ev
+ *
+ * DESCRIPTION
+ *
+ * SEE ALSO
+ *
+ */
+ib_api_status_t
+osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind,
+			IN uint64_t key, IN uint64_t msec)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	cl_event_wheel_t *p_event_wheel = p_bo->txn_mgr.p_event_wheel;
+	cl_status_t status;
+
+	status = cl_event_wheel_reg(p_event_wheel, key, cl_get_time_stamp() + 1000 * msec,	/* TTL */
+				    __osmv_txn_timeout_cb,
+				    p_bo /* The context */ );
+
+	return (ib_api_status_t) status;
+}
+
+/*
+ * NAME
+ *  osmv_txn_remove_timeout_ev
+ *
+ * DESCRIPTION
+
+ * SEE ALSO
+ *
+ */
+void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key)
+{
+	cl_event_wheel_t *p_event_wheel =
+	    ((osmv_bind_obj_t *) h_bind)->txn_mgr.p_event_wheel;
+	cl_event_wheel_unreg(p_event_wheel, key);
+}
+
+void
+osmv_txn_done(IN osm_bind_handle_t h_bind,
+	      IN uint64_t key, IN boolean_t is_in_cb)
+{
+	osmv_txn_ctx_t *p_ctx;
+	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	CL_ASSERT(h_bind);
+
+	/* Cancel the (single) timeout possibly outstanding for this txn
+	 * Don't do this if you are in the callback context, for 2 reasons:
+	 * (1) The event wheel will remove the context itself.
+	 * (2) If we try to, there is a deadlock in the event wheel
+	 */
+	if (FALSE == is_in_cb) {
+		osmv_txn_remove_timeout_ev(h_bind, key);
+	}
+
+	/* Remove from DB */
+	if (IB_NOT_FOUND ==
+	    __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) {
+		return;
+	}
+
+	/* Destroy the transaction's RMPP contexts
+	 * (can be more than one in the case of double sided transfer)
+	 */
+
+	if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) {
+		osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx);
+	}
+
+	if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) {
+		osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx);
+	}
+
+	free(p_ctx);
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+ib_api_status_t
+osmv_txn_lookup(IN osm_bind_handle_t h_bind,
+		IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	return __osmv_txnmgr_lookup(&(((osmv_bind_obj_t *) h_bind)->txn_mgr),
+				    key, pp_txn);
+}
+
+void osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	cl_map_item_t *p_item;
+	cl_map_obj_t *p_obj;
+	osmv_txn_ctx_t *p_txn;
+	osmv_rmpp_send_ctx_t *p_send_ctx;
+	cl_qmap_t *p_map = p_bo->txn_mgr.p_txn_map;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	while (FALSE == cl_is_qmap_empty(p_map)) {
+
+		p_item = cl_qmap_head(p_map);
+		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
+		p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
+		p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
+
+		if (NULL != p_send_ctx) {
+
+			p_send_ctx->status = IB_INTERRUPTED;
+
+			/* Wake up the sender thread to let it break out */
+			cl_event_signal(&p_send_ctx->event);
+		}
+
+		cl_qmap_remove_item(p_map, p_item);
+	}
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+ib_api_status_t
+osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr,
+		 IN osm_log_t * p_log, IN cl_spinlock_t * p_lock)
+{
+	cl_status_t cl_st = CL_SUCCESS;
+
+	p_tx_mgr->p_event_wheel = malloc(sizeof(cl_event_wheel_t));
+	if (!p_tx_mgr->p_event_wheel) {
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_tx_mgr->p_event_wheel, 0, sizeof(cl_event_wheel_t));
+
+	cl_event_wheel_construct(p_tx_mgr->p_event_wheel);
+
+	/* NOTE! We are using an extended constructor.
+	 * We tell the Event Wheel run in a non-protected manner in the reg/unreg calls,
+	 * and acquire an external lock in the asynchronous callback.
+	 */
+	cl_st = cl_event_wheel_init_ex(p_tx_mgr->p_event_wheel, p_lock);
+	if (cl_st != CL_SUCCESS) {
+		free(p_tx_mgr->p_event_wheel);
+		return (ib_api_status_t) cl_st;
+	}
+
+	p_tx_mgr->p_txn_map = malloc(sizeof(cl_qmap_t));
+	if (!p_tx_mgr->p_txn_map) {
+		cl_event_wheel_destroy(p_tx_mgr->p_event_wheel);
+		free(p_tx_mgr->p_event_wheel);
+		return IB_INSUFFICIENT_MEMORY;
+	}
+
+	memset(p_tx_mgr->p_txn_map, 0, sizeof(cl_qmap_t));
+
+	cl_qmap_init(p_tx_mgr->p_txn_map);
+	p_tx_mgr->p_log = p_log;
+
+	return cl_st;
+}
+
+void osmv_txnmgr_done(IN osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	__osmv_txn_all_done(h_bind);
+	free(p_bo->txn_mgr.p_txn_map);
+
+	cl_event_wheel_destroy(p_bo->txn_mgr.p_event_wheel);
+	free(p_bo->txn_mgr.p_event_wheel);
+}
+
+ib_api_status_t
+__osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr,
+		     IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	cl_map_item_t *p_item;
+	cl_map_obj_t *p_obj;
+
+	uint64_t tmp_key;
+
+	OSM_LOG_ENTER(p_tx_mgr->p_log);
+
+	CL_ASSERT(p_tx_mgr);
+	CL_ASSERT(pp_txn);
+
+	osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
+		"__osmv_txnmgr_lookup: "
+		"Looking for key: 0x%llX in map ptr:%p\n", key,
+		p_tx_mgr->p_txn_map);
+
+	p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
+	while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
+		tmp_key = cl_qmap_key(p_item);
+		osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
+			"__osmv_txnmgr_lookup: "
+			"Found key 0x%llX \n", tmp_key);
+		p_item = cl_qmap_next(p_item);
+	}
+
+	p_item = cl_qmap_get(p_tx_mgr->p_txn_map, key);
+	if (cl_qmap_end(p_tx_mgr->p_txn_map) == p_item) {
+		status = IB_NOT_FOUND;
+	} else {
+		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
+		*pp_txn = cl_qmap_obj(p_obj);
+	}
+
+	OSM_LOG_EXIT(p_tx_mgr->p_log);
+	return status;
+}
+
+ib_api_status_t
+__osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr,
+			 IN osmv_txn_ctx_t * p_txn, IN uint64_t key)
+{
+	cl_map_obj_t *p_obj = NULL;
+	cl_map_item_t *p_item;
+	uint64_t tmp_key;
+
+	CL_ASSERT(p_tx_mgr);
+	CL_ASSERT(p_txn);
+
+	key = osmv_txn_get_key(p_txn);
+	p_obj = malloc(sizeof(cl_map_obj_t));
+	if (NULL == p_obj)
+		return IB_INSUFFICIENT_MEMORY;
+
+	osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
+		"__osmv_txnmgr_insert_txn: "
+		"Inserting key: 0x%llX to map ptr:%p\n", key,
+		p_tx_mgr->p_txn_map);
+
+	memset(p_obj, 0, sizeof(cl_map_obj_t));
+
+	cl_qmap_set_obj(p_obj, p_txn);
+	/* assuming lookup with this key was made and the result was IB_NOT_FOUND */
+	cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item);
+
+	p_item = cl_qmap_head(p_tx_mgr->p_txn_map);
+	while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) {
+		tmp_key = cl_qmap_key(p_item);
+		osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG,
+			"__osmv_txnmgr_insert_txn: "
+			"Found key 0x%llX \n", tmp_key);
+		p_item = cl_qmap_next(p_item);
+	}
+
+	return IB_SUCCESS;
+}
+
+ib_api_status_t
+__osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr,
+			 IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn)
+{
+	cl_map_obj_t *p_obj;
+	cl_map_item_t *p_item;
+
+	OSM_LOG_ENTER(p_tx_mgr->p_log);
+
+	CL_ASSERT(p_tx_mgr);
+	CL_ASSERT(pp_txn);
+
+	p_item = cl_qmap_remove(p_tx_mgr->p_txn_map, key);
+
+	if (p_item == cl_qmap_end(p_tx_mgr->p_txn_map)) {
+
+		osm_log(p_tx_mgr->p_log, OSM_LOG_ERROR,
+			"__osmv_txnmgr_remove_txn: ERR 6701: "
+			"Could not remove the transaction 0x%llX - "
+			"something is really wrong!\n", key);
+		OSM_LOG_EXIT(p_tx_mgr->p_log);
+		return IB_NOT_FOUND;
+	}
+
+	p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
+	*pp_txn = cl_qmap_obj(p_obj);
+
+	free(p_obj);
+
+	OSM_LOG_EXIT(p_tx_mgr->p_log);
+	return IB_SUCCESS;
+}
+
+void __osmv_txn_all_done(osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	cl_map_item_t *p_item;
+	cl_map_obj_t *p_obj;
+	osmv_txn_ctx_t *p_txn;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
+	while (p_item != cl_qmap_end(p_bo->txn_mgr.p_txn_map)) {
+
+		p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item);
+		p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj);
+		osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
+		free(p_obj);
+		/* assuming osmv_txn_done has removed the txn from the map */
+		p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map);
+	}
+
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+}
+
+/******************************************************************************/
+
+void osmv_txn_lock(IN osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"--> Acquiring lock %p on bind handle %p\n", &p_bo->lock, p_bo);
+
+	cl_spinlock_acquire(&p_bo->lock);
+
+	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+		"--> Acquired lock %p on bind handle %p\n", &p_bo->lock, p_bo);
+}
+
+void osmv_txn_unlock(IN osm_bind_handle_t h_bind)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
+	cl_spinlock_t *p_lock = &p_bo->lock;
+	osm_log_t *p_log = p_bo->p_vendor->p_log;
+
+	osm_log(p_log, OSM_LOG_DEBUG,
+		"<-- Releasing lock %p on bind handle %p\n", p_lock, p_bo);
+
+	cl_spinlock_release(&p_bo->lock);
+
+	/* We'll use the saved ptrs, since now the p_bo can be destroyed already */
+	osm_log(p_log, OSM_LOG_DEBUG,
+		"<-- Released lock %p on bind handle %p\n", p_lock, p_bo);
+
+}
+
+static uint64_t
+__osmv_txn_timeout_cb(IN uint64_t key,
+		      IN uint32_t num_regs, IN void *cb_context)
+{
+	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) cb_context;
+	uint64_t ret = 0;
+	osmv_txn_ctx_t *p_txn;
+	osmv_rmpp_send_ctx_t *p_send_ctx;
+	osm_madw_t *p_madw = NULL;
+	ib_mad_t *p_mad;
+	osm_mad_addr_t *p_mad_addr;
+	boolean_t invoke_err_cb = FALSE;
+
+	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
+
+	/* Don't try to acquire a lock on the Bind Object -
+	 * it's taken by the mechanism that drives the timeout based events!
+	 * (Recall the special constructor that the Event Wheel is applied with)
+	 */
+	if (p_bo->is_closing) {
+		goto txn_done;
+	}
+
+	ret = osmv_txn_lookup(p_bo, key, &p_txn);
+	if (IB_NOT_FOUND == ret) {
+		/* Prevent a race - the transaction is already destroyed */
+		goto txn_done;
+	}
+
+	p_madw = p_txn->p_madw;
+
+	switch (osmv_txn_get_rmpp_state(p_txn)) {
+
+	case OSMV_TXN_RMPP_NONE:
+		if (num_regs <= OSMV_MAX_RETRANSMIT) {
+			/* We still did not exceed the limit of retransmissions.
+			 * Set the next timeout's value.
+			 */
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+				"__osmv_txn_timeout_cb: "
+				"The transaction request (tid=0x%llX) timed out %d times. "
+				"Retrying the send.\n",
+				osmv_txn_get_tid(p_txn), num_regs);
+
+			/* resend this mad */
+			ret = osmv_simple_send_madw((osm_bind_handle_t *) p_bo,
+						    p_madw, p_txn, TRUE);
+			if (ret != IB_SUCCESS) {
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+					"__osmv_txn_timeout_cb: "
+					"Fail to send retry for transaction request (tid=0x%llX).\n",
+					osmv_txn_get_tid(p_txn));
+
+				osmv_txn_done((osm_bind_handle_t) p_bo, key,
+					      TRUE /*in timeout callback */ );
+
+				/* This is a requester. Always apply the callback */
+				invoke_err_cb = TRUE;
+			} else {
+				uint64_t next_timeout_ms;
+				next_timeout_ms =
+				    p_bo->p_vendor->resp_timeout * (num_regs +
+								    1) *
+				    (num_regs + 1);
+				/* when do we need to timeout again */
+				ret =
+				    cl_get_time_stamp() +
+				    (uint64_t) (1000 * next_timeout_ms);
+
+				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+					"__osmv_txn_timeout_cb: "
+					"Retry request timout in : %lu [msec].\n",
+					next_timeout_ms);
+			}
+		} else {
+			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
+				"__osmv_txn_timeout_cb: ERR 6702: "
+				"The transaction request (tid=0x%llX) timed out (after %d retries). "
+				"Invoking the error callback.\n",
+				osmv_txn_get_tid(p_txn), num_regs);
+
+			osmv_txn_done((osm_bind_handle_t) p_bo, key,
+				      TRUE /*in timeout callback */ );
+
+			/* This is a requester. Always apply the callback */
+			invoke_err_cb = TRUE;
+		}
+		break;
+
+	case OSMV_TXN_RMPP_SENDER:
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"RMPP sender (tid=0x%llX) did not receive ACK "
+			"on every segment in the current send window.\n",
+			osmv_txn_get_tid(p_txn));
+
+		p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
+		if (num_regs <= OSMV_MAX_RETRANSMIT) {
+			/* We still did not exceed the limit of retransmissions.
+			 * Set the next timeout's value.
+			 */
+			ret =
+			    cl_get_time_stamp() +
+			    1000 * p_bo->p_vendor->resp_timeout;
+		} else {
+			p_send_ctx->status = IB_TIMEOUT;
+
+			p_mad = osm_madw_get_mad_ptr(p_madw);
+			p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
+
+			/* Send an ABORT to the other side */
+			osmv_rmpp_send_nak((osm_bind_handle_t) p_bo, p_mad,
+					   p_mad_addr, IB_RMPP_TYPE_ABORT,
+					   IB_RMPP_STATUS_T2L);
+		}
+
+		/* Wake the RMPP sender thread up */
+		cl_event_signal(&p_send_ctx->event);
+		break;
+
+	case OSMV_TXN_RMPP_RECEIVER:
+		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
+			"Transaction timeout on an RMPP receiver (tid=0x%llX). "
+			"Dropping the transaction.\n", osmv_txn_get_tid(p_txn));
+
+		osmv_txn_done((osm_bind_handle_t) p_bo, key,
+			      TRUE /*in timeout callback */ );
+
+		if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) {
+			/* This is a requester, still waiting for the reply. Apply the callback */
+			invoke_err_cb = TRUE;
+		}
+
+		break;
+
+	default:
+		CL_ASSERT(FALSE);
+	}
+
+	if (TRUE == invoke_err_cb) {
+		CL_ASSERT(NULL != p_madw);
+		/* update the status in the p_madw */
+		p_madw->status = IB_TIMEOUT;
+		p_bo->send_err_cb(p_bo->cb_context, p_madw);
+		/* no re-registration */
+		ret = 0;
+	}
+
+txn_done:
+	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
+	return ret;
+}
diff --git a/man/opensm.8.in b/man/opensm.8.in
new file mode 100644
index 0000000..3000eaf
--- /dev/null
+++ b/man/opensm.8.in
@@ -0,0 +1,1012 @@
+.TH OPENSM 8 "June 13, 2008" "OpenIB" "OpenIB Management"
+
+.SH NAME
+opensm \- InfiniBand subnet manager and administration (SM/SA)
+
+.SH SYNOPSIS
+.B opensm
+[\-\-version]]
+[\-F | \-\-config <file_name>]
+[\-c(reate-config) <file_name>]
+[\-g(uid) <GUID in hex>]
+[\-l(mc) <LMC>]
+[\-p(riority) <PRIORITY>]
+[\-smkey <SM_Key>]
+[\-r(eassign_lids)]
+[\-R <engine name(s)> | \-\-routing_engine <engine name(s)>]
+[\-A | \-\-ucast_cache]
+[\-z | \-\-connect_roots]
+[\-M <file name> | \-\-lid_matrix_file <file name>]
+[\-U <file name> | \-\-lfts_file <file name>]
+[\-S | \-\-sadb_file <file name>]
+[\-a | \-\-root_guid_file <path to file>]
+[\-u | \-\-cn_guid_file <path to file>]
+[\-X | \-\-guid_routing_order_file <path to file>]
+[\-m | \-\-ids_guid_file <path to file>]
+[\-o(nce)]
+[\-s(weep) <interval>]
+[\-t(imeout) <milliseconds>]
+[\-maxsmps <number>]
+[\-console [off | local | socket | loopback]]
+[\-console-port <port>]
+[\-i(gnore-guids) <equalize-ignore-guids-file>]
+[\-f <log file path> | \-\-log_file <log file path> ]
+[\-L | \-\-log_limit <size in MB>] [\-e(rase_log_file)]
+[\-P(config) <partition config file> ]
+[\-N | \-\-no_part_enforce]
+[\-Q | \-\-qos [\-Y | \-\-qos_policy_file <file name>]]
+[\-y | \-\-stay_on_fatal]
+[\-B | \-\-daemon]
+[\-I | \-\-inactive]
+[\-\-perfmgr]
+[\-\-perfmgr_sweep_time_s <seconds>]
+[\-\-prefix_routes_file <path>]
+[\-\-consolidate_ipv6_snm_req]
+[\-v(erbose)] [\-V] [\-D <flags>] [\-d(ebug) <number>]
+[\-h(elp)] [\-?]
+
+.SH DESCRIPTION
+.PP
+opensm is an InfiniBand compliant Subnet Manager and Administration,
+and runs on top of OpenIB.
+
+opensm provides an implementation of an InfiniBand Subnet Manager and
+Administration. Such a software entity is required to run for in order
+to initialize the InfiniBand hardware (at least one per each
+InfiniBand subnet).
+
+opensm also now contains an experimental version of a performance
+manager as well.
+
+opensm defaults were designed to meet the common case usage on clusters with up to a few hundred nodes. Thus, in this default mode, opensm will scan the IB
+fabric, initialize it, and sweep occasionally for changes.
+
+opensm attaches to a specific IB port on the local machine and configures only
+the fabric connected to it. (If the local machine has other IB ports,
+opensm will ignore the fabrics connected to those other ports). If no port is
+specified, it will select the first "best" available port.
+
+opensm can present the available ports and prompt for a port number to
+attach to.
+
+By default, the run is logged to two files: /var/log/messages and /var/log/opensm.log.
+The first file will register only general major events, whereas the second
+will include details of reported errors. All errors reported in this second
+file should be treated as indicators of IB fabric health issues.
+(Note that when a fatal and non-recoverable error occurs, opensm will exit.)
+Both log files should include the message "SUBNET UP" if opensm was able to
+setup the subnet correctly.
+
+.SH OPTIONS
+
+.PP
+.TP
+\fB\-\-version\fR
+Prints OpenSM version and exits.
+.TP
+\fB\-F\fR, \fB\-\-config\fR <config file>
+The name of the OpenSM config file. When not specified
+\fB\% @OPENSM_CONFIG_DIR@/@OPENSM_CONFIG_FILE@\fP will be used (if exists).
+.TP
+\fB\-c\fR, \fB\-\-create-config\fR <file name>
+OpenSM will dump its configuration to the specified file and exit.
+This is a way to generate OpenSM configuration file template.
+.TP
+\fB\-g\fR, \fB\-\-guid\fR <GUID in hex>
+This option specifies the local port GUID value
+with which OpenSM should bind.  OpenSM may be
+bound to 1 port at a time.
+If GUID given is 0, OpenSM displays a list
+of possible port GUIDs and waits for user input.
+Without -g, OpenSM tries to use the default port.
+.TP
+\fB\-l\fR, \fB\-\-lmc\fR <LMC value>
+This option specifies the subnet's LMC value.
+The number of LIDs assigned to each port is 2^LMC.
+The LMC value must be in the range 0-7.
+LMC values > 0 allow multiple paths between ports.
+LMC values > 0 should only be used if the subnet
+topology actually provides multiple paths between
+ports, i.e. multiple interconnects between switches.
+Without -l, OpenSM defaults to LMC = 0, which allows
+one path between any two ports.
+.TP
+\fB\-p\fR, \fB\-\-priority\fR <Priority value>
+This option specifies the SM\'s PRIORITY.
+This will effect the handover cases, where master
+is chosen by priority and GUID.  Range goes from 0
+(default and lowest priority) to 15 (highest).
+.TP
+\fB\-smkey\fR <SM_Key value>
+This option specifies the SM\'s SM_Key (64 bits).
+This will effect SM authentication.
+Note that OpenSM version 3.2.1 and below used the default value '1'
+in a host byte order, it is fixed now but you may need this option to
+interoperate with old OpenSM running on a little endian machine.
+.TP
+\fB\-r\fR, \fB\-\-reassign_lids\fR
+This option causes OpenSM to reassign LIDs to all
+end nodes. Specifying -r on a running subnet
+may disrupt subnet traffic.
+Without -r, OpenSM attempts to preserve existing
+LID assignments resolving multiple use of same LID.
+.TP
+\fB\-R\fR, \fB\-\-routing_engine\fR <Routing engine names>
+This option chooses routing engine(s) to use instead of Min Hop
+algorithm (default).  Multiple routing engines can be specified
+separated by commas so that specific ordering of routing algorithms
+will be tried if earlier routing engines fail.
+Supported engines: minhop, updn, file, ftree, lash, dor
+.TP
+\fB\-A\fR, \fB\-\-ucast_cache\fR
+This option enables unicast routing cache and prevents routing
+recalculation (which is a heavy task in a large cluster) when
+there was no topology change detected during the heavy sweep, or
+when the topology change does not require new routing calculation,
+e.g. when one or more CAs/RTRs/leaf switches going down, or one or
+more of these nodes coming back after being down.
+A very common case that is handled by the unicast routing cache
+is host reboot, which otherwise would cause two full routing
+recalculations: one when the host goes down, and the other when
+the host comes back online.
+.TP
+\fB\-z\fR, \fB\-\-connect_roots\fR
+This option enforces a routing engine (currently up/down
+only) to make connectivity between root switches and in
+this way to be fully IBA complaint. In many cases this can
+violate "pure" deadlock free algorithm, so use it carefully.
+.TP
+\fB\-M\fR, \fB\-\-lid_matrix_file\fR <file name>
+This option specifies the name of the lid matrix dump file
+from where switch lid matrices (min hops tables will be
+loaded.
+.TP
+\fB\-U\fR, \fB\-\-lfts_file\fR <file name>
+This option specifies the name of the LFTs file
+from where switch forwarding tables will be loaded.
+.TP
+\fB\-S\fR, \fB\-\-sadb_file\fR <file name>
+This option specifies the name of the SA DB dump file
+from where SA database will be loaded.
+.TP
+\fB\-a\fR, \fB\-\-root_guid_file\fR <file name>
+Set the root nodes for the Up/Down or Fat-Tree routing
+algorithm to the guids provided in the given file (one to a line).
+.TP
+\fB\-u\fR, \fB\-\-cn_guid_file\fR <file name>
+Set the compute nodes for the Fat-Tree routing algorithm
+to the guids provided in the given file (one to a line).
+.TP
+\fB\-m\fR, \fB\-\-ids_guid_file\fR <file name>
+Name of the map file with set of the IDs which will be used
+by Up/Down routing algorithm instead of node GUIDs
+(format: <guid> <id> per line).
+.TP
+\fB\-X\fR, \fB\-\-guid_routing_order_file\fR <file name>
+Set the order port guids will be routed for the MinHop
+and Up/Down routing algorithms to the guids provided in the
+given file (one to a line).
+.TP
+\fB\-o\fR, \fB\-\-once\fR
+This option causes OpenSM to configure the subnet
+once, then exit.  Ports remain in the ACTIVE state.
+.TP
+\fB\-s\fR, \fB\-\-sweep\fR <interval value>
+This option specifies the number of seconds between
+subnet sweeps.  Specifying -s 0 disables sweeping.
+Without -s, OpenSM defaults to a sweep interval of
+10 seconds.
+.TP
+\fB\-t\fR, \fB\-\-timeout\fR <value>
+This option specifies the time in milliseconds
+used for transaction timeouts.
+Specifying -t 0 disables timeouts.
+Without -t, OpenSM defaults to a timeout value of
+200 milliseconds.
+.TP
+\fB\-maxsmps\fR <number>
+This option specifies the number of VL15 SMP MADs
+allowed on the wire at any one time.
+Specifying -maxsmps 0 allows unlimited outstanding
+SMPs.
+Without -maxsmps, OpenSM defaults to a maximum of
+4 outstanding SMPs.
+.TP
+\fB\-console [off | local | socket | loopback]\fR
+This option brings up the OpenSM console (default off).
+Note that the socket and loopback options will only be available
+if OpenSM was built with --enable-console-socket.
+.TP
+\fB\-console-port\fR <port>
+Specify an alternate telnet port for the socket console (default 10000).
+Note that this option only appears if OpenSM was built with
+--enable-console-socket.
+.TP
+\fB\-i\fR, \fB\-ignore-guids\fR <equalize-ignore-guids-file>
+This option provides the means to define a set of ports
+(by node guid and port number) that will be ignored by the link load
+equalization algorithm.
+.TP
+\fB\-x\fR, \fB\-\-honor_guid2lid\fR
+This option forces OpenSM to honor the guid2lid file,
+when it comes out of Standby state, if such file exists
+under OSM_CACHE_DIR, and is valid.
+By default, this is FALSE.
+.TP
+\fB\-f\fR, \fB\-\-log_file\fR <file name>
+This option defines the log to be the given file.
+By default, the log goes to /var/log/opensm.log.
+For the log to go to standard output use -f stdout.
+.TP
+\fB\-L\fR, \fB\-\-log_limit\fR <size in MB>
+This option defines maximal log file size in MB. When
+specified the log file will be truncated upon reaching
+this limit.
+.TP
+\fB\-e\fR, \fB\-\-erase_log_file\fR
+This option will cause deletion of the log file
+(if it previously exists). By default, the log file
+is accumulative.
+.TP
+\fB\-P\fR, \fB\-\-Pconfig\fR <partition config file>
+This option defines the optional partition configuration file.
+The default name is \fB\%@OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@\fP.
+.TP
+\fB\-\-prefix_routes_file\fR <file name>
+Prefix routes control how the SA responds to path record queries for
+off-subnet DGIDs.  By default, the SA fails such queries. The
+.B PREFIX ROUTES
+section below describes the format of the configuration file.
+The default path is \fB\%@OPENSM_CONFIG_DIR@/prefix\-routes.conf\fP.
+.TP
+\fB\-Q\fR, \fB\-\-qos\fR
+This option enables QoS setup. It is disabled by default.
+.TP
+\fB\-Y\fR, \fB\-\-qos_policy_file\fR <file name>
+This option defines the optional QoS policy file. The default
+name is \fB\%@OPENSM_CONFIG_DIR@/@QOS_POLICY_FILE@\fP.
+.TP
+\fB\-N\fR, \fB\-\-no_part_enforce\fR
+This option disables partition enforcement on switch external ports.
+.TP
+\fB\-y\fR, \fB\-\-stay_on_fatal\fR
+This option will cause SM not to exit on fatal initialization
+issues: if SM discovers duplicated guids or a 12x link with
+lane reversal badly configured.
+By default, the SM will exit on these errors.
+.TP
+\fB\-B\fR, \fB\-\-daemon\fR
+Run in daemon mode - OpenSM will run in the background.
+.TP
+\fB\-I\fR, \fB\-\-inactive\fR
+Start SM in inactive rather than init SM state.  This
+option can be used in conjunction with the perfmgr so as to
+run a standalone performance manager without SM/SA.  However,
+this is NOT currently implemented in the performance manager.
+.TP
+\fB\-perfmgr\fR
+Enable the perfmgr.  Only takes effect if --enable-perfmgr was specified at
+configure time.
+.TP
+\fB\-perfmgr_sweep_time_s\fR <seconds>
+Specify the sweep time for the performance manager in seconds
+(default is 180 seconds).  Only takes
+effect if --enable-perfmgr was specified at configure time.
+.TP
+.BI --consolidate_ipv6_snm_req
+Consolidate IPv6 Solicited Node Multicast group join requests into one
+multicast group per MGID PKey.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+This option increases the log verbosity level.
+The -v option may be specified multiple times
+to further increase the verbosity level.
+See the -D option for more information about
+log verbosity.
+.TP
+\fB\-V\fR
+This option sets the maximum verbosity level and
+forces log flushing.
+The -V option is equivalent to \'-D 0xFF -d 2\'.
+See the -D option for more information about
+log verbosity.
+.TP
+\fB\-D\fR <value>
+This option sets the log verbosity level.
+A flags field must follow the -D option.
+A bit set/clear in the flags enables/disables a
+specific log level as follows:
+
+ BIT    LOG LEVEL ENABLED
+ ----   -----------------
+ 0x01 - ERROR (error messages)
+ 0x02 - INFO (basic messages, low volume)
+ 0x04 - VERBOSE (interesting stuff, moderate volume)
+ 0x08 - DEBUG (diagnostic, high volume)
+ 0x10 - FUNCS (function entry/exit, very high volume)
+ 0x20 - FRAMES (dumps all SMP and GMP frames)
+ 0x40 - ROUTING (dump FDB routing information)
+ 0x80 - currently unused.
+
+Without -D, OpenSM defaults to ERROR + INFO (0x3).
+Specifying -D 0 disables all messages.
+Specifying -D 0xFF enables all messages (see -V).
+High verbosity levels may require increasing
+the transaction timeout with the -t option.
+.TP
+\fB\-d\fR, \fB\-\-debug\fR <value>
+This option specifies a debug option.
+These options are not normally needed.
+The number following -d selects the debug
+option to enable as follows:
+
+ OPT   Description
+ ---    -----------------
+ -d0  - Ignore other SM nodes
+ -d1  - Force single threaded dispatching
+ -d2  - Force log flushing after each log message
+ -d3  - Disable multicast support
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display this usage info then exit.
+.TP
+\fB\-?\fR
+Display this usage info then exit.
+
+.SH ENVIRONMENT VARIABLES
+.PP
+The following environment variables control opensm behavior:
+
+OSM_TMP_DIR - controls the directory in which the temporary files generated by
+opensm are created. These files are: opensm-subnet.lst, opensm.fdbs, and
+opensm.mcfdbs. By default, this directory is /var/log.
+
+OSM_CACHE_DIR - opensm stores certain data to the disk such that subsequent
+runs are consistent. The default directory used is /var/cache/opensm.
+The following file is included in it:
+
+ guid2lid - stores the LID range assigned to each GUID
+
+.SH NOTES
+.PP
+When opensm receives a HUP signal, it starts a new heavy sweep as if a trap was received or a topology change was found.
+.PP
+Also, SIGUSR1 can be used to trigger a reopen of /var/log/opensm.log for
+logrotate purposes.
+
+.SH PARTITION CONFIGURATION
+.PP
+The default name of OpenSM partitions configuration file is
+\fB\%@OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@\fP. The default may be changed by using
+--Pconfig (-P) option with OpenSM.
+
+The default partition will be created by OpenSM unconditionally even
+when partition configuration file does not exist or cannot be accessed.
+
+The default partition has P_Key value 0x7fff. OpenSM\'s port will have
+full membership in default partition. All other end ports will have
+partial membership.
+
+File Format
+
+Comments:
+
+Line content followed after \'#\' character is comment and ignored by
+parser.
+
+General file format:
+
+<Partition Definition>:<PortGUIDs list> ;
+
+Partition Definition:
+
+[PartitionName][=PKey][,flag[=value]][,defmember=full|limited]
+
+ PartitionName - string, will be used with logging. When omitted
+                 empty string will be used.
+ PKey          - P_Key value for this partition. Only low 15 bits will
+                 be used. When omitted will be autogenerated.
+ flag          - used to indicate IPoIB capability of this partition.
+ defmember=full|limited - specifies default membership for port guid
+                 list. Default is limited.
+
+Currently recognized flags are:
+
+ ipoib       - indicates that this partition may be used for IPoIB, as
+               result IPoIB capable MC group will be created.
+ rate=<val>  - specifies rate for this IPoIB MC group
+               (default is 3 (10GBps))
+ mtu=<val>   - specifies MTU for this IPoIB MC group
+               (default is 4 (2048))
+ sl=<val>    - specifies SL for this IPoIB MC group
+               (default is 0)
+ scope=<val> - specifies scope for this IPoIB MC group
+               (default is 2 (link local)).  Multiple scope settings
+               are permitted for a partition.
+
+Note that values for rate, mtu, and scope should be specified as
+defined in the IBTA specification (for example, mtu=4 for 2048).
+
+PortGUIDs list:
+
+ PortGUID         - GUID of partition member EndPort. Hexadecimal
+                    numbers should start from 0x, decimal numbers
+                    are accepted too.
+ full or limited  - indicates full or limited membership for this
+                    port.  When omitted (or unrecognized) limited
+                    membership is assumed.
+
+There are two useful keywords for PortGUID definition:
+
+ - 'ALL' means all end ports in this subnet.
+ - 'SELF' means subnet manager's port.
+
+Empty list means no ports in this partition.
+
+Notes:
+
+White space is permitted between delimiters ('=', ',',':',';').
+
+The line can be wrapped after ':' followed after Partition Definition and
+between.
+
+PartitionName does not need to be unique, PKey does need to be unique.
+If PKey is repeated then those partition configurations will be merged
+and first PartitionName will be used (see also next note).
+
+It is possible to split partition configuration in more than one
+definition, but then PKey should be explicitly specified (otherwise
+different PKey values will be generated for those definitions).
+
+Examples:
+
+ Default=0x7fff : ALL, SELF=full ;
+
+ NewPartition , ipoib : 0x123456=full, 0x3456789034=limi, 0x2134af2306 ;
+
+ YetAnotherOne = 0x300 : SELF=full ;
+ YetAnotherOne = 0x300 : ALL=limited ;
+
+ ShareIO = 0x80 , defmember=full : 0x123451, 0x123452;
+ # 0x123453, 0x123454 will be limited
+ ShareIO = 0x80 : 0x123453, 0x123454, 0x123455=full;
+ # 0x123456, 0x123457 will be limited
+ ShareIO = 0x80 : defmember=limited : 0x123456, 0x123457, 0x123458=full;
+ ShareIO = 0x80 , defmember=full : 0x123459, 0x12345a;
+ ShareIO = 0x80 , defmember=full : 0x12345b, 0x12345c=limited, 0x12345d;
+
+
+Note:
+
+The following rule is equivalent to how OpenSM used to run prior to the
+partition manager:
+
+ Default=0x7fff,ipoib:ALL=full;
+
+.SH QOS CONFIGURATION
+.PP
+There are a set of QoS related low-level configuration parameters.
+All these parameter names are prefixed by "qos_" string. Here is a full
+list of these parameters:
+
+ qos_max_vls    - The maximum number of VLs that will be on the subnet
+ qos_high_limit - The limit of High Priority component of VL
+                  Arbitration table (IBA 7.6.9)
+ qos_vlarb_low  - Low priority VL Arbitration table (IBA 7.6.9)
+                  template
+ qos_vlarb_high - High priority VL Arbitration table (IBA 7.6.9)
+                  template
+                  Both VL arbitration templates are pairs of
+                  VL and weight
+ qos_sl2vl      - SL2VL Mapping table (IBA 7.6.6) template. It is
+                  a list of VLs corresponding to SLs 0-15 (Note
+                  that VL15 used here means drop this SL)
+
+Typical default values (hard-coded in OpenSM initialization) are:
+
+ qos_max_vls 15
+ qos_high_limit 0
+ qos_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4
+ qos_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0
+ qos_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+The syntax is compatible with rest of OpenSM configuration options and
+values may be stored in OpenSM config file (cached options file).
+
+In addition to the above, we may define separate QoS configuration
+parameters sets for various target types. As targets, we currently support
+CAs, routers, switch external ports, and switch's enhanced port 0. The
+names of such specialized parameters are prefixed by "qos_<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
+
+.SH PREFIX ROUTES
+.PP
+Prefix routes control how the SA responds to path record queries for
+off-subnet DGIDs.  By default, the SA fails such queries.
+Note that IBA does not specify how the SA should obtain off-subnet path
+record information.
+The prefix routes configuration is meant as a stop-gap until the
+specification is completed.
+.PP
+Each line in the configuration file is a 64-bit prefix followed by a
+64-bit GUID, separated by white space.
+The GUID specifies the router port on the local subnet that will
+handle the prefix.
+Blank lines are ignored, as is anything between a \fB#\fP character
+and the end of the line.
+The prefix and GUID are both in hex, the leading 0x is optional.
+Either, or both, can be wild-carded by specifying an
+asterisk instead of an explicit prefix or GUID.
+.PP
+When responding to a path record query for an off-subnet DGID,
+opensm searches for the first prefix match in the configuration file.
+Therefore, the order of the lines in the configuration file is important:
+a wild-carded prefix at the beginning of the configuration file renders
+all subsequent lines useless.
+If there is no match, then opensm fails the query.
+It is legal to repeat prefixes in the configuration file,
+opensm will return the path to the first available matching router.
+A configuration file with a single line where both prefix and GUID
+are wild-carded means that a path record query specifying any
+off-subnet DGID should return a path to the first available router.
+This configuration yields the same behaviour formerly achieved by
+compiling opensm with -DROUTER_EXP.
+
+.SH ROUTING
+.PP
+OpenSM now offers five 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
+for congestion-free "shift" communication pattern.
+It should be chosen if a subnet is a symmetrical or almost symmetrical
+fat-tree of various types, not just K-ary-N-Trees: non-constant K, not
+fully staffed, any Constant Bisectional Bandwidth (CBB) ratio.
+Similar to UPDN, Fat Tree routing is constrained to ranking rules.
+
+4. LASH unicast routing algorithm - uses Infiniband virtual layers
+(SL) to provide deadlock-free shortest-path routing while also
+distributing the paths between layers. LASH is an alternative
+deadlock-free topology-agnostic routing algorithm to the non-minimal
+UPDN algorithm avoiding the use of a potentially congested root node.
+
+5. DOR Unicast routing algorithm - based on the Min Hop algorithm, but
+avoids port equalization except for redundant links between the same
+two switches.  This provides deadlock free routes for hypercubes when
+the fabric is cabled as a hypercube and for meshes when cabled as a
+mesh (see details below).
+
+OpenSM also supports a file method which
+can load routes from a table. See \'Modular Routing Engine\' for more
+information on this.
+
+The basic routing algorithm is comprised of two stages:
+
+1. MinHop matrix calculation
+   How many hops are required to get from each port to each LID ?
+   The algorithm to fill these tables is different if you run standard
+(min hop) or Up/Down.
+   For standard routing, a "relaxation" algorithm is used to propagate
+min hop from every destination LID through neighbor switches
+   For Up/Down routing, a BFS from every target is used. The BFS tracks link
+direction (up or down) and avoid steps that will perform up after a down
+step was used.
+
+2. Once MinHop matrices exist, each switch is visited and for each target LID a
+decision is made as to what port should be used to get to that LID.
+   This step is common to standard and Up/Down routing. Each port has a
+counter counting the number of target LIDs going through it.
+   When there are multiple alternative ports with same MinHop to a LID,
+the one with less previously assigned 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
+.br
+--reassign_lids
+          This option causes OpenSM to reassign LIDs to all
+          end nodes. Specifying -r on a running subnet
+          may disrupt subnet traffic.
+          Without -r, OpenSM attempts to preserve existing
+          LID assignments resolving multiple use of same LID.
+
+If a link is added or removed, OpenSM does not recalculate
+the routes that do not have to change. A route has to change
+if the port is no longer UP or no longer the MinHop. When routing changes
+are performed, the same algorithm for balancing the routes is invoked.
+
+In the case of using the file based routing, any topology changes are
+currently ignored The 'file' routing engine just loads the LFTs from the file
+specified, with no reaction to real topology. Obviously, this will not be able
+to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent
+switches will be skipped. Multicast is not affected by 'file' routing engine
+(this uses min hop tables).
+
+
+Min Hop Algorithm
+
+The Min Hop algorithm is invoked by default if no routing algorithm is
+specified.  It can also be invoked by specifying '-R minhop'.
+
+The Min Hop algorithm is divided into two stages: computation of
+min-hop tables on every switch and LFT output port assignment. Link
+subscription is also equalized with the ability to override based on
+port GUID. The latter is supplied by:
+
+-i <equalize-ignore-guids-file>
+.br
+-ignore-guids <equalize-ignore-guids-file>
+          This option provides the means to define a set of ports
+          (by guid) that will be ignored by the link load
+          equalization algorithm. Note that only endports (CA,
+          switch port 0, and router ports) and not switch external
+          ports are supported.
+
+LMC awareness routes based on (remote) system or switch basis.
+
+
+Purpose of UPDN Algorithm
+
+The UPDN algorithm is designed to prevent deadlocks from occurring in loops
+of the subnet. A loop-deadlock is a situation in which it is no longer
+possible to send data between any two hosts connected through the loop. As
+such, the UPDN routing algorithm should be used if the subnet is not a pure
+Fat Tree, and one of its loops may experience a deadlock (due, for example,
+to high pressure).
+
+The UPDN algorithm is based on the following main stages:
+
+1.  Auto-detect root nodes - based on the CA hop length from any switch in
+the subnet, a statistical histogram is built for each switch (hop num vs
+number of occurrences). If the histogram reflects a specific column (higher
+than others) for a certain node, then it is marked as a root node. Since
+the algorithm is statistical, it may not find any root nodes. The list of
+the root nodes found by this auto-detect stage is used by the ranking
+process stage.
+
+    Note 1: The user can override the node list manually.
+    Note 2: If this stage cannot find any root nodes, and the user did
+            not specify a guid list file, OpenSM defaults back to the
+            Min Hop routing algorithm.
+
+2.  Ranking process - All root switch nodes (found in stage 1) are assigned
+a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the
+subnet are ranked incrementally. This ranking aids in the process of enforcing
+rules that ensure loop-free paths.
+
+3.  Min Hop Table setting - after ranking is done, a BFS algorithm is run from
+each (CA or switch) node in the subnet. During the BFS process, the FDB table
+of each switch node traversed by BFS is updated, in reference to the starting
+node, based on the ranking rules and guid values.
+
+At the end of the process, the updated FDB tables ensure loop-free paths
+through the subnet.
+
+Note: Up/Down routing does not allow LID routing communication between
+switches that are located inside spine "switch systems".
+The reason is that there is no way to allow a LID route between them
+that does not break the Up/Down rule.
+One ramification of this is that you cannot run SM on switches other
+than the leaf switches of the fabric.
+
+
+UPDN Algorithm Usage
+
+Activation through OpenSM
+
+Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm.
+Use '-a <root_guid_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.
+.br
+2.   The user should specify the root switch guids. However, it is also
+possible to specify CA guids; OpenSM will use the guid of the switch (if
+it exists) that connects the CA to the subnet as a root node.
+
+
+Fat-tree Routing Algorithm
+
+The fat-tree algorithm optimizes routing for "shift" communication pattern.
+It should be chosen if a subnet is a symmetrical or almost symmetrical
+fat-tree of various types.
+It supports not just K-ary-N-Trees, by handling for non-constant K,
+cases where not all leafs (CAs) are present, any CBB ratio.
+As in UPDN, fat-tree also prevents credit-loop-deadlocks.
+
+If the root guid file is not provided ('-a' or '--root_guid_file' options),
+the topology has to be pure fat-tree that complies with the following rules:
+  - Tree rank should be between two and eight (inclusively)
+  - Switches of the same rank should have the same number
+    of UP-going port groups*, unless they are root switches,
+    in which case the shouldn't have UP-going ports at all.
+  - Switches of the same rank should have the same number
+    of DOWN-going port groups, unless they are leaf switches.
+  - Switches of the same rank should have the same number
+    of ports in each UP-going port group.
+  - Switches of the same rank should have the same number
+    of ports in each DOWN-going port group.
+  - All the CAs have to be at the same tree level (rank).
+
+If the root guid file is provided, the topology doesn't have to be pure
+fat-tree, and it should only comply with the following rules:
+  - Tree rank should be between two and eight (inclusively)
+  - All the Compute Nodes** have to be at the same tree level (rank).
+    Note that non-compute node CAs are allowed here to be at different
+    tree ranks.
+
+* ports that are connected to the same remote switch are referenced as
+\'port group\'.
+
+** list of compute nodes (CNs) can be specified by \'-u\' or \'--cn_guid_file\'
+OpenSM options.
+
+Topologies that do not comply cause a fallback to min hop routing.
+Note that this can also occur on link failures which cause the topology
+to no longer be "pure" fat-tree.
+
+Note that although fat-tree algorithm supports trees with non-integer CBB
+ratio, the routing will not be as balanced as in case of integer CBB ratio.
+In addition to this, although the algorithm allows leaf switches to have any
+number of CAs, the closer the tree is to be fully populated, the more
+effective the "shift" communication pattern will be.
+In general, even if the root list is provided, the closer the topology to a
+pure and symmetrical fat-tree, the more optimal the routing will be.
+
+The algorithm also dumps compute node ordering file (opensm-ftree-ca-order.dump)
+in the same directory where the OpenSM log resides. This ordering file provides
+the CN order that may be used to create efficient communication pattern, that
+will match the routing tables.
+
+Activation through OpenSM
+
+Use '-R ftree' option to activate the fat-tree algorithm.
+Use '-a <root_guid_file>' to provide root nodes for ranking. If the `-a' option
+is not used, routing algorithm will detect roots automatically.
+Use '-u <root_cn_file>' to provide the list of compute nodes. If the `-u' option
+is not used, all the CAs are considered as compute nodes.
+
+Note: LMC > 0 is not supported by fat-tree routing. If this is
+specified, the default routing algorithm is invoked instead.
+
+
+LASH Routing Algorithm
+
+LASH is an acronym for LAyered SHortest Path Routing. It is a
+deterministic shortest path routing algorithm that enables topology
+agnostic deadlock-free routing within communication networks.
+
+When computing the routing function, LASH analyzes the network
+topology for the shortest-path routes between all pairs of sources /
+destinations and groups these paths into virtual layers in such a way
+as to avoid deadlock.
+
+Note LASH analyzes routes and ensures deadlock freedom between switch
+pairs. The link from HCA between and switch does not need virtual
+layers as deadlock will not arise between switch and HCA.
+
+In more detail, the algorithm works as follows:
+
+1) LASH determines the shortest-path between all pairs of source /
+destination switches. Note, LASH ensures the same SL is used for all
+SRC/DST - DST/SRC pairs and there is no guarantee that the return
+path for a given DST/SRC will be the reverse of the route SRC/DST.
+
+2) LASH then begins an SL assignment process where a route is assigned
+to a layer (SL) if the addition of that route does not cause deadlock
+within that layer. This is achieved by maintaining and analysing a
+channel dependency graph for each layer. Once the potential addition
+of a path could lead to deadlock, LASH opens a new layer and continues
+the process.
+
+3) Once this stage has been completed, it is highly likely that the
+first layers processed will contain more paths than the latter ones.
+To better balance the use of layers, LASH moves paths from one layer
+to another so that the number of paths in each layer averages out.
+
+Note, the implementation of LASH in opensm attempts to use as few layers
+as possible. This number can be less than the number of actual layers
+available.
+
+In general LASH is a very flexible algorithm. It can, for example,
+reduce to Dimension Order Routing in certain topologies, it is topology
+agnostic and fares well in the face of faults.
+
+It has been shown that for both regular and irregular topologies, LASH
+outperforms Up/Down. The reason for this is that LASH distributes the
+traffic more evenly through a network, avoiding the bottleneck issues
+related to a root node and always routes shortest-path.
+
+The algorithm was developed by Simula Research Laboratory.
+
+
+Use '-R lash -Q ' option to activate the LASH algorithm.
+
+Note: QoS support has to be turned on in order that SL/VL mappings are
+used.
+
+Note: LMC > 0 is not supported by the LASH routing. If this is
+specified, the default routing algorithm is invoked instead.
+
+
+DOR Routing Algorithm
+
+The Dimension Order Routing algorithm is based on the Min Hop
+algorithm and so uses shortest paths.  Instead of spreading traffic
+out across different paths with the same shortest distance, it chooses
+among the available shortest paths based on an ordering of dimensions.
+Each port must be consistently cabled to represent a hypercube
+dimension or a mesh dimension.  Paths are grown from a destination
+back to a source using the lowest dimension (port) of available paths
+at each step.  This provides the ordering necessary to avoid deadlock.
+When there are multiple links between any two switches, they still
+represent only one dimension and traffic is balanced across them
+unless port equalization is turned off.  In the case of hypercubes,
+the same port must be used throughout the fabric to represent the
+hypercube dimension and match on both ends of the cable.  In the case
+of meshes, the dimension should consistently use the same pair of
+ports, one port on one end of the cable, and the other port on the
+other end, continuing along the mesh dimension.
+
+Use '-R dor' option to activate the DOR algorithm.
+
+
+Routing References
+
+To learn more about deadlock-free routing, see the article
+"Deadlock Free Message Routing in Multiprocessor Interconnection Networks"
+by William J Dally and Charles L Seitz (1985).
+
+To learn more about the up/down algorithm, see the article
+"Effective Strategy to Compute Forwarding Tables for InfiniBand Networks"
+by Jose Carlos Sancho, Antonio Robles, and Jose Duato at the
+Universidad Politecnica de Valencia.
+
+To learn more about LASH and the flexibility behind it, the requirement
+for layers, performance comparisons to other algorithms, see the
+following articles:
+
+"Layered Routing in Irregular Networks", Lysne et al, IEEE
+Transactions on Parallel and Distributed Systems, VOL.16, No12,
+December 2005.
+
+"Routing for the ASI Fabric Manager", Solheim et al. IEEE
+Communications Magazine, Vol.44, No.7, July 2006.
+
+"Layered Shortest Path (LASH) Routing in Irregular System Area
+Networks", Skeie et al. IEEE Computer Society Communication
+Architecture for Clusters 2002.
+
+
+Modular Routine Engine
+
+Modular routing engine structure allows for the ease of
+"plugging" new routing modules.
+
+Currently, only unicast callbacks are supported. Multicast
+can be added later.
+
+One existing routing module is up-down "updn", which may be
+activated with '-R updn' option (instead of old '-u').
+
+General usage is:
+$ opensm -R 'module-name'
+
+There is also a trivial routing module which is able
+to load LFT tables from a file.
+
+Main features:
+
+ - this will load switch LFTs and/or LID matrices (min hops tables)
+ - this will load switch LFTs according to the path entries introduced
+   in the file
+ - no additional checks will be performed (such as "is port connected",
+   etc.)
+ - in case when fabric LIDs were changed this will try to reconstruct
+   LFTs correctly if endport GUIDs are represented in the file
+   (in order to disable this, GUIDs may be removed from the file
+    or zeroed)
+
+The file format is compatible with output of 'ibroute' util and for
+whole fabric can be generated with dump_lfts.sh script.
+
+To activate file based routing module, use:
+
+  opensm -R file -U /path/to/lfts_file
+
+If the lfts_file is not found or is in error, the default routing
+algorithm is utilized.
+
+The ability to dump switch lid matrices (aka min hops tables) to file and
+later to load these is also supported.
+
+The usage is similar to unicast forwarding tables loading from a lfts
+file (introduced by 'file' routing engine), but new lid matrix file
+name should be specified by -M or --lid_matrix_file option. For example:
+
+  opensm -R file -M ./opensm-lid-matrix.dump
+
+The dump file is named \'opensm-lid-matrix.dump\' and will be generated
+in standard opensm dump directory (/var/log by default) when
+OSM_LOG_ROUTING logging flag is set.
+
+When routing engine 'file' is activated, but the lfts file is not specified
+or not cannot be open default lid matrix algorithm will be used.
+
+There is also a switch forwarding tables dumper which generates
+a file compatible with dump_lfts.sh output. This file can be used
+as input for forwarding tables loading by 'file' routing engine.
+Both or one of options -U and -M can be specified together with \'-R file\'.
+
+.SH FILES
+.TP
+.B @OPENSM_CONFIG_DIR@/@OPENSM_CONFIG_FILE@
+default OpenSM config file.
+
+.TP
+.B @OPENSM_CONFIG_DIR@/@NODENAMEMAPFILE@
+default node name map file.  See ibnetdiscover for more information on format.
+
+.TP
+.B @OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@
+default partition config file
+
+.TP
+.B @OPENSM_CONFIG_DIR@/@QOS_POLICY_FILE@
+default QOS policy config file
+
+.TP
+.B @OPENSM_CONFIG_DIR@/@PREFIX_ROUTES_FILE@
+default prefix routes file.
+
+.SH AUTHORS
+.TP
+Hal Rosenstock
+.RI < hal.rosenstock at gmail.com >
+.TP
+Sasha Khapyorsky
+.RI < sashak at voltaire.com >
+.TP
+Eitan Zahavi
+.RI < eitan at mellanox.co.il >
+.TP
+Yevgeny Kliteynik
+.RI < kliteyn at mellanox.co.il >
+.TP
+Thomas Sodring
+.RI < tsodring at simula.no >
+.TP
+Ira Weiny
+.RI < weiny2 at llnl.gov >
diff --git a/man/osmtest.8 b/man/osmtest.8
new file mode 100644
index 0000000..c814b49
--- /dev/null
+++ b/man/osmtest.8
@@ -0,0 +1,190 @@
+.TH OSMTEST 8 "August 11, 2008" "OpenIB" "OpenIB Management"
+
+.SH NAME
+osmtest \- InfiniBand subnet manager and administration (SM/SA) test program
+
+.SH SYNOPSIS
+.B osmtest
+[\-f(low) <c|a|v|s|e|f|m|q|t>] [\-w(ait) <trap_wait_time>] [\-d(ebug) <number>]
+[\-m(ax_lid) <LID in hex>] [\-g(uid)[=]<GUID in hex>] [-p(ort)]
+[\-i(nventory) <filename>] [\-s(tress)] [\-M(ulticast_Mode)]
+[\-t(imeout) <milliseconds>] [\-l | \-\-log_file] [\-v] [\-vf <flags>]
+[\-h(elp)]
+
+.SH DESCRIPTION
+.PP
+osmtest is a test program to validate InfiniBand subnet manager and
+administration (SM/SA).
+
+Default is to run all flows with the exception of the QoS flow.
+
+osmtest provides a test suite for opensm.
+
+osmtest has the following capabilities and testing flows:
+
+It creates an inventory file of all available Nodes, Ports, and PathRecords,
+including all their fields.
+It verifies the existing inventory, with all the object fields, and matches it
+to a pre-saved one.
+A Multicast Compliancy test.
+An Event Forwarding test.
+A Service Record registration test.
+An RMPP stress test.
+A Small SA Queries stress test.
+
+It is recommended that after installing opensm, the user should run
+"osmtest -f c" to generate the inventory file, and
+immediately afterwards run "osmtest -f a" to test OpenSM.
+
+Another recommendation for osmtest usage is to create the inventory when the
+IB fabric is stable, and occasionally
+run "osmtest -v" to verify that nothing has changed.
+
+.SH OPTIONS
+
+.PP
+.TP
+\fB\-f\fR, \fB\-\-flow\fR
+This option directs osmtest to run a specific flow:
+ FLOW  DESCRIPTION
+ c = create an inventory file with all nodes, ports and paths
+ a = run all validation tests (expecting an input inventory)
+ v = only validate the given inventory file
+ s = run service registration, deregistration, and lease test
+ e = run event forwarding test
+ f = flood the SA with queries according to the stress mode
+ m = multicast flow
+ q = QoS info: dump VLArb and SLtoVL tables
+ t = run trap 64/65 flow (this flow requires running of external tool)
+ (default is all flows except QoS)
+.TP
+\fB\-w\fR, \fB\-\-wait\fR
+This option specifies the wait time for trap 64/65 in seconds
+It is used only when running -f t - the trap 64/65 flow
+(default to 10 sec)
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+This option specifies a debug option.
+These options are not normally needed.
+The number following -d selects the debug
+option to enable as follows:
+
+ OPT   Description
+ ---    -----------------
+ -d0  - Ignore other SM nodes
+ -d1  - Force single threaded dispatching
+ -d2  - Force log flushing after each log message
+ -d3  - Disable multicast support
+.TP
+\fB\-m\fR, \fB\-\-max_lid\fR
+This option specifies the maximal LID number to be searched
+for during inventory file build (default to 100)
+.TP
+\fB\-g\fR, \fB\-\-guid\fR
+This option specifies the local port GUID value
+with which OpenSM should bind.  OpenSM may be
+bound to 1 port at a time.
+If GUID given is 0, OpenSM displays a list
+of possible port GUIDs and waits for user input.
+Without -g, OpenSM trys to use the default port.
+.TP
+\fB\-p\fR, \fB\-\-port\fR
+This option displays a menu of possible local port GUID values
+with which osmtest could bind
+.TP
+\fB\-i\fR, \fB\-\-inventory\fR
+This option specifies the name of the inventory file
+Normally, osmtest expects to find an inventory file,
+which osmtest uses to validate real-time information
+received from the SA during testing
+If -i is not specified, osmtest defaults to the file
+\'osmtest.dat\'
+See -c option for related information
+.TP
+\fB\-s\fR, \fB\-\-stress\fR
+This option runs the specified stress test instead
+of the normal test suite
+Stress test options are as follows:
+
+ OPT    Description
+ ---    -----------------
+ -s1  - Single-MAD response SA queries
+ -s2  - Multi-MAD (RMPP) response SA queries
+ -s3  - Multi-MAD (RMPP) Path Record SA queries
+
+Without -s, stress testing is not performed
+.TP
+\fB\-M\fR, \fB\-\-Multicast_Mode\fR
+This option specify length of Multicast test:
+
+ OPT    Description
+ ---    -----------------
+ -M1  - Short Multicast Flow (default) - single mode
+ -M2  - Short Multicast Flow - multiple mode
+ -M3  - Long Multicast Flow - single mode
+ -M4  - Long Multicast Flow - multiple mode
+
+Single mode - Osmtest is tested alone, with no other
+apps that interact with OpenSM MC
+
+Multiple mode - Could be run with other apps using MC with
+OpenSM. Without -M, default flow testing is performed
+.TP
+\fB\-t\fR, \fB\-\-timeout\fR
+This option specifies the time in milliseconds
+used for transaction timeouts.
+Specifying -t 0 disables timeouts.
+Without -t, OpenSM defaults to a timeout value of
+200 milliseconds.
+.TP
+\fB\-l\fR, \fB\-\-log_file\fR
+This option defines the log to be the given file.
+By default the log goes to stdout.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+This option increases the log verbosity level.
+The -v option may be specified multiple times
+to further increase the verbosity level.
+See the -vf option for more information about.
+log verbosity.
+.TP
+\fB\-V\fR
+This option sets the maximum verbosity level and
+forces log flushing.
+The -V is equivalent to '-vf 0xFF -d 2'.
+See the -vf option for more information about.
+log verbosity.
+.TP
+\fB\-vf\fR
+This option sets the log verbosity level.
+A flags field must follow the -D option.
+A bit set/clear in the flags enables/disables a
+specific log level as follows:
+
+ BIT    LOG LEVEL ENABLED
+ ----   -----------------
+ 0x01 - ERROR (error messages)
+ 0x02 - INFO (basic messages, low volume)
+ 0x04 - VERBOSE (interesting stuff, moderate volume)
+ 0x08 - DEBUG (diagnostic, high volume)
+ 0x10 - FUNCS (function entry/exit, very high volume)
+ 0x20 - FRAMES (dumps all SMP and GMP frames)
+ 0x40 - ROUTING (dump FDB routing information)
+ 0x80 - currently unused.
+
+Without -vf, osmtest defaults to ERROR + INFO (0x3)
+Specifying -vf 0 disables all messages
+Specifying -vf 0xFF enables all messages (see -V)
+High verbosity levels may require increasing
+the transaction timeout with the -t option
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display this usage info then exit.
+
+.SH AUTHORS
+.TP
+Hal Rosenstock
+.RI < hal at xsigo.com >
+.TP
+Eitan Zahavi
+.RI < eitan at mellanox.co.il >
diff --git a/opensm.spec.in b/opensm.spec.in
new file mode 100644
index 0000000..9c23f47
--- /dev/null
+++ b/opensm.spec.in
@@ -0,0 +1,146 @@
+%define RELEASE @RELEASE@
+%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
+%if %{?_with_console_socket:1}%{!?_with_console_socket:0}
+%define _enable_console_socket --enable-console-socket
+%endif
+%if %{?_without_console_socket:1}%{!?_without_console_socket:0}
+%define _disable_console_socket --disable-console-socket
+%endif
+
+%if %{?_with_perf_mgr:1}%{!?_with_perf_mgr:0}
+%define _enable_perf_mgr --enable-perf-mgr
+%endif
+%if %{?_without_perf_mgr:1}%{!?_without_perf_mgr:0}
+%define _disable_perf_mgr --disable-perf-mgr
+%endif
+
+%if %{?_with_event_plugin:1}%{!?_with_event_plugin:0}
+%define _enable_event_plugin --enable-event-plugin
+%endif
+%if %{?_without_event_plugin:1}%{!?_without_event_plugin:0}
+%define _disable_event_plugin --disable-event-plugin
+%endif
+
+Summary: InfiniBand subnet manager and administration
+Name: opensm
+Version: @VERSION@
+Release: %rel%{?dist}
+License: GPLv2 or BSD
+Group: System Environment/Daemons
+URL: http://openfabrics.org/
+Source: http://www.openfabrics.org/downloads/management/@TARBALL@
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: libibumad-devel, libtool
+Requires: %{name}-libs = %{version}-%{release}, logrotate
+Requires(post): /sbin/service, /sbin/chkconfig
+Requires(preun): /sbin/chkconfig, /sbin/service
+
+%description
+OpenSM provides an implementation of an InfiniBand Subnet Manager and
+Administration. Such a software entity is required to run for in order
+to initialize the InfiniBand hardware (at least one per each
+InfiniBand subnet).
+
+%package libs
+Summary: Libraries from the opensm package
+Group: System Environment/Libraries
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+Obsoletes: libopensm, libosmcomp, libosmvendor
+
+%description libs
+Shared libraries that are part of the opensm package but are also used by
+other applications.  If you don't need opensm itself installed, these
+libraries can be installed to satisfy dependencies of other applications.
+
+%package devel
+Summary: Development files for OpenSM
+Group: System Environment/Libraries
+Requires: %{name}-libs = %{version}-%{release} libibumad-devel
+Obsoletes: libopensm-devel, libosmcomp-devel, libosmvendor-devel
+
+%description devel
+Header files for OpenSM.
+
+%package static
+Summary: Static version of the opensm libraries
+Group: System Environment/Libraries
+Requires: %{name}-libs = %{version}-%{release} libibumad-devel
+
+%description static
+Static version of the opensm libraries
+
+%prep
+%setup -q
+
+%build
+%configure \
+        %{?_enable_console_socket} \
+        %{?_disable_console_socket} \
+        %{?_enable_perf_mgr} \
+        %{?_disable_perf_mgr} \
+        %{?_enable_event_plugin} \
+        %{?_disable_event_plugin}
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make DESTDIR=$RPM_BUILD_ROOT install
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+etc=$RPM_BUILD_ROOT%{_sysconfdir}
+mkdir -p ${RPM_BUILD_ROOT}/var/cache/opensm
+if [ -f /etc/redhat-release -o -s /etc/redhat-release ]; then
+    REDHAT="redhat-"
+else
+    REDHAT=""
+fi
+mkdir -p $etc/{init.d,logrotate.d} $etc/@OPENSM_CONFIG_SUB_DIR@
+install -m 755 scripts/${REDHAT}opensm.init $etc/init.d/opensmd
+install -D -m 644 scripts/opensm.logrotate $etc/logrotate.d/opensm
+install -m 755 scripts/sldd.sh $RPM_BUILD_ROOT%{_sbindir}/sldd.sh
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if [ $1 = 1 ]; then
+    /sbin/chkconfig --add opensmd
+else
+    /sbin/service opensmd condrestart
+fi
+
+%preun
+if [ $1 = 0 ]; then
+    /sbin/service opensmd stop
+    /sbin/chkconfig --del opensmd
+    rm -f /var/cache/opensm/*
+fi
+
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+%{_sbindir}/opensm
+%{_sbindir}/osmtest
+%{_mandir}/man8/*
+%doc AUTHORS COPYING README doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt doc/opensm_release_notes-3.2.txt
+%{_sysconfdir}/init.d/opensmd
+%{_sbindir}/sldd.sh
+%config(noreplace) %{_sysconfdir}/logrotate.d/opensm
+%dir /var/cache/opensm
+%dir %{_sysconfdir}/@OPENSM_CONFIG_SUB_DIR@
+
+%files libs
+%defattr(-,root,root,-)
+%{_libdir}/*.so.*
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/infiniband/*
+%{_libdir}/*.so
+
+%files static
+%defattr(-,root,root,-)
+%{_libdir}/*.a
+
diff --git a/opensm/ChangeLog b/opensm/ChangeLog
new file mode 100644
index 0000000..97eb67a
--- /dev/null
+++ b/opensm/ChangeLog
@@ -0,0 +1,115 @@
+2007-07-11 Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump to version 2.2.1
+
+2007-06-20 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Add 3LeafNetworks and Xsigo to osm_get_manufacturer_str
+
+2007-06-15 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_helper.c: Fix PortInfo:CapMask printing when CapMask is 0
+
+2007-06-11 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_helper.c: Remove OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED
+	  from __osm_sm_mgr_signal_str
+
+2007-06-06 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_helper.c: More optimally deal with manufacturer strings
+
+2007-06-06 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Add Sun to osm_get_manufacturer_str
+
+2007-06-04 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Add 8x to __osm_lwa_str_fixed_width
+
+2007-05-07 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_helper.c: Remove repeated strlen() calls
+
+2007-04-27 Ira K. Weiny <weiny2 at llnl.gov>
+
+	* osm_helper.c: In osm_dump_notice, use ib_get_producer_type_str
+	  for printing producer type
+
+2007-04-26 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Clarify the proper usage of
+	  osm_get_node_type_str_fixed_width to take uint8_t rather
+	  than uint32_t for node_type argument
+
+2007-04-25 Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
+
+	* osm_helper.c: Fix problematic usage of sprintf() when
+	  source and destination strings overlap.
+
+2007-04-24 Albert L. Chu <chu11 at llnl.gov>
+
+	* osm_helper.c: In osm_get_node_type_str_fixed_width, fix
+	  both range limit and endian of node type check
+
+2007-03-29 Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.2.0
+
+2007-03-21 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_log.c: Changed to support daemon mode
+
+2007-03-01 Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.1.2
+
+	* osm_helper.c: Eliminate extraneous comma in __osm_disp_msg_ string
+	  for OSM_MSG_MAD_PORT_INFO
+
+2007-02-26 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_log.c: Minor optimization to previous change to osm_log
+	  for also flushing on OSM_LOG_SYS
+
+2007-02-26 Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
+
+	* osm_log.c: In osm_log, flush log on OSM_LOG_SYS (as well
+	  as OSM_LOG_ERROR)
+
+2007-02-20 Hal Rosenstock <halr at voltaire.com>
+
+	* configure.in: Bump version to 2.1.1
+
+	* osm_helper.c: In osm_dbg_get_capabilities_str, only display
+	  Capability Mask if there are capabilities present
+
+2007-01-22 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Change DR path format from [%X] to %d,
+
+2007-01-08 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_log.c: Add osm_log_reopen_file API
+
+2006-12-22 Hal Rosenstock <halr at voltaire.com>
+
+	* osm_helper.c: Add osm_dump_switch_info_record API
+
+2006-11-03 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_log.c: Add osm_log_printf API
+
+2006-10-30 Sasha Khapyorsky <sashak at voltaire.com>
+
+	* osm_helper.c: Fix seg fault with strings which
+	  might not be null terminated
+
+2006-10-18 Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
+
+	* osm_log.c: Windows porting changes
+
+2006-09-19 Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
+
+	* osm_log.c: Windows porting changes
+
diff --git a/opensm/Makefile.am b/opensm/Makefile.am
new file mode 100644
index 0000000..01573d2
--- /dev/null
+++ b/opensm/Makefile.am
@@ -0,0 +1,132 @@
+
+INCLUDES = $(OSMV_INCLUDES)
+
+AM_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+
+lib_LTLIBRARIES = libopensm.la
+
+if DEBUG
+DBGFLAGS = -ggdb -D_DEBUG_
+else
+DBGFLAGS = -g
+endif
+
+if HAVE_LD_VERSION_SCRIPT
+libopensm_version_script = -Wl,--version-script=$(srcdir)/libopensm.map
+else
+libopensm_version_script =
+endif
+
+opensm_api_version=$(shell grep LIBVERSION= $(srcdir)/libopensm.ver | sed 's/LIBVERSION=//')
+
+libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c
+libopensm_la_LDFLAGS = -version-info $(opensm_api_version) \
+	-export-dynamic $(libopensm_version_script)
+libopensm_la_DEPENDENCIES = $(srcdir)/libopensm.map
+
+sbin_PROGRAMS = opensm
+opensm_DEPENDENCIES = libopensm.la
+opensm_SOURCES = main.c osm_console_io.c osm_console.c osm_db_files.c \
+		 osm_db_pack.c osm_drop_mgr.c \
+		 osm_inform.c osm_lid_mgr.c osm_lin_fwd_rcv.c \
+		 osm_link_mgr.c osm_mcast_fwd_rcv.c \
+		 osm_mcast_mgr.c osm_mcast_tbl.c osm_mcm_info.c \
+		 osm_mcm_port.c osm_mtree.c osm_multicast.c osm_node.c \
+		 osm_node_desc_rcv.c osm_node_info_rcv.c \
+		 osm_opensm.c osm_pkey.c osm_pkey_mgr.c osm_pkey_rcv.c \
+		 osm_port.c osm_port_info_rcv.c \
+		 osm_remote_sm.c osm_req.c \
+		 osm_resp.c osm_sa.c osm_sa_class_port_info.c \
+		 osm_sa_informinfo.c osm_sa_lft_record.c osm_sa_mft_record.c \
+		 osm_sa_link_record.c osm_sa_mad_ctrl.c \
+		 osm_sa_mcmember_record.c osm_sa_node_record.c \
+		 osm_sa_path_record.c osm_sa_pkey_record.c \
+		 osm_sa_portinfo_record.c osm_sa_guidinfo_record.c \
+		 osm_sa_multipath_record.c \
+		 osm_sa_service_record.c osm_sa_slvl_record.c \
+		 osm_sa_sminfo_record.c osm_sa_vlarb_record.c \
+		 osm_sa_sw_info_record.c osm_service.c \
+		 osm_slvl_map_rcv.c osm_sm.c osm_sminfo_rcv.c \
+		 osm_sm_mad_ctrl.c osm_sm_state_mgr.c osm_state_mgr.c \
+		 osm_subnet.c osm_sw_info_rcv.c osm_switch.c \
+		 osm_prtn.c osm_prtn_config.c osm_qos.c osm_router.c \
+		 osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_updn.c \
+		 osm_ucast_lash.c osm_ucast_file.c osm_ucast_ftree.c \
+		 osm_vl15intf.c osm_vl_arb_rcv.c \
+		 st.c osm_perfmgr.c osm_perfmgr_db.c \
+		 osm_event_plugin.c osm_dump.c osm_ucast_cache.c \
+		 osm_qos_parser_y.y osm_qos_parser_l.l osm_qos_policy.c
+
+AM_YFLAGS:= -d
+
+# we need to be able to load libraries from local build subtree before make install
+# we always give precedence to local tree libs and then use the pre-installed ones.
+opensm_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L. -lopensm $(OSMV_LDADD)
+
+opensmincludedir = $(includedir)/infiniband/opensm
+
+opensminclude_HEADERS = \
+	$(srcdir)/../include/opensm/osm_attrib_req.h \
+	$(srcdir)/../include/opensm/osm_base.h \
+	$(srcdir)/../include/opensm/osm_console.h \
+	$(srcdir)/../include/opensm/osm_console_io.h \
+	$(srcdir)/../include/opensm/osm_db.h \
+	$(srcdir)/../include/opensm/osm_db_pack.h \
+	$(srcdir)/../include/opensm/osm_event_plugin.h \
+	$(srcdir)/../include/opensm/osm_errors.h \
+	$(srcdir)/../include/opensm/osm_helper.h \
+	$(srcdir)/../include/opensm/osm_inform.h \
+	$(srcdir)/../include/opensm/osm_lid_mgr.h \
+	$(srcdir)/../include/opensm/osm_log.h \
+	$(srcdir)/../include/opensm/osm_mad_pool.h \
+	$(srcdir)/../include/opensm/osm_madw.h \
+	$(srcdir)/../include/opensm/osm_mcast_tbl.h \
+	$(srcdir)/../include/opensm/osm_mcm_info.h \
+	$(srcdir)/../include/opensm/osm_mcm_port.h \
+	$(srcdir)/../include/opensm/osm_mtree.h \
+	$(srcdir)/../include/opensm/osm_multicast.h \
+	$(srcdir)/../include/opensm/osm_msgdef.h \
+	$(srcdir)/../include/opensm/osm_node.h \
+	$(srcdir)/../include/opensm/osm_opensm.h \
+	$(srcdir)/../include/opensm/osm_partition.h \
+	$(srcdir)/../include/opensm/osm_path.h \
+	$(srcdir)/../include/opensm/osm_perfmgr.h \
+	$(srcdir)/../include/opensm/osm_perfmgr_db.h \
+	$(srcdir)/../include/opensm/osm_pkey.h \
+	$(srcdir)/../include/opensm/osm_pkey_mgr.h \
+	$(srcdir)/../include/opensm/osm_port.h \
+	$(srcdir)/../include/opensm/osm_port_profile.h \
+	$(srcdir)/../include/opensm/osm_prefix_route.h \
+	$(srcdir)/../include/opensm/osm_qos_policy.h \
+	$(srcdir)/../include/opensm/osm_remote_sm.h \
+	$(srcdir)/../include/opensm/osm_router.h \
+	$(srcdir)/../include/opensm/osm_sa.h \
+	$(srcdir)/../include/opensm/osm_sa_mad_ctrl.h \
+	$(srcdir)/../include/opensm/osm_service.h \
+	$(srcdir)/../include/opensm/osm_sm.h \
+	$(srcdir)/../include/opensm/osm_sm_mad_ctrl.h \
+	$(srcdir)/../include/opensm/st.h \
+	$(srcdir)/../include/opensm/osm_stats.h \
+	$(srcdir)/../include/opensm/osm_subnet.h \
+	$(srcdir)/../include/opensm/osm_switch.h \
+	$(srcdir)/../include/opensm/osm_ucast_mgr.h \
+	$(srcdir)/../include/opensm/osm_ucast_cache.h \
+	$(srcdir)/../include/opensm/osm_vl15intf.h \
+	$(top_builddir)/include/opensm/osm_version.h \
+	$(top_builddir)/include/opensm/osm_config.h
+
+BUILT_SOURCES = osm_version osm_qos_parser_y.h
+osm_version:
+	if [ -x $(top_srcdir)/../gen_ver.sh ] ; then \
+		ver_file=$(top_builddir)/include/opensm/osm_version.h ; \
+		osm_ver=`cat $$ver_file | sed -ne '/#define OSM_VERSION /s/^.*\"OpenSM \(.*\)\"$$/\1/p'` ; \
+		ver=`$(top_srcdir)/../gen_ver.sh $(PACKAGE)` ; \
+		if [ $$ver != $$osm_ver ] ; then \
+			cat $$ver_file | sed -e '/#define OSM_VERSION /s/\"OpenSM .*\"/\"OpenSM '$$ver'\"/' > tmp_new_version ; \
+			cat tmp_new_version > $$ver_file && rm -f tmp_new_version ; \
+		fi ; \
+	fi
+
+# files distributed as part of the srcdir
+EXTRA_DIST = $(srcdir)/libopensm.map $(srcdir)/libopensm.ver \
+	     $(srcdir)/ChangeLog
diff --git a/opensm/Makefile.in b/opensm/Makefile.in
new file mode 100644
index 0000000..f1952ca
--- /dev/null
+++ b/opensm/Makefile.in
@@ -0,0 +1,816 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = opensm$(EXEEXT)
+subdir = opensm
+DIST_COMMON = $(opensminclude_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in ChangeLog osm_qos_parser_l.c \
+	osm_qos_parser_y.c osm_qos_parser_y.h
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" \
+	"$(DESTDIR)$(opensmincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libopensm_la_LIBADD =
+am_libopensm_la_OBJECTS = osm_log.lo osm_mad_pool.lo osm_helper.lo
+libopensm_la_OBJECTS = $(am_libopensm_la_OBJECTS)
+libopensm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(libopensm_la_LDFLAGS) $(LDFLAGS) -o $@
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(sbin_PROGRAMS)
+am_opensm_OBJECTS = main.$(OBJEXT) osm_console_io.$(OBJEXT) \
+	osm_console.$(OBJEXT) osm_db_files.$(OBJEXT) \
+	osm_db_pack.$(OBJEXT) osm_drop_mgr.$(OBJEXT) \
+	osm_inform.$(OBJEXT) osm_lid_mgr.$(OBJEXT) \
+	osm_lin_fwd_rcv.$(OBJEXT) osm_link_mgr.$(OBJEXT) \
+	osm_mcast_fwd_rcv.$(OBJEXT) osm_mcast_mgr.$(OBJEXT) \
+	osm_mcast_tbl.$(OBJEXT) osm_mcm_info.$(OBJEXT) \
+	osm_mcm_port.$(OBJEXT) osm_mtree.$(OBJEXT) \
+	osm_multicast.$(OBJEXT) osm_node.$(OBJEXT) \
+	osm_node_desc_rcv.$(OBJEXT) osm_node_info_rcv.$(OBJEXT) \
+	osm_opensm.$(OBJEXT) osm_pkey.$(OBJEXT) osm_pkey_mgr.$(OBJEXT) \
+	osm_pkey_rcv.$(OBJEXT) osm_port.$(OBJEXT) \
+	osm_port_info_rcv.$(OBJEXT) osm_remote_sm.$(OBJEXT) \
+	osm_req.$(OBJEXT) osm_resp.$(OBJEXT) osm_sa.$(OBJEXT) \
+	osm_sa_class_port_info.$(OBJEXT) osm_sa_informinfo.$(OBJEXT) \
+	osm_sa_lft_record.$(OBJEXT) osm_sa_mft_record.$(OBJEXT) \
+	osm_sa_link_record.$(OBJEXT) osm_sa_mad_ctrl.$(OBJEXT) \
+	osm_sa_mcmember_record.$(OBJEXT) osm_sa_node_record.$(OBJEXT) \
+	osm_sa_path_record.$(OBJEXT) osm_sa_pkey_record.$(OBJEXT) \
+	osm_sa_portinfo_record.$(OBJEXT) \
+	osm_sa_guidinfo_record.$(OBJEXT) \
+	osm_sa_multipath_record.$(OBJEXT) \
+	osm_sa_service_record.$(OBJEXT) osm_sa_slvl_record.$(OBJEXT) \
+	osm_sa_sminfo_record.$(OBJEXT) osm_sa_vlarb_record.$(OBJEXT) \
+	osm_sa_sw_info_record.$(OBJEXT) osm_service.$(OBJEXT) \
+	osm_slvl_map_rcv.$(OBJEXT) osm_sm.$(OBJEXT) \
+	osm_sminfo_rcv.$(OBJEXT) osm_sm_mad_ctrl.$(OBJEXT) \
+	osm_sm_state_mgr.$(OBJEXT) osm_state_mgr.$(OBJEXT) \
+	osm_subnet.$(OBJEXT) osm_sw_info_rcv.$(OBJEXT) \
+	osm_switch.$(OBJEXT) osm_prtn.$(OBJEXT) \
+	osm_prtn_config.$(OBJEXT) osm_qos.$(OBJEXT) \
+	osm_router.$(OBJEXT) osm_trap_rcv.$(OBJEXT) \
+	osm_ucast_mgr.$(OBJEXT) osm_ucast_updn.$(OBJEXT) \
+	osm_ucast_lash.$(OBJEXT) osm_ucast_file.$(OBJEXT) \
+	osm_ucast_ftree.$(OBJEXT) osm_vl15intf.$(OBJEXT) \
+	osm_vl_arb_rcv.$(OBJEXT) st.$(OBJEXT) osm_perfmgr.$(OBJEXT) \
+	osm_perfmgr_db.$(OBJEXT) osm_event_plugin.$(OBJEXT) \
+	osm_dump.$(OBJEXT) osm_ucast_cache.$(OBJEXT) \
+	osm_qos_parser_y.$(OBJEXT) osm_qos_parser_l.$(OBJEXT) \
+	osm_qos_policy.$(OBJEXT)
+opensm_OBJECTS = $(am_opensm_OBJECTS)
+am__DEPENDENCIES_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/config/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+SOURCES = $(libopensm_la_SOURCES) $(opensm_SOURCES)
+DIST_SOURCES = $(libopensm_la_SOURCES) $(opensm_SOURCES)
+opensmincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(opensminclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = $(OSMV_INCLUDES)
+AM_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+lib_LTLIBRARIES = libopensm.la
+ at DEBUG_FALSE@DBGFLAGS = -g
+ at DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_
+ at HAVE_LD_VERSION_SCRIPT_FALSE@libopensm_version_script = 
+ at HAVE_LD_VERSION_SCRIPT_TRUE@libopensm_version_script = -Wl,--version-script=$(srcdir)/libopensm.map
+opensm_api_version = $(shell grep LIBVERSION= $(srcdir)/libopensm.ver | sed 's/LIBVERSION=//')
+libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c
+libopensm_la_LDFLAGS = -version-info $(opensm_api_version) \
+	-export-dynamic $(libopensm_version_script)
+
+libopensm_la_DEPENDENCIES = $(srcdir)/libopensm.map
+opensm_DEPENDENCIES = libopensm.la
+opensm_SOURCES = main.c osm_console_io.c osm_console.c osm_db_files.c \
+		 osm_db_pack.c osm_drop_mgr.c \
+		 osm_inform.c osm_lid_mgr.c osm_lin_fwd_rcv.c \
+		 osm_link_mgr.c osm_mcast_fwd_rcv.c \
+		 osm_mcast_mgr.c osm_mcast_tbl.c osm_mcm_info.c \
+		 osm_mcm_port.c osm_mtree.c osm_multicast.c osm_node.c \
+		 osm_node_desc_rcv.c osm_node_info_rcv.c \
+		 osm_opensm.c osm_pkey.c osm_pkey_mgr.c osm_pkey_rcv.c \
+		 osm_port.c osm_port_info_rcv.c \
+		 osm_remote_sm.c osm_req.c \
+		 osm_resp.c osm_sa.c osm_sa_class_port_info.c \
+		 osm_sa_informinfo.c osm_sa_lft_record.c osm_sa_mft_record.c \
+		 osm_sa_link_record.c osm_sa_mad_ctrl.c \
+		 osm_sa_mcmember_record.c osm_sa_node_record.c \
+		 osm_sa_path_record.c osm_sa_pkey_record.c \
+		 osm_sa_portinfo_record.c osm_sa_guidinfo_record.c \
+		 osm_sa_multipath_record.c \
+		 osm_sa_service_record.c osm_sa_slvl_record.c \
+		 osm_sa_sminfo_record.c osm_sa_vlarb_record.c \
+		 osm_sa_sw_info_record.c osm_service.c \
+		 osm_slvl_map_rcv.c osm_sm.c osm_sminfo_rcv.c \
+		 osm_sm_mad_ctrl.c osm_sm_state_mgr.c osm_state_mgr.c \
+		 osm_subnet.c osm_sw_info_rcv.c osm_switch.c \
+		 osm_prtn.c osm_prtn_config.c osm_qos.c osm_router.c \
+		 osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_updn.c \
+		 osm_ucast_lash.c osm_ucast_file.c osm_ucast_ftree.c \
+		 osm_vl15intf.c osm_vl_arb_rcv.c \
+		 st.c osm_perfmgr.c osm_perfmgr_db.c \
+		 osm_event_plugin.c osm_dump.c osm_ucast_cache.c \
+		 osm_qos_parser_y.y osm_qos_parser_l.l osm_qos_policy.c
+
+AM_YFLAGS := -d
+
+# we need to be able to load libraries from local build subtree before make install
+# we always give precedence to local tree libs and then use the pre-installed ones.
+opensm_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L. -lopensm $(OSMV_LDADD)
+opensmincludedir = $(includedir)/infiniband/opensm
+opensminclude_HEADERS = \
+	$(srcdir)/../include/opensm/osm_attrib_req.h \
+	$(srcdir)/../include/opensm/osm_base.h \
+	$(srcdir)/../include/opensm/osm_console.h \
+	$(srcdir)/../include/opensm/osm_console_io.h \
+	$(srcdir)/../include/opensm/osm_db.h \
+	$(srcdir)/../include/opensm/osm_db_pack.h \
+	$(srcdir)/../include/opensm/osm_event_plugin.h \
+	$(srcdir)/../include/opensm/osm_errors.h \
+	$(srcdir)/../include/opensm/osm_helper.h \
+	$(srcdir)/../include/opensm/osm_inform.h \
+	$(srcdir)/../include/opensm/osm_lid_mgr.h \
+	$(srcdir)/../include/opensm/osm_log.h \
+	$(srcdir)/../include/opensm/osm_mad_pool.h \
+	$(srcdir)/../include/opensm/osm_madw.h \
+	$(srcdir)/../include/opensm/osm_mcast_tbl.h \
+	$(srcdir)/../include/opensm/osm_mcm_info.h \
+	$(srcdir)/../include/opensm/osm_mcm_port.h \
+	$(srcdir)/../include/opensm/osm_mtree.h \
+	$(srcdir)/../include/opensm/osm_multicast.h \
+	$(srcdir)/../include/opensm/osm_msgdef.h \
+	$(srcdir)/../include/opensm/osm_node.h \
+	$(srcdir)/../include/opensm/osm_opensm.h \
+	$(srcdir)/../include/opensm/osm_partition.h \
+	$(srcdir)/../include/opensm/osm_path.h \
+	$(srcdir)/../include/opensm/osm_perfmgr.h \
+	$(srcdir)/../include/opensm/osm_perfmgr_db.h \
+	$(srcdir)/../include/opensm/osm_pkey.h \
+	$(srcdir)/../include/opensm/osm_pkey_mgr.h \
+	$(srcdir)/../include/opensm/osm_port.h \
+	$(srcdir)/../include/opensm/osm_port_profile.h \
+	$(srcdir)/../include/opensm/osm_prefix_route.h \
+	$(srcdir)/../include/opensm/osm_qos_policy.h \
+	$(srcdir)/../include/opensm/osm_remote_sm.h \
+	$(srcdir)/../include/opensm/osm_router.h \
+	$(srcdir)/../include/opensm/osm_sa.h \
+	$(srcdir)/../include/opensm/osm_sa_mad_ctrl.h \
+	$(srcdir)/../include/opensm/osm_service.h \
+	$(srcdir)/../include/opensm/osm_sm.h \
+	$(srcdir)/../include/opensm/osm_sm_mad_ctrl.h \
+	$(srcdir)/../include/opensm/st.h \
+	$(srcdir)/../include/opensm/osm_stats.h \
+	$(srcdir)/../include/opensm/osm_subnet.h \
+	$(srcdir)/../include/opensm/osm_switch.h \
+	$(srcdir)/../include/opensm/osm_ucast_mgr.h \
+	$(srcdir)/../include/opensm/osm_ucast_cache.h \
+	$(srcdir)/../include/opensm/osm_vl15intf.h \
+	$(top_builddir)/include/opensm/osm_version.h \
+	$(top_builddir)/include/opensm/osm_config.h
+
+BUILT_SOURCES = osm_version osm_qos_parser_y.h
+
+# files distributed as part of the srcdir
+EXTRA_DIST = $(srcdir)/libopensm.map $(srcdir)/libopensm.ver \
+	     $(srcdir)/ChangeLog
+
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  opensm/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  opensm/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libopensm.la: $(libopensm_la_OBJECTS) $(libopensm_la_DEPENDENCIES) 
+	$(libopensm_la_LINK) -rpath $(libdir) $(libopensm_la_OBJECTS) $(libopensm_la_LIBADD) $(LIBS)
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+	done
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+osm_qos_parser_y.h: osm_qos_parser_y.c
+	@if test ! -f $@; then \
+	  rm -f osm_qos_parser_y.c; \
+	  $(MAKE) $(AM_MAKEFLAGS) osm_qos_parser_y.c; \
+	else :; fi
+opensm$(EXEEXT): $(opensm_OBJECTS) $(opensm_DEPENDENCIES) 
+	@rm -f opensm$(EXEEXT)
+	$(LINK) $(opensm_OBJECTS) $(opensm_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_console.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_console_io.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_db_files.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_db_pack.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_drop_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_event_plugin.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_helper.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_inform.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_lid_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_lin_fwd_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_link_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_log.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mad_pool.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mcast_fwd_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mcast_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mcast_tbl.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mcm_info.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mcm_port.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_mtree.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_multicast.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_node.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_node_desc_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_node_info_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_opensm.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_perfmgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_perfmgr_db.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_pkey.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_pkey_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_pkey_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_port.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_port_info_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_prtn.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_prtn_config.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_qos.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_qos_parser_l.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_qos_parser_y.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_qos_policy.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_remote_sm.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_req.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_resp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_router.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_class_port_info.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_guidinfo_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_informinfo.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_lft_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_link_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_mad_ctrl.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_mcmember_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_mft_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_multipath_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_node_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_path_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_pkey_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_portinfo_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_service_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_slvl_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_sminfo_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_sw_info_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sa_vlarb_record.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_service.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_slvl_map_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sm.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sm_mad_ctrl.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sm_state_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sminfo_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_state_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_subnet.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_sw_info_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_switch.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_trap_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_cache.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_file.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_ftree.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_lash.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_mgr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_ucast_updn.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_vl15intf.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osm_vl_arb_rcv.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/st.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+	$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+	$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-opensmincludeHEADERS: $(opensminclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(opensmincludedir)" || $(MKDIR_P) "$(DESTDIR)$(opensmincludedir)"
+	@list='$(opensminclude_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(opensmincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(opensmincludedir)/$$f'"; \
+	  $(opensmincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(opensmincludedir)/$$f"; \
+	done
+
+uninstall-opensmincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(opensminclude_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(opensmincludedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(opensmincludedir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(opensmincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-rm -f osm_qos_parser_l.c
+	-rm -f osm_qos_parser_y.c
+	-rm -f osm_qos_parser_y.h
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-opensmincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-opensmincludeHEADERS \
+	uninstall-sbinPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS ctags \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-libLTLIBRARIES install-man \
+	install-opensmincludeHEADERS install-pdf install-pdf-am \
+	install-ps install-ps-am install-sbinPROGRAMS install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-libLTLIBRARIES \
+	uninstall-opensmincludeHEADERS uninstall-sbinPROGRAMS
+
+osm_version:
+	if [ -x $(top_srcdir)/../gen_ver.sh ] ; then \
+		ver_file=$(top_builddir)/include/opensm/osm_version.h ; \
+		osm_ver=`cat $$ver_file | sed -ne '/#define OSM_VERSION /s/^.*\"OpenSM \(.*\)\"$$/\1/p'` ; \
+		ver=`$(top_srcdir)/../gen_ver.sh $(PACKAGE)` ; \
+		if [ $$ver != $$osm_ver ] ; then \
+			cat $$ver_file | sed -e '/#define OSM_VERSION /s/\"OpenSM .*\"/\"OpenSM '$$ver'\"/' > tmp_new_version ; \
+			cat tmp_new_version > $$ver_file && rm -f tmp_new_version ; \
+		fi ; \
+	fi
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/opensm/libopensm.map b/opensm/libopensm.map
new file mode 100644
index 0000000..7cd2aba
--- /dev/null
+++ b/opensm/libopensm.map
@@ -0,0 +1,59 @@
+OPENSM_1.5 {
+	global:
+		osm_log;
+		osm_log_msg_box;
+		osm_is_debug;
+		osm_log_init;
+		osm_log_init_v2;
+		osm_log_reopen_file;
+		osm_mad_pool_construct;
+		osm_mad_pool_destroy;
+		osm_mad_pool_init;
+		osm_mad_pool_get;
+		osm_mad_pool_put;
+		osm_mad_pool_get_wrapper;
+		osm_mad_pool_get_wrapper_raw;
+		ib_get_sa_method_str;
+		ib_get_sm_method_str;
+		ib_get_sm_attr_str;
+		ib_get_sa_attr_str;
+		ib_get_trap_str;
+		osm_dump_port_info;
+		osm_dump_portinfo_record;
+		osm_dump_guidinfo_record;
+		osm_dump_node_info;
+		osm_dump_node_record;
+		osm_dump_path_record;
+		osm_dump_multipath_record;
+		osm_dump_mc_record;
+		osm_dump_service_record;
+		osm_dump_inform_info;
+		osm_dump_inform_info_record;
+		osm_dump_link_record;
+		osm_dump_switch_info;
+		osm_dump_switch_info_record;
+		osm_dump_pkey_table;
+		osm_dump_slvl_map_table;
+		osm_dump_vl_arb_table;
+		osm_dump_sm_info;
+		osm_dump_sm_info_record;
+		osm_dump_notice;
+		osm_dump_dr_smp;
+		osm_dump_sa_mad;
+		osm_dump_dr_path;
+		osm_dump_smp_dr_path;
+		osm_dump_pkey_block;
+		osm_log_raw;
+		osm_get_sm_state_str;
+		osm_get_sm_signal_str;
+		osm_get_disp_msg_str;
+		osm_get_port_state_str_fixed_width;
+		osm_get_node_type_str_fixed_width;
+		osm_get_manufacturer_str;
+		osm_get_mtu_str;
+		osm_get_lwa_str;
+		osm_get_lsa_str;
+		osm_get_sm_mgr_signal_str;
+		osm_get_sm_mgr_state_str;
+	local: *;
+};
diff --git a/opensm/libopensm.ver b/opensm/libopensm.ver
new file mode 100644
index 0000000..f552dd0
--- /dev/null
+++ b/opensm/libopensm.ver
@@ -0,0 +1,9 @@
+# In this file we track the current API version
+# of the opensm common interface (and libraries)
+# The version is built of the following
+# tree numbers:
+# API_REV:RUNNING_REV:AGE
+# API_REV - advance on any added API
+# RUNNING_REV - advance any change to the vendor files
+# AGE - number of backward versions the API still supports
+LIBVERSION=3:3:1
diff --git a/opensm/main.c b/opensm/main.c
new file mode 100644
index 0000000..999e92f
--- /dev/null
+++ b/opensm/main.c
@@ -0,0 +1,1027 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Command line interface for opensm.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <complib/cl_types.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_console.h>
+#include <opensm/osm_console_io.h>
+#include <opensm/osm_perfmgr.h>
+
+volatile unsigned int osm_exit_flag = 0;
+
+static volatile unsigned int osm_hup_flag = 0;
+static volatile unsigned int osm_usr1_flag = 0;
+
+#define GUID_ARRAY_SIZE 64
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+static void mark_exit_flag(int signum)
+{
+	if (!osm_exit_flag)
+		printf("OpenSM: Got signal %d - exiting...\n", signum);
+	osm_exit_flag = 1;
+}
+
+static void mark_hup_flag(int signum)
+{
+	osm_hup_flag = 1;
+}
+
+static void mark_usr1_flag(int signum)
+{
+	osm_usr1_flag = 1;
+}
+
+static sigset_t saved_sigset;
+
+static void block_signals()
+{
+	sigset_t set;
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGINT);
+	sigaddset(&set, SIGTERM);
+	sigaddset(&set, SIGHUP);
+#ifndef HAVE_OLD_LINUX_THREADS
+	sigaddset(&set, SIGUSR1);
+#endif
+	pthread_sigmask(SIG_SETMASK, &set, &saved_sigset);
+}
+
+static void setup_signals()
+{
+	struct sigaction act;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = mark_exit_flag;
+	act.sa_flags = 0;
+	sigaction(SIGINT, &act, NULL);
+	sigaction(SIGTERM, &act, NULL);
+	act.sa_handler = mark_hup_flag;
+	sigaction(SIGHUP, &act, NULL);
+	sigaction(SIGCONT, &act, NULL);
+#ifndef HAVE_OLD_LINUX_THREADS
+	act.sa_handler = mark_usr1_flag;
+	sigaction(SIGUSR1, &act, NULL);
+#endif
+	pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void show_usage(void)
+{
+	printf("\n------- OpenSM - Usage and options ----------------------\n");
+	printf("Usage:   opensm [options]\n");
+	printf("Options:\n");
+	printf("--version\n          Prints OpenSM version and exits.\n\n");
+	printf("--config, -F <file-name>\n"
+	       "          The name of the OpenSM config file. When not specified\n"
+	       "          " OSM_DEFAULT_CONFIG_FILE " will be used (if exists).\n\n");
+	printf("--create-config, -c <file-name>\n"
+	       "          OpenSM will dump its configuration to the specified file and exit.\n"
+	       "          This is a way to generate OpenSM configuration file template.\n\n");
+	printf("--guid, -g <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("--lmc, -l <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("--priority, -p <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.  Range goes\n"
+	       "          from 0 (lowest priority) to 15 (highest).\n\n");
+	printf("--smkey, -k <SM_Key>\n"
+	       "          This option specifies the SM's SM_Key (64 bits).\n"
+	       "          This will effect SM authentication.\n"
+	       "          Note that OpenSM version 3.2.1 and below used the\n"
+	       "          default value '1' in a host byte order, it is fixed\n"
+	       "          now but you may need this option to interoperate\n"
+	       "          with old OpenSM running on a little endian machine.\n\n");
+	printf("--reassign_lids, -r\n"
+	       "          This option causes OpenSM to reassign LIDs to all\n"
+	       "          end nodes. Specifying -r on a running subnet\n"
+	       "          may disrupt subnet traffic.\n"
+	       "          Without -r, OpenSM attempts to preserve existing\n"
+	       "          LID assignments resolving multiple use of same LID.\n\n");
+	printf("--routing_engine, -R <engine name>\n"
+	       "          This option chooses routing engine(s) to use instead of default\n"
+	       "          Min Hop algorithm.  Multiple routing engines can be specified\n"
+	       "          separated by commas so that specific ordering of routing\n"
+	       "          algorithms will be tried if earlier routing engines fail.\n"
+	       "          Supported engines: updn, file, ftree, lash, dor\n\n");
+	printf("--connect_roots, -z\n"
+	       "          This option enforces a routing engine (currently\n"
+	       "          up/down only) to make connectivity between root switches\n"
+	       "          and in this way be IBA compliant. In many cases,\n"
+	       "          this can violate \"pure\" deadlock free algorithm, so\n"
+	       "          use it carefully.\n\n");
+	printf("--ucast_cache, -A\n"
+	       "          This option enables unicast routing cache to prevent\n"
+	       "          routing recalculation (which is a heavy task in a\n"
+	       "          large cluster) when there was no topology change\n"
+	       "          detected during the heavy sweep, or when the topology\n"
+	       "          change does not require new routing calculation,\n"
+	       "          e.g. in case of host reboot.\n"
+	       "          This option becomes very handy when the cluster size\n"
+	       "          is thousands of nodes.\n\n");
+	printf("--lid_matrix_file, -M <file name>\n"
+	       "          This option specifies the name of the lid matrix dump file\n"
+	       "          from where switch lid matrices (min hops tables will be\n"
+	       "          loaded.\n\n");
+	printf("--lfts_file, -U <file name>\n"
+	       "          This option specifies the name of the LFTs file\n"
+	       "          from where switch forwarding tables will be loaded.\n\n");
+	printf("--sadb_file, -S <file name>\n"
+	       "          This option specifies the name of the SA DB dump file\n"
+	       "          from where SA database will be loaded.\n\n");
+	printf("--root_guid_file, -a <path to file>\n"
+	       "          Set the root nodes for the Up/Down or Fat-Tree routing\n"
+	       "          algorithm to the guids provided in the given file (one\n"
+	       "          to a line)\n" "\n");
+	printf("--cn_guid_file, -u <path to file>\n"
+	       "          Set the compute nodes for the Fat-Tree routing algorithm\n"
+	       "          to the guids provided in the given file (one to a line)\n\n");
+	printf("--ids_guid_file, -m <path to file>\n"
+	       "          Name of the map file with set of the IDs which will be used\n"
+	       "          by Up/Down routing algorithm instead of node GUIDs\n"
+	       "          (format: <guid> <id> per line)\n\n");
+	printf("--guid_routing_order_file, -X <path to file>\n"
+	       "          Set the order port guids will be routed for the MinHop\n"
+	       "          and Up/Down routing algorithms to the guids provided in the\n"
+	       "          given file (one to a line)\n\n");
+	printf("--once, -o\n"
+	       "          This option causes OpenSM to configure the subnet\n"
+	       "          once, then exit.  Ports remain in the ACTIVE state.\n\n");
+	printf("--sweep, -s <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("--timeout, -t <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, -n <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("--console, -q [off|local"
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	       "|socket|loopback"
+#endif
+	       "]\n          This option activates the OpenSM console (default off).\n\n");
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	printf("--console-port, -C <port>\n"
+	       "          Specify an alternate telnet port for the console (default %d).\n\n",
+	       OSM_DEFAULT_CONSOLE_PORT);
+#endif
+	printf("--ignore-guids, -i <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("--honor_guid2lid, -x\n"
+	       "          This option forces OpenSM to honor the guid2lid file,\n"
+	       "          when it comes out of Standby state, if such file exists\n"
+	       "          under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n");
+	printf("--log_file, -f <log-file-name>\n"
+	       "          This option defines the log to be the given file.\n"
+	       "          By default, the log goes to /var/log/opensm.log.\n"
+	       "          For the log to go to standard output use -f stdout.\n\n");
+	printf("--log_limit, -L <size in MB>\n"
+	       "          This option defines maximal log file size in MB. When\n"
+	       "          specified the log file will be truncated upon reaching\n"
+	       "          this limit.\n\n");
+	printf("--erase_log_file, -e\n"
+	       "          This option will cause deletion of the log file\n"
+	       "          (if it previously exists). By default, the log file\n"
+	       "          is accumulative.\n\n");
+	printf("--Pconfig, -P <partition-config-file>\n"
+	       "          This option defines the optional partition configuration file.\n"
+	       "          The default name is \'"
+	       OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n");
+	printf("--no_part_enforce, -N\n"
+	       "          This option disables partition enforcement on switch external ports.\n\n");
+	printf("--qos, -Q\n" "          This option enables QoS setup.\n\n");
+	printf("--qos_policy_file, -Y <QoS-policy-file>\n"
+	       "          This option defines the optional QoS policy file.\n"
+	       "          The default name is \'" OSM_DEFAULT_QOS_POLICY_FILE
+	       "\'.\n\n");
+	printf("--stay_on_fatal, -y\n"
+	       "          This option will cause SM not to exit on fatal initialization\n"
+	       "          issues: if SM discovers duplicated guids or 12x link with\n"
+	       "          lane reversal badly configured.\n"
+	       "          By default, the SM will exit on these errors.\n\n");
+	printf("--daemon, -B\n"
+	       "          Run in daemon mode - OpenSM will run in the background.\n\n");
+	printf("--inactive, -I\n"
+	       "           Start SM in inactive rather than normal init SM state.\n\n");
+#ifdef ENABLE_OSM_PERF_MGR
+	printf("--perfmgr\n" "           Start with PerfMgr enabled.\n\n");
+	printf("--perfmgr_sweep_time_s <sec.>\n"
+	       "           PerfMgr sweep interval in seconds.\n\n");
+#endif
+	printf("--prefix_routes_file <path to file>\n"
+	       "          This option specifies the prefix routes file.\n"
+	       "          Prefix routes control how the SA responds to path record\n"
+	       "          queries for off-subnet DGIDs.  Default file is:\n"
+	       "              " OSM_DEFAULT_PREFIX_ROUTES_FILE "\n\n");
+	printf("--consolidate_ipv6_snm_req\n"
+	       "          Consolidate IPv6 Solicited Node Multicast group joins\n"
+	       "          into 1 IB multicast group.\n\n");
+	printf("--verbose, -v\n"
+	       "          This option increases the log verbosity level.\n"
+	       "          The -v option may be specified multiple times\n"
+	       "          to further increase the verbosity level.\n"
+	       "          See the -D option for more information about\n"
+	       "          log verbosity.\n\n");
+	printf("--V, -V\n"
+	       "          This option sets the maximum verbosity level and\n"
+	       "          forces log flushing.\n"
+	       "          The -V is equivalent to '-D 0xFF -d 2'.\n"
+	       "          See the -D option for more information about\n"
+	       "          log verbosity.\n\n");
+	printf("--D, -D <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("--debug, -d <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("--help, -h, -?\n"
+	       "          Display this usage info then exit.\n\n");
+	fflush(stdout);
+	exit(2);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid)
+{
+	ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+	uint32_t num_ports = GUID_ARRAY_SIZE;
+	char junk[128];
+	uint32_t i, choice = 0;
+	boolean_t done_flag = FALSE;
+	ib_api_status_t status;
+
+	/*
+	   Call the transport layer for a list of local port
+	   GUID values.
+	 */
+	status =
+	    osm_vendor_get_all_port_attr(p_osm->p_vendor, attr_array,
+					 &num_ports);
+	if (status != IB_SUCCESS) {
+		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
+		       status);
+		return (0);
+	}
+
+	/* if num_ports is 0 - return 0 */
+	if (num_ports == 0) {
+		printf("\nNo local ports detected!\n");
+		return (0);
+	}
+	/* If num_ports is 1, then there is only one possible port to use.
+	 * Use it. */
+	if (num_ports == 1) {
+		printf("Using default GUID 0x%" PRIx64 "\n",
+		       cl_hton64(attr_array[0].port_guid));
+		return (attr_array[0].port_guid);
+	}
+	/* If port_guid is 0 - use the first connected port */
+	if (port_guid == 0) {
+		for (i = 0; i < num_ports; i++)
+			if (attr_array[i].link_state > IB_LINK_DOWN)
+				break;
+		if (i == num_ports)
+			i = 0;
+		printf("Using default GUID 0x%" PRIx64 "\n",
+		       cl_hton64(attr_array[i].port_guid));
+		return (attr_array[i].port_guid);
+	}
+
+	if (p_osm->subn.opt.daemon)
+		return 0;
+
+	/* More than one possible port - list all ports and let the user
+	 * to choose. */
+	while (done_flag == FALSE) {
+		printf("\nChoose a local port number with which to bind:\n\n");
+		for (i = 0; i < num_ports; i++)
+			/* Print the index + 1 since by convention, port
+			 * numbers start with 1 on host channel adapters. */
+			printf("\t%u: GUID 0x%" PRIx64
+			       ", lid %u, state %s\n", i + 1,
+			       cl_ntoh64(attr_array[i].port_guid),
+			       attr_array[i].lid,
+			       ib_get_port_state_str(attr_array[i].link_state));
+		printf("\nEnter choice (1-%u): ", i);
+		fflush(stdout);
+		if (scanf("%u", &choice)) {
+			if (choice > num_ports || choice < 1) {
+				printf("\nError: Lame choice!\n");
+				fflush(stdin);
+			} else {
+				choice--;
+				done_flag = TRUE;
+			}
+		} else {
+			/* get rid of the junk in the selection line */
+			scanf("%s", junk);
+			printf("\nError: Lame choice!\n");
+			fflush(stdin);
+		}
+	}
+	printf("Choice guid=0x%" PRIx64 "\n",
+	       cl_ntoh64(attr_array[choice].port_guid));
+	return (attr_array[choice].port_guid);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static int daemonize(osm_opensm_t * osm)
+{
+	pid_t pid;
+	int fd;
+
+	fd = open("/dev/null", O_WRONLY);
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+
+	if ((pid = fork()) < 0) {
+		perror("fork");
+		exit(-1);
+	} else if (pid > 0)
+		exit(0);
+
+	setsid();
+
+	if ((pid = fork()) < 0) {
+		perror("fork");
+		exit(-1);
+	} else if (pid > 0)
+		exit(0);
+
+	close(0);
+	close(1);
+	close(2);
+
+	dup2(fd, 0);
+	dup2(fd, 1);
+	dup2(fd, 2);
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm)
+{
+	int console_init_flag = 0;
+
+	if (is_console_enabled(p_opt)) {
+		if (!osm_console_init(p_opt, &p_osm->console, &p_osm->log))
+			console_init_flag = 1;
+	}
+
+	/*
+	   Sit here forever - dwell or do console i/o & cmds
+	 */
+	while (!osm_exit_flag) {
+		if (console_init_flag)
+			osm_console(p_osm);
+		else
+			cl_thread_suspend(10000);
+
+		if (osm_usr1_flag) {
+			osm_usr1_flag = 0;
+			osm_log_reopen_file(&(p_osm->log));
+		}
+		if (osm_hup_flag) {
+			osm_hup_flag = 0;
+			/* a HUP signal should only start a new heavy sweep */
+			p_osm->subn.force_heavy_sweep = TRUE;
+			osm_opensm_sweep(p_osm);
+		}
+	}
+	if (is_console_enabled(p_opt))
+		osm_console_exit(&p_osm->console, &p_osm->log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int main(int argc, char *argv[])
+{
+	osm_opensm_t osm;
+	osm_subn_opt_t opt;
+	ib_net64_t sm_key = 0;
+	ib_api_status_t status;
+	uint32_t temp, dbg_lvl;
+	boolean_t run_once_flag = FALSE;
+	int32_t vendor_debug = 0;
+	uint32_t next_option;
+	char *conf_template = NULL;
+	uint32_t val;
+	unsigned config_file_done = 0;
+	const char *const short_option =
+	    "F:c:i:f:ed:D:g:l:L:s:t:a:u:m:X:R:zM:U:S:P:Y:ANBIQvVhoryxp:n:q:k:C:";
+
+	/*
+	   In the array below, the 2nd parameter specifies the number
+	   of arguments as follows:
+	   0: no arguments
+	   1: argument
+	   2: optional
+	 */
+	const struct option long_option[] = {
+		{"version", 0, NULL, 12},
+		{"config", 1, NULL, 'F'},
+		{"create-config", 1, NULL, 'c'},
+		{"debug", 1, NULL, 'd'},
+		{"guid", 1, NULL, 'g'},
+		{"ignore_guids", 1, NULL, 'i'},
+		{"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'},
+		{"qos", 0, NULL, 'Q'},
+		{"qos_policy_file", 1, NULL, 'Y'},
+		{"maxsmps", 1, NULL, 'n'},
+		{"console", 1, NULL, 'q'},
+		{"V", 0, NULL, 'V'},
+		{"help", 0, NULL, 'h'},
+		{"once", 0, NULL, 'o'},
+		{"reassign_lids", 0, NULL, 'r'},
+		{"priority", 1, NULL, 'p'},
+		{"smkey", 1, NULL, 'k'},
+		{"routing_engine", 1, NULL, 'R'},
+		{"ucast_cache", 0, NULL, 'A'},
+		{"connect_roots", 0, NULL, 'z'},
+		{"lid_matrix_file", 1, NULL, 'M'},
+		{"lfts_file", 1, NULL, 'U'},
+		{"sadb_file", 1, NULL, 'S'},
+		{"root_guid_file", 1, NULL, 'a'},
+		{"cn_guid_file", 1, NULL, 'u'},
+		{"ids_guid_file", 1, NULL, 'm'},
+		{"guid_routing_order_file", 1, NULL, 'X'},
+		{"stay_on_fatal", 0, NULL, 'y'},
+		{"honor_guid2lid", 0, NULL, 'x'},
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+		{"console-port", 1, NULL, 'C'},
+#endif
+		{"daemon", 0, NULL, 'B'},
+		{"inactive", 0, NULL, 'I'},
+#ifdef ENABLE_OSM_PERF_MGR
+		{"perfmgr", 0, NULL, 1},
+		{"perfmgr_sweep_time_s", 1, NULL, 2},
+#endif
+		{"prefix_routes_file", 1, NULL, 3},
+		{"consolidate_ipv6_snm_req", 0, NULL, 4},
+		{NULL, 0, NULL, 0}	/* Required at the end of the array */
+	};
+
+	/* Make sure that the opensm and complib were compiled using
+	   same modes (debug/free) */
+	if (osm_is_debug() != cl_is_debug()) {
+		fprintf(stderr,
+			"ERROR: OpenSM and Complib were compiled using different modes\n");
+		fprintf(stderr, "ERROR: OpenSM debug:%d Complib debug:%d \n",
+			osm_is_debug(), cl_is_debug());
+		exit(1);
+	}
+#if defined (_DEBUG_) && defined (OSM_VENDOR_INTF_OPENIB)
+	enable_stack_dump(1);
+#endif
+
+	printf("-------------------------------------------------\n");
+	printf("%s\n", OSM_VERSION);
+
+	osm_subn_set_default_opt(&opt);
+
+	if (osm_subn_parse_conf_file(OSM_DEFAULT_CONFIG_FILE, &opt) < 0)
+		printf("\nosm_subn_parse_conf_file failed!\n");
+
+	printf("Command Line Arguments:\n");
+	do {
+		next_option = getopt_long_only(argc, argv, short_option,
+					       long_option, NULL);
+		switch (next_option) {
+		case 12: /* --version - already printed above */
+			exit(0);
+			break;
+		case 'F':
+			if (config_file_done)
+				break;
+			printf("Reloading config from `%s`:\n", optarg);
+			if (osm_subn_parse_conf_file(optarg, &opt)) {
+				printf("cannot parse config file.\n");
+				exit(1);
+			}
+			printf("Rescaning command line:\n");
+			config_file_done = 1;
+			optind = 0;
+			break;
+		case 'c':
+			conf_template = optarg;
+			printf(" Creating config file template \'%s\'.\n",
+			       conf_template);
+			break;
+		case 'o':
+			/*
+			   Run once option.
+			 */
+			run_once_flag = TRUE;
+			printf(" Run Once\n");
+			break;
+
+		case 'r':
+			/*
+			   Reassign LIDs subnet option.
+			 */
+			opt.reassign_lids = TRUE;
+			printf(" Reassign LIDs\n");
+			break;
+
+		case 'i':
+			/*
+			   Specifies ignore guids file.
+			 */
+			opt.port_prof_ignore_file = optarg;
+			printf(" Ignore Guids File = %s\n",
+			       opt.port_prof_ignore_file);
+			break;
+
+		case 'g':
+			/*
+			   Specifies port guid with which to bind.
+			 */
+			opt.guid = cl_hton64(strtoull(optarg, NULL, 16));
+			if (!opt.guid)
+				/* If guid is 0 - need to display the
+				 * guid list */
+				opt.guid = INVALID_GUID;
+			else
+				printf(" Guid <0x%" PRIx64 ">\n",
+				       cl_hton64(opt.guid));
+			break;
+
+		case 's':
+			val = strtol(optarg, NULL, 0);
+			/* Check that the number is not too large */
+			if (((uint32_t) (val * 1000000)) / 1000000 != val)
+				fprintf(stderr,
+					"ERROR: sweep interval given is too large. Ignoring it.\n");
+			else {
+				opt.sweep_interval = val;
+				printf(" sweep interval = %d\n",
+				       opt.sweep_interval);
+			}
+			break;
+
+		case 't':
+			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
+			 */
+			if (strcmp(optarg, OSM_DISABLE_CONSOLE) == 0
+			    || strcmp(optarg, OSM_LOCAL_CONSOLE) == 0
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+			    || strcmp(optarg, OSM_REMOTE_CONSOLE) == 0
+			    || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0
+#endif
+			    )
+				opt.console = optarg;
+			else
+				printf("-console %s option not understood\n",
+				       optarg);
+			break;
+
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+		case 'C':
+			opt.console_port = strtol(optarg, NULL, 0);
+			break;
+#endif
+
+		case 'd':
+			dbg_lvl = strtol(optarg, NULL, 0);
+			printf(" d level = 0x%x\n", dbg_lvl);
+			if (dbg_lvl == 0) {
+				printf(" Debug mode: Ignore Other SMs\n");
+				opt.ignore_other_sm = TRUE;
+			} else if (dbg_lvl == 1) {
+				printf(" Debug mode: Forcing Single Thread\n");
+				opt.single_thread = TRUE;
+			} else if (dbg_lvl == 2) {
+				printf(" Debug mode: Force Log Flush\n");
+				opt.force_log_flush = TRUE;
+			} else if (dbg_lvl == 3) {
+				printf
+				    (" Debug mode: Disable multicast support\n");
+				opt.disable_multicast = TRUE;
+			}
+			/*
+			 * NOTE: Debug level 4 used to be used for memory
+			 * tracking but this is now deprecated
+			 */
+			else if (dbg_lvl == 5)
+				vendor_debug++;
+			else
+				printf(" OpenSM: Unknown debug option %d"
+				       " ignored\n", dbg_lvl);
+			break;
+
+		case 'l':
+			temp = strtol(optarg, NULL, 0);
+			if (temp > 7) {
+				fprintf(stderr,
+					"ERROR: LMC must be 7 or less.\n");
+				return (-1);
+			}
+			opt.lmc = (uint8_t) temp;
+			printf(" LMC = %d\n", temp);
+			break;
+
+		case 'D':
+			opt.log_flags = strtol(optarg, NULL, 0);
+			printf(" verbose option -D = 0x%x\n", opt.log_flags);
+			break;
+
+		case 'f':
+			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.qos = TRUE;
+			break;
+
+		case 'Y':
+			opt.qos_policy_file = optarg;
+			printf(" QoS policy file \'%s\'\n", optarg);
+			break;
+
+		case 'y':
+			opt.exit_on_fatal = FALSE;
+			printf(" Staying on fatal initialization errors\n");
+			break;
+
+		case 'v':
+			opt.log_flags = (opt.log_flags << 1) | 1;
+			printf(" Verbose option -v (log flags = 0x%X)\n",
+			       opt.log_flags);
+			break;
+
+		case 'V':
+			opt.log_flags = 0xFF;
+			opt.force_log_flush = TRUE;
+			printf(" Big V selected\n");
+			break;
+
+		case 'p':
+			temp = 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_names = optarg;
+			printf(" Activate \'%s\' routing engine(s)\n", optarg);
+			break;
+
+		case 'z':
+			opt.connect_roots = TRUE;
+			printf(" Connect roots option is on\n");
+			break;
+
+		case 'A':
+			opt.use_ucast_cache = TRUE;
+			printf(" Unicast routing cache option is on\n");
+			break;
+
+		case 'M':
+			opt.lid_matrix_dump_file = optarg;
+			printf(" Lid matrix dump file is \'%s\'\n", optarg);
+			break;
+
+		case 'U':
+			opt.lfts_file = optarg;
+			printf(" LFTs file is \'%s\'\n", optarg);
+			break;
+
+		case 'S':
+			opt.sa_db_file = optarg;
+			printf(" SA DB file is \'%s\'\n", optarg);
+			break;
+
+		case 'a':
+			/*
+			   Specifies root guids file
+			 */
+			opt.root_guid_file = optarg;
+			printf(" Root Guid File: %s\n", opt.root_guid_file);
+			break;
+
+		case 'u':
+			/*
+			   Specifies compute node guids file
+			 */
+			opt.cn_guid_file = optarg;
+			printf(" Compute Node Guid File: %s\n",
+			       opt.cn_guid_file);
+			break;
+
+		case 'm':
+			/* Specifies ids guid file */
+			opt.ids_guid_file = optarg;
+			printf(" IDs Guid File: %s\n", opt.ids_guid_file);
+			break;
+
+		case 'X':
+			/* Specifies guid routing order file */
+			opt.guid_routing_order_file = optarg;
+			printf(" GUID Routing Order File: %s\n", opt.guid_routing_order_file);
+			break;
+
+		case 'x':
+			opt.honor_guid2lid_file = TRUE;
+			printf(" Honor guid2lid file, if possible\n");
+			break;
+
+		case 'B':
+			opt.daemon = TRUE;
+			printf(" Daemon mode\n");
+			break;
+
+		case 'I':
+			opt.sm_inactive = TRUE;
+			printf(" SM started in inactive state\n");
+			break;
+
+#ifdef ENABLE_OSM_PERF_MGR
+		case 1:
+			opt.perfmgr = TRUE;
+			break;
+		case 2:
+			opt.perfmgr_sweep_time_s = atoi(optarg);
+			break;
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+		case 3:
+			opt.prefix_routes_file = optarg;
+			break;
+		case 4:
+			opt.consolidate_ipv6_snm_req = TRUE;
+			break;
+		case 'h':
+		case '?':
+		case ':':
+			show_usage();
+			break;
+
+		case -1:
+			break;	/* done with option */
+		default:	/* something wrong */
+			abort();
+		}
+	}
+	while (next_option != -1);
+
+	if (opt.log_file != NULL)
+		printf(" Log File: %s\n", opt.log_file);
+	/* Done with options description */
+	printf("-------------------------------------------------\n");
+
+	if (conf_template) {
+		status = osm_subn_write_conf_file(conf_template, &opt);
+		if (status)
+			printf("\nosm_subn_write_conf_file failed!\n");
+		exit(status);
+	}
+
+	osm_subn_verify_config(&opt);
+
+	if (vendor_debug)
+		osm_vendor_set_debug(osm.p_vendor, vendor_debug);
+
+	block_signals();
+
+	if (opt.daemon)
+		daemonize(&osm);
+
+	complib_init();
+
+	status = osm_opensm_init(&osm, &opt);
+	if (status != IB_SUCCESS) {
+		const char *err_str = ib_get_err_str(status);
+		if (err_str == NULL)
+			err_str = "Unknown Error Type";
+		printf("\nError from osm_opensm_init: %s.\n", err_str);
+		/* We will just exit, and not go to Exit, since we don't
+		   want the destroy to be called. */
+		complib_exit();
+		return (status);
+	}
+
+	/*
+	   If the user didn't specify a GUID on the command line,
+	   then get a port GUID value with which to bind.
+	 */
+	if (opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID))
+		opt.guid = get_port_guid(&osm, opt.guid);
+
+	status = osm_opensm_bind(&osm, opt.guid);
+	if (status != IB_SUCCESS) {
+		printf("\nError from osm_opensm_bind (0x%X)\n", status);
+		printf
+		    ("Perhaps another instance of OpenSM is already running\n");
+		goto Exit;
+	}
+
+	setup_signals();
+
+	osm_opensm_sweep(&osm);
+
+	if (run_once_flag == TRUE) {
+		while (!osm_exit_flag) {
+			status =
+			    osm_opensm_wait_for_subnet_up(&osm,
+							  osm.subn.opt.
+							  sweep_interval *
+							  1000000, TRUE);
+			if (!status)
+				osm_exit_flag = 1;
+		}
+	} else {
+		/*
+		 *         Sit here until signaled to exit
+		 */
+		osm_manager_loop(&opt, &osm);
+	}
+
+	if (osm.mad_pool.mads_out) {
+		fprintf(stdout,
+			"There are still %u MADs out. Forcing the exit of the OpenSM application...\n",
+			osm.mad_pool.mads_out);
+#ifdef HAVE_LIBPTHREAD
+		pthread_cond_signal(&osm.stats.cond);
+#else
+		cl_event_signal(&osm.stats.event);
+#endif
+	}
+
+Exit:
+	osm_opensm_destroy(&osm);
+	complib_exit();
+
+	exit(0);
+}
diff --git a/opensm/osm_console.c b/opensm/osm_console.c
new file mode 100644
index 0000000..5727cea
--- /dev/null
+++ b/opensm/osm_console.c
@@ -0,0 +1,1320 @@
+/*
+ * Copyright (c) 2005-2008 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#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 <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+#include <arpa/inet.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <opensm/osm_console.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_subnet.h>
+
+struct command {
+	char *name;
+	void (*help_function) (FILE * out, int detail);
+	void (*parse_function) (char **p_last, osm_opensm_t * p_osm,
+				FILE * out);
+};
+
+static struct {
+	int on;
+	int delay_s;
+	time_t previous;
+	void (*loop_function) (osm_opensm_t * p_osm, FILE * out);
+} loop_command = {
+on: 0, delay_s: 2, loop_function:NULL};
+
+static const struct command console_cmds[];
+
+static inline char *next_token(char **p_last)
+{
+	return strtok_r(NULL, " \t\n\r", p_last);
+}
+
+static void help_command(FILE * out, int detail)
+{
+	int i;
+
+	fprintf(out, "Supported commands and syntax:\n");
+	fprintf(out, "help [<command>]\n");
+	/* skip help command */
+	for (i = 1; console_cmds[i].name; i++)
+		console_cmds[i].help_function(out, 0);
+}
+
+static void help_quit(FILE * out, int detail)
+{
+	fprintf(out, "quit (not valid in local mode; use ctl-c)\n");
+}
+
+static void help_loglevel(FILE * out, int detail)
+{
+	fprintf(out, "loglevel [<log-level>]\n");
+	if (detail) {
+		fprintf(out, "   log-level is OR'ed from the following\n");
+		fprintf(out, "   OSM_LOG_NONE             0x%02X\n",
+			OSM_LOG_NONE);
+		fprintf(out, "   OSM_LOG_ERROR            0x%02X\n",
+			OSM_LOG_ERROR);
+		fprintf(out, "   OSM_LOG_INFO             0x%02X\n",
+			OSM_LOG_INFO);
+		fprintf(out, "   OSM_LOG_VERBOSE          0x%02X\n",
+			OSM_LOG_VERBOSE);
+		fprintf(out, "   OSM_LOG_DEBUG            0x%02X\n",
+			OSM_LOG_DEBUG);
+		fprintf(out, "   OSM_LOG_FUNCS            0x%02X\n",
+			OSM_LOG_FUNCS);
+		fprintf(out, "   OSM_LOG_FRAMES           0x%02X\n",
+			OSM_LOG_FRAMES);
+		fprintf(out, "   OSM_LOG_ROUTING          0x%02X\n",
+			OSM_LOG_ROUTING);
+		fprintf(out, "   OSM_LOG_SYS              0x%02X\n",
+			OSM_LOG_SYS);
+		fprintf(out, "\n");
+		fprintf(out, "   OSM_LOG_DEFAULT_LEVEL    0x%02X\n",
+			OSM_LOG_DEFAULT_LEVEL);
+	}
+}
+
+static void help_priority(FILE * out, int detail)
+{
+	fprintf(out, "priority [<sm-priority>]\n");
+}
+
+static void help_resweep(FILE * out, int detail)
+{
+	fprintf(out, "resweep [heavy|light]\n");
+}
+
+static void help_reroute(FILE * out, int detail)
+{
+	fprintf(out, "reroute\n");
+	if (detail) {
+		fprintf(out, "reroute the fabric\n");
+	}
+}
+
+static void help_status(FILE * out, int detail)
+{
+	fprintf(out, "status [loop]\n");
+	if (detail) {
+		fprintf(out, "   loop -- type \"q<ret>\" to quit\n");
+	}
+}
+
+static void help_logflush(FILE * out, int detail)
+{
+	fprintf(out, "logflush -- flush the opensm.log file\n");
+}
+
+static void help_querylid(FILE * out, int detail)
+{
+	fprintf(out,
+		"querylid lid -- print internal information about the lid specified\n");
+}
+
+static void help_portstatus(FILE * out, int detail)
+{
+	fprintf(out, "portstatus [ca|switch|router]\n");
+	if (detail) {
+		fprintf(out, "summarize port status\n");
+		fprintf(out,
+			"   [ca|switch|router] -- limit the results to the node type specified\n");
+	}
+
+}
+
+static void help_switchbalance(FILE * out, int detail)
+{
+	fprintf(out, "switchbalance [verbose] [guid]\n");
+	if (detail) {
+		fprintf(out, "output switch balancing information\n");
+		fprintf(out,
+			"  [verbose] -- verbose output\n"
+			"  [guid] -- limit results to specified guid\n");
+	}
+}
+
+static void help_lidbalance(FILE * out, int detail)
+{
+	fprintf(out, "lidbalance [switchguid]\n");
+	if (detail) {
+		fprintf(out, "output lid balanced forwarding information\n");
+		fprintf(out,
+			"  [switchguid] -- limit results to specified switch guid\n");
+	}
+}
+
+static void help_dump_conf(FILE *out, int detail)
+{
+	fprintf(out, "dump_conf\n");
+	if (detail) {
+		fprintf(out, "dump current opensm configuration\n");
+	}
+}
+
+#ifdef ENABLE_OSM_PERF_MGR
+static void help_perfmgr(FILE * out, int detail)
+{
+	fprintf(out,
+		"perfmgr [enable|disable|clear_counters|dump_counters|sweep_time[seconds]]\n");
+	if (detail) {
+		fprintf(out,
+			"perfmgr -- print the performance manager state\n");
+		fprintf(out,
+			"   [enable|disable] -- change the perfmgr state\n");
+		fprintf(out,
+			"   [sweep_time] -- change the perfmgr sweep time (requires [seconds] option)\n");
+		fprintf(out,
+			"   [clear_counters] -- clear the counters stored\n");
+		fprintf(out,
+			"   [dump_counters [mach]] -- dump the counters (optionally in [mach]ine readable format)\n");
+		fprintf(out,
+			"   [print_counters <nodename|nodeguid>] -- print the counters for the specified node\n");
+	}
+}
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+/* more help routines go here */
+
+static void help_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	int i, found = 0;
+
+	p_cmd = next_token(p_last);
+	if (!p_cmd)
+		help_command(out, 0);
+	else {
+		for (i = 1; console_cmds[i].name; i++) {
+			if (!strcmp(p_cmd, console_cmds[i].name)) {
+				found = 1;
+				console_cmds[i].help_function(out, 1);
+				break;
+			}
+		}
+		if (!found) {
+			fprintf(out, "%s : Command not found\n\n", p_cmd);
+			help_command(out, 0);
+		}
+	}
+}
+
+static void loglevel_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	int level;
+
+	p_cmd = next_token(p_last);
+	if (!p_cmd)
+		fprintf(out, "Current log level is 0x%x\n",
+			osm_log_get_level(&p_osm->log));
+	else {
+		/* Handle x, 0x, and decimal specification of log level */
+		if (!strncmp(p_cmd, "x", 1)) {
+			p_cmd++;
+			level = strtoul(p_cmd, NULL, 16);
+		} else {
+			if (!strncmp(p_cmd, "0x", 2)) {
+				p_cmd += 2;
+				level = strtoul(p_cmd, NULL, 16);
+			} else
+				level = strtol(p_cmd, NULL, 10);
+		}
+		if ((level >= 0) && (level < 256)) {
+			fprintf(out, "Setting log level to 0x%x\n", level);
+			osm_log_set_level(&p_osm->log, level);
+		} else
+			fprintf(out, "Invalid log level 0x%x\n", level);
+	}
+}
+
+static void priority_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	int priority;
+
+	p_cmd = next_token(p_last);
+	if (!p_cmd)
+		fprintf(out, "Current sm-priority is %d\n",
+			p_osm->subn.opt.sm_priority);
+	else {
+		priority = strtol(p_cmd, NULL, 0);
+		if (0 > priority || 15 < priority)
+			fprintf(out,
+				"Invalid sm-priority %d; must be between 0 and 15\n",
+				priority);
+		else {
+			fprintf(out, "Setting sm-priority to %d\n", priority);
+			osm_set_sm_priority(&p_osm->sm, (uint8_t)priority);
+		}
+	}
+}
+
+static char *sm_state_str(int state)
+{
+	switch (state) {
+	case IB_SMINFO_STATE_DISCOVERING:
+		return ("Discovering");
+	case IB_SMINFO_STATE_STANDBY:
+		return ("Standby");
+	case IB_SMINFO_STATE_NOTACTIVE:
+		return ("Not Active");
+	case IB_SMINFO_STATE_MASTER:
+		return ("Master");
+	}
+	return ("UNKNOWN");
+}
+
+static char *sa_state_str(osm_sa_state_t state)
+{
+	switch (state) {
+	case OSM_SA_STATE_INIT:
+		return ("Init");
+	case OSM_SA_STATE_READY:
+		return ("Ready");
+	}
+	return ("UNKNOWN");
+}
+
+static void print_status(osm_opensm_t * p_osm, FILE * out)
+{
+	if (out) {
+		cl_plock_acquire(&p_osm->lock);
+		fprintf(out, "   OpenSM Version: %s\n", p_osm->osm_version);
+		fprintf(out, "   SM State      : %s\n",
+			sm_state_str(p_osm->subn.sm_state));
+		fprintf(out, "   SA State      : %s\n",
+			sa_state_str(p_osm->sa.state));
+		fprintf(out, "   Routing Engine: %s\n",
+			osm_routing_engine_type_str(p_osm->
+						    routing_engine_used));
+#ifdef ENABLE_OSM_PERF_MGR
+		fprintf(out, "\n   PerfMgr state/sweep state : %s/%s\n",
+			osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
+			osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)));
+#endif
+		fprintf(out, "\n   MAD stats\n"
+			"   ---------\n"
+			"   QP0 MADs outstanding           : %d\n"
+			"   QP0 MADs outstanding (on wire) : %d\n"
+			"   QP0 MADs rcvd                  : %d\n"
+			"   QP0 MADs sent                  : %d\n"
+			"   QP0 unicasts sent              : %d\n"
+			"   QP0 unknown MADs rcvd          : %d\n"
+			"   SA MADs outstanding            : %d\n"
+			"   SA MADs rcvd                   : %d\n"
+			"   SA MADs sent                   : %d\n"
+			"   SA unknown MADs rcvd           : %d\n"
+			"   SA MADs ignored                : %d\n",
+			p_osm->stats.qp0_mads_outstanding,
+			p_osm->stats.qp0_mads_outstanding_on_wire,
+			p_osm->stats.qp0_mads_rcvd,
+			p_osm->stats.qp0_mads_sent,
+			p_osm->stats.qp0_unicasts_sent,
+			p_osm->stats.qp0_mads_rcvd_unknown,
+			p_osm->stats.sa_mads_outstanding,
+			p_osm->stats.sa_mads_rcvd,
+			p_osm->stats.sa_mads_sent,
+			p_osm->stats.sa_mads_rcvd_unknown,
+			p_osm->stats.sa_mads_ignored);
+		fprintf(out, "\n   Subnet flags\n"
+			"   ------------\n"
+			"   Ignore existing lfts           : %d\n"
+			"   Subnet Init errors             : %d\n"
+			"   In sweep hop 0                 : %d\n"
+			"   First time master sweep        : %d\n"
+			"   Coming out of standby          : %d\n",
+			p_osm->subn.ignore_existing_lfts,
+			p_osm->subn.subnet_initialization_error,
+			p_osm->subn.in_sweep_hop_0,
+			p_osm->subn.first_time_master_sweep,
+			p_osm->subn.coming_out_of_standby);
+		fprintf(out, "\n");
+		cl_plock_release(&p_osm->lock);
+	}
+}
+
+static int loop_command_check_time(void)
+{
+	time_t cur = time(NULL);
+	if ((loop_command.previous + loop_command.delay_s) < cur) {
+		loop_command.previous = cur;
+		return (1);
+	}
+	return (0);
+}
+
+static void status_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		if (strcmp(p_cmd, "loop") == 0) {
+			fprintf(out, "Looping on status command...\n");
+			fflush(out);
+			loop_command.on = 1;
+			loop_command.previous = time(NULL);
+			loop_command.loop_function = print_status;
+		} else {
+			help_status(out, 1);
+			return;
+		}
+	}
+	print_status(p_osm, out);
+}
+
+static void resweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+
+	p_cmd = next_token(p_last);
+	if (!p_cmd ||
+	    (strcmp(p_cmd, "heavy") != 0 && strcmp(p_cmd, "light") != 0)) {
+		fprintf(out, "Invalid resweep command\n");
+		help_resweep(out, 1);
+	} else {
+		if (strcmp(p_cmd, "heavy") == 0)
+			p_osm->subn.force_heavy_sweep = TRUE;
+		osm_opensm_sweep(p_osm);
+	}
+}
+
+static void reroute_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	p_osm->subn.force_reroute = TRUE;
+	osm_opensm_sweep(p_osm);
+}
+
+static void logflush_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	fflush(p_osm->log.out_port);
+}
+
+static void querylid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	int p = 0;
+	uint16_t lid = 0;
+	osm_port_t *p_port = NULL;
+	char *p_cmd = next_token(p_last);
+
+	if (!p_cmd) {
+		fprintf(out, "no LID specified\n");
+		help_querylid(out, 1);
+		return;
+	}
+
+	lid = (uint16_t) strtoul(p_cmd, NULL, 0);
+	cl_plock_acquire(&p_osm->lock);
+	if (lid > cl_ptr_vector_get_capacity(&(p_osm->subn.port_lid_tbl)))
+		goto invalid_lid;
+	p_port = cl_ptr_vector_get(&(p_osm->subn.port_lid_tbl), lid);
+	if (!p_port)
+		goto invalid_lid;
+
+	fprintf(out, "Query results for LID %u\n", lid);
+	fprintf(out,
+		"   GUID                : 0x%016" PRIx64 "\n"
+		"   Node Desc           : %s\n"
+		"   Node Type           : %s\n"
+		"   Num Ports           : %d\n",
+		cl_ntoh64(p_port->guid),
+		p_port->p_node->print_desc,
+		ib_get_node_type_str(osm_node_get_type(p_port->p_node)),
+		p_port->p_node->node_info.num_ports);
+
+	if (p_port->p_node->sw)
+		p = 0;
+	else
+		p = 1;
+	for ( /* see above */ ; p < p_port->p_node->physp_tbl_size; p++) {
+		fprintf(out,
+			"   Port %d health       : %s\n",
+			p,
+			p_port->p_node->physp_table[p].
+			healthy ? "OK" : "ERROR");
+	}
+
+	cl_plock_release(&p_osm->lock);
+	return;
+
+invalid_lid:
+	cl_plock_release(&p_osm->lock);
+	fprintf(out, "Invalid lid %d\n", lid);
+	return;
+}
+
+/**
+ * Data structures for the portstatus command
+ */
+typedef struct _port_report {
+	struct _port_report *next;
+	uint64_t node_guid;
+	uint8_t port_num;
+	char print_desc[IB_NODE_DESCRIPTION_SIZE + 1];
+} port_report_t;
+
+static void
+__tag_port_report(port_report_t ** head, uint64_t node_guid,
+		  uint8_t port_num, char *print_desc)
+{
+	port_report_t *rep = malloc(sizeof(*rep));
+	if (!rep)
+		return;
+
+	rep->node_guid = node_guid;
+	rep->port_num = port_num;
+	memcpy(rep->print_desc, print_desc, IB_NODE_DESCRIPTION_SIZE + 1);
+	rep->next = NULL;
+	if (*head) {
+		rep->next = *head;
+		*head = rep;
+	} else
+		*head = rep;
+}
+
+static void __print_port_report(FILE * out, port_report_t * head)
+{
+	port_report_t *item = head;
+	while (item != NULL) {
+		fprintf(out, "      0x%016" PRIx64 " %d (%s)\n",
+			item->node_guid, item->port_num, item->print_desc);
+		port_report_t *next = item->next;
+		free(item);
+		item = next;
+	}
+}
+
+typedef struct {
+	uint8_t node_type_lim;	/* limit the results; 0 == ALL */
+	uint64_t total_nodes;
+	uint64_t total_ports;
+	uint64_t ports_down;
+	uint64_t ports_active;
+	uint64_t ports_disabled;
+	port_report_t *disabled_ports;
+	uint64_t ports_1X;
+	uint64_t ports_4X;
+	uint64_t ports_8X;
+	uint64_t ports_12X;
+	uint64_t ports_unknown_width;
+	uint64_t ports_reduced_width;
+	port_report_t *reduced_width_ports;
+	uint64_t ports_sdr;
+	uint64_t ports_ddr;
+	uint64_t ports_qdr;
+	uint64_t ports_unknown_speed;
+	uint64_t ports_reduced_speed;
+	port_report_t *reduced_speed_ports;
+} fabric_stats_t;
+
+/**
+ * iterator function to get portstatus on each node
+ */
+static void __get_stats(cl_map_item_t * const p_map_item, void *context)
+{
+	fabric_stats_t *fs = (fabric_stats_t *) context;
+	osm_node_t *node = (osm_node_t *) p_map_item;
+	uint8_t num_ports = osm_node_get_num_physp(node);
+	uint8_t port = 0;
+
+	/* Skip nodes we are not interested in */
+	if (fs->node_type_lim != 0
+	    && fs->node_type_lim != node->node_info.node_type)
+		return;
+
+	fs->total_nodes++;
+
+	for (port = 1; port < num_ports; port++) {
+		osm_physp_t *phys = osm_node_get_physp_ptr(node, port);
+		ib_port_info_t *pi = NULL;
+		uint8_t active_speed = 0;
+		uint8_t enabled_speed = 0;
+		uint8_t active_width = 0;
+		uint8_t enabled_width = 0;
+		uint8_t port_state = 0;
+		uint8_t port_phys_state = 0;
+
+		if (!phys)
+			continue;
+
+		pi = &(phys->port_info);
+		active_speed = ib_port_info_get_link_speed_active(pi);
+		enabled_speed = ib_port_info_get_link_speed_enabled(pi);
+		active_width = pi->link_width_active;
+		enabled_width = pi->link_width_enabled;
+		port_state = ib_port_info_get_port_state(pi);
+		port_phys_state = ib_port_info_get_port_phys_state(pi);
+
+		if ((enabled_width ^ active_width) > active_width) {
+			__tag_port_report(&(fs->reduced_width_ports),
+					  cl_ntoh64(node->node_info.node_guid),
+					  port, node->print_desc);
+			fs->ports_reduced_width++;
+		}
+
+		if ((enabled_speed ^ active_speed) > active_speed) {
+			__tag_port_report(&(fs->reduced_speed_ports),
+					  cl_ntoh64(node->node_info.node_guid),
+					  port, node->print_desc);
+			fs->ports_reduced_speed++;
+		}
+
+		switch (active_speed) {
+		case IB_LINK_SPEED_ACTIVE_2_5:
+			fs->ports_sdr++;
+			break;
+		case IB_LINK_SPEED_ACTIVE_5:
+			fs->ports_ddr++;
+			break;
+		case IB_LINK_SPEED_ACTIVE_10:
+			fs->ports_qdr++;
+			break;
+		default:
+			fs->ports_unknown_speed++;
+			break;
+		}
+		switch (active_width) {
+		case IB_LINK_WIDTH_ACTIVE_1X:
+			fs->ports_1X++;
+			break;
+		case IB_LINK_WIDTH_ACTIVE_4X:
+			fs->ports_4X++;
+			break;
+		case IB_LINK_WIDTH_ACTIVE_8X:
+			fs->ports_8X++;
+			break;
+		case IB_LINK_WIDTH_ACTIVE_12X:
+			fs->ports_12X++;
+			break;
+		default:
+			fs->ports_unknown_width++;
+			break;
+		}
+		if (port_state == IB_LINK_DOWN)
+			fs->ports_down++;
+		else if (port_state == IB_LINK_ACTIVE)
+			fs->ports_active++;
+		if (port_phys_state == IB_PORT_PHYS_STATE_DISABLED) {
+			__tag_port_report(&(fs->disabled_ports),
+					  cl_ntoh64(node->node_info.node_guid),
+					  port, node->print_desc);
+			fs->ports_disabled++;
+		}
+
+		fs->total_ports++;
+	}
+}
+
+static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	fabric_stats_t fs;
+	struct timeval before, after;
+	char *p_cmd;
+
+	memset(&fs, 0, sizeof(fs));
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		if (strcmp(p_cmd, "ca") == 0) {
+			fs.node_type_lim = IB_NODE_TYPE_CA;
+		} else if (strcmp(p_cmd, "switch") == 0) {
+			fs.node_type_lim = IB_NODE_TYPE_SWITCH;
+		} else if (strcmp(p_cmd, "router") == 0) {
+			fs.node_type_lim = IB_NODE_TYPE_ROUTER;
+		} else {
+			fprintf(out, "Node type not understood\n");
+			help_portstatus(out, 1);
+			return;
+		}
+	}
+
+	gettimeofday(&before, NULL);
+
+	/* for each node in the system gather the stats */
+	cl_plock_acquire(&p_osm->lock);
+	cl_qmap_apply_func(&(p_osm->subn.node_guid_tbl), __get_stats,
+			   (void *)&fs);
+	cl_plock_release(&p_osm->lock);
+
+	gettimeofday(&after, NULL);
+
+	/* report the stats */
+	fprintf(out, "\"%s\" port status:\n",
+		fs.node_type_lim ? ib_get_node_type_str(fs.
+							node_type_lim) : "ALL");
+	fprintf(out,
+		"   %" PRIu64 " port(s) scanned on %" PRIu64
+		" nodes in %lu us\n", fs.total_ports, fs.total_nodes,
+		after.tv_usec - before.tv_usec);
+
+	if (fs.ports_down)
+		fprintf(out, "   %" PRIu64 " down\n", fs.ports_down);
+	if (fs.ports_active)
+		fprintf(out, "   %" PRIu64 " active\n", fs.ports_active);
+	if (fs.ports_1X)
+		fprintf(out, "   %" PRIu64 " at 1X\n", fs.ports_1X);
+	if (fs.ports_4X)
+		fprintf(out, "   %" PRIu64 " at 4X\n", fs.ports_4X);
+	if (fs.ports_8X)
+		fprintf(out, "   %" PRIu64 " at 8X\n", fs.ports_8X);
+	if (fs.ports_12X)
+		fprintf(out, "   %" PRIu64 " at 12X\n", fs.ports_12X);
+
+	if (fs.ports_sdr)
+		fprintf(out, "   %" PRIu64 " at 2.5 Gbps\n", fs.ports_sdr);
+	if (fs.ports_ddr)
+		fprintf(out, "   %" PRIu64 " at 5.0 Gbps\n", fs.ports_ddr);
+	if (fs.ports_qdr)
+		fprintf(out, "   %" PRIu64 " at 10.0 Gbps\n", fs.ports_qdr);
+
+	if (fs.ports_disabled + fs.ports_reduced_speed + fs.ports_reduced_width
+	    > 0) {
+		fprintf(out, "\nPossible issues:\n");
+	}
+	if (fs.ports_disabled) {
+		fprintf(out, "   %" PRIu64 " disabled\n", fs.ports_disabled);
+		__print_port_report(out, fs.disabled_ports);
+	}
+	if (fs.ports_reduced_speed) {
+		fprintf(out, "   %" PRIu64 " with reduced speed\n",
+			fs.ports_reduced_speed);
+		__print_port_report(out, fs.reduced_speed_ports);
+	}
+	if (fs.ports_reduced_width) {
+		fprintf(out, "   %" PRIu64 " with reduced width\n",
+			fs.ports_reduced_width);
+		__print_port_report(out, fs.reduced_width_ports);
+	}
+	fprintf(out, "\n");
+}
+
+static void switchbalance_check(osm_opensm_t * p_osm,
+				osm_switch_t * p_sw, FILE * out, int verbose)
+{
+	uint8_t port_num;
+	uint8_t num_ports;
+	const cl_qmap_t *p_port_tbl;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_rem_physp;
+	osm_node_t *p_rem_node;
+	uint32_t count[255];	/* max ports is a uint8_t */
+	uint8_t output_ports[255];
+	uint8_t output_ports_count = 0;
+	uint32_t min_count = 0xFFFFFFFF;
+	uint32_t max_count = 0;
+	unsigned int i;
+
+	memset(count, '\0', sizeof(uint32_t) * 255);
+
+	/* Count port usage */
+	p_port_tbl = &p_osm->subn.port_guid_tbl;
+	for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
+	     p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
+	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
+		uint16_t min_lid_ho;
+		uint16_t max_lid_ho;
+		uint16_t lid_ho;
+
+		/* Don't count switches in port usage */
+		if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
+			continue;
+
+		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+		if (min_lid_ho == 0 || max_lid_ho == 0)
+			continue;
+
+		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
+			port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
+			if (port_num == OSM_NO_PATH)
+				continue;
+
+			count[port_num]++;
+		}
+	}
+
+	num_ports = p_sw->num_ports;
+	for (port_num = 1; port_num < num_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+
+		/* if port is down/unhealthy, don't consider it in
+		 * min/max calculations
+		 */
+		if (!p_physp || !osm_physp_is_healthy(p_physp)
+		    || !osm_physp_get_remote(p_physp))
+			continue;
+
+		p_rem_physp = osm_physp_get_remote(p_physp);
+		p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+		/* If we are directly connected to a CA/router, its not really
+		 * up for balancing consideration.
+		 */
+		if (osm_node_get_type(p_rem_node) != IB_NODE_TYPE_SWITCH)
+			continue;
+
+		output_ports[output_ports_count] = port_num;
+		output_ports_count++;
+
+		if (count[port_num] < min_count)
+			min_count = count[port_num];
+		if (count[port_num] > max_count)
+			max_count = count[port_num];
+	}
+
+	if (verbose || ((max_count - min_count) > 1)) {
+		if ((max_count - min_count) > 1)
+			fprintf(out,
+				"Unbalanced Switch: 0x%016" PRIx64 " (%s)\n",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+		else
+			fprintf(out,
+				"Switch: 0x%016" PRIx64 " (%s)\n",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+
+		for (i = 0; i < output_ports_count; i++) {
+			fprintf(out,
+				"Port %d: %d\n",
+				output_ports[i], count[output_ports[i]]);
+		}
+	}
+}
+
+static void switchbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	uint64_t guid = 0;
+	osm_switch_t *p_sw;
+	int verbose = 0;
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		char *p_end;
+
+		if (strcmp(p_cmd, "verbose") == 0) {
+			verbose++;
+			p_cmd = next_token(p_last);
+		}
+
+		if (p_cmd) {
+			guid = strtoull(p_cmd, &p_end, 0);
+			if (!guid || *p_end != '\0') {
+				fprintf(out, "Invalid guid specified\n");
+				help_switchbalance(out, 1);
+				return;
+			}
+		}
+	}
+
+	cl_plock_acquire(&p_osm->lock);
+	if (guid) {
+		p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
+		if (!p_sw) {
+			fprintf(out, "guid not found\n");
+			goto lock_exit;
+		}
+
+		switchbalance_check(p_osm, p_sw, out, verbose);
+	} else {
+		cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
+		for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
+		     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
+		     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
+			switchbalance_check(p_osm, p_sw, out, verbose);
+	}
+lock_exit:
+	cl_plock_release(&p_osm->lock);
+	return;
+}
+
+static void lidbalance_check(osm_opensm_t * p_osm,
+			     osm_switch_t * p_sw, FILE * out)
+{
+	uint8_t port_num;
+	const cl_qmap_t *p_port_tbl;
+	osm_port_t *p_port;
+
+	p_port_tbl = &p_osm->subn.port_guid_tbl;
+	for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
+	     p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
+	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
+		uint32_t port_count[255];	/* max ports is a uint8_t */
+		osm_node_t *rem_node[255];
+		uint32_t rem_node_count;
+		uint32_t rem_count[255];
+		osm_physp_t *p_physp;
+		osm_physp_t *p_rem_physp;
+		osm_node_t *p_rem_node;
+		uint32_t port_min_count = 0xFFFFFFFF;
+		uint32_t port_max_count = 0;
+		uint32_t rem_min_count = 0xFFFFFFFF;
+		uint32_t rem_max_count = 0;
+		uint16_t min_lid_ho;
+		uint16_t max_lid_ho;
+		uint16_t lid_ho;
+		uint8_t num_ports;
+		unsigned int i;
+
+		/* we only care about non-switches */
+		if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
+			continue;
+
+		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+		if (min_lid_ho == 0 || max_lid_ho == 0)
+			continue;
+
+		memset(port_count, '\0', sizeof(uint32_t) * 255);
+		memset(rem_node, '\0', sizeof(osm_node_t *) * 255);
+		rem_node_count = 0;
+		memset(rem_count, '\0', sizeof(uint32_t) * 255);
+
+		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
+			boolean_t rem_node_found = FALSE;
+			unsigned int indx = 0;
+
+			port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
+			if (port_num == OSM_NO_PATH)
+				continue;
+
+			p_physp =
+			    osm_node_get_physp_ptr(p_sw->p_node, port_num);
+
+			/* if port is down/unhealthy, can't calculate */
+			if (!p_physp || !osm_physp_is_healthy(p_physp)
+			    || !osm_physp_get_remote(p_physp))
+				continue;
+
+			p_rem_physp = osm_physp_get_remote(p_physp);
+			p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+			/* determine if we've seen this remote node before.
+			 * If not, store it.  If yes, update the counter
+			 */
+			for (i = 0; i < rem_node_count; i++) {
+				if (rem_node[i] == p_rem_node) {
+					rem_node_found = TRUE;
+					indx = i;
+					break;
+				}
+			}
+
+			if (!rem_node_found) {
+				rem_node[rem_node_count] = p_rem_node;
+				rem_count[rem_node_count]++;
+				indx = rem_node_count;
+				rem_node_count++;
+			} else
+				rem_count[indx]++;
+
+			port_count[port_num]++;
+		}
+
+		if (!rem_node_count)
+			continue;
+
+		for (i = 0; i < rem_node_count; i++) {
+			if (rem_count[i] < rem_min_count)
+				rem_min_count = rem_count[i];
+			if (rem_count[i] > rem_max_count)
+				rem_max_count = rem_count[i];
+		}
+
+		num_ports = p_sw->num_ports;
+		for (i = 0; i < num_ports; i++) {
+			if (!port_count[i])
+				continue;
+			if (port_count[i] < port_min_count)
+				port_min_count = port_count[i];
+			if (port_count[i] > port_max_count)
+				port_max_count = port_count[i];
+		}
+
+		/* Output if this CA/router is being forwarded an unbalanced number of
+		 * times to a destination.
+		 */
+		if ((rem_max_count - rem_min_count) > 1) {
+			fprintf(out,
+				"Unbalanced Remote Forwarding: Switch 0x%016"
+				PRIx64 " (%s): ",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+			if (osm_node_get_type(p_port->p_node) ==
+			    IB_NODE_TYPE_CA)
+				fprintf(out, "CA");
+			else if (osm_node_get_type(p_port->p_node) ==
+				 IB_NODE_TYPE_ROUTER)
+				fprintf(out, "Router");
+			fprintf(out, " 0x%016" PRIx64 " (%s): ",
+				cl_ntoh64(p_port->p_node->node_info.node_guid),
+				p_port->p_node->print_desc);
+			for (i = 0; i < rem_node_count; i++) {
+				fprintf(out,
+					"Dest 0x%016" PRIx64 "(%s) - %u ",
+					cl_ntoh64(rem_node[i]->node_info.
+						  node_guid),
+					rem_node[i]->print_desc, rem_count[i]);
+			}
+			fprintf(out, "\n");
+		}
+
+		/* Output if this CA/router is being forwarded through a port
+		 * an unbalanced number of times.
+		 */
+		if ((port_max_count - port_min_count) > 1) {
+			fprintf(out,
+				"Unbalanced Port Forwarding: Switch 0x%016"
+				PRIx64 " (%s): ",
+				cl_ntoh64(p_sw->p_node->node_info.node_guid),
+				p_sw->p_node->print_desc);
+			if (osm_node_get_type(p_port->p_node) ==
+			    IB_NODE_TYPE_CA)
+				fprintf(out, "CA");
+			else if (osm_node_get_type(p_port->p_node) ==
+				 IB_NODE_TYPE_ROUTER)
+				fprintf(out, "Router");
+			fprintf(out, " 0x%016" PRIx64 " (%s): ",
+				cl_ntoh64(p_port->p_node->node_info.node_guid),
+				p_port->p_node->print_desc);
+			for (i = 0; i < num_ports; i++) {
+				if (!port_count[i])
+					continue;
+				fprintf(out, "Port %u - %u: ", i,
+					port_count[i]);
+			}
+			fprintf(out, "\n");
+		}
+	}
+}
+
+static void lidbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+	uint64_t guid = 0;
+	osm_switch_t *p_sw;
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		char *p_end;
+
+		guid = strtoull(p_cmd, &p_end, 0);
+		if (!guid || *p_end != '\0') {
+			fprintf(out, "Invalid switchguid specified\n");
+			help_lidbalance(out, 1);
+			return;
+		}
+	}
+
+	cl_plock_acquire(&p_osm->lock);
+	if (guid) {
+		p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
+		if (!p_sw) {
+			fprintf(out, "switchguid not found\n");
+			goto lock_exit;
+		}
+		lidbalance_check(p_osm, p_sw, out);
+	} else {
+		cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
+		for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
+		     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
+		     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
+			lidbalance_check(p_osm, p_sw, out);
+	}
+
+lock_exit:
+	cl_plock_release(&p_osm->lock);
+	return;
+}
+
+static void dump_conf_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	osm_subn_output_conf(out, &p_osm->subn.opt);
+}
+
+#ifdef ENABLE_OSM_PERF_MGR
+static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	char *p_cmd;
+
+	p_cmd = next_token(p_last);
+	if (p_cmd) {
+		if (strcmp(p_cmd, "enable") == 0) {
+			osm_perfmgr_set_state(&(p_osm->perfmgr),
+					      PERFMGR_STATE_ENABLED);
+		} else if (strcmp(p_cmd, "disable") == 0) {
+			osm_perfmgr_set_state(&(p_osm->perfmgr),
+					      PERFMGR_STATE_DISABLE);
+		} else if (strcmp(p_cmd, "clear_counters") == 0) {
+			osm_perfmgr_clear_counters(&(p_osm->perfmgr));
+		} else if (strcmp(p_cmd, "dump_counters") == 0) {
+			p_cmd = next_token(p_last);
+			if (p_cmd && (strcmp(p_cmd, "mach") == 0)) {
+				osm_perfmgr_dump_counters(&(p_osm->perfmgr),
+							  PERFMGR_EVENT_DB_DUMP_MR);
+			} else {
+				osm_perfmgr_dump_counters(&(p_osm->perfmgr),
+							  PERFMGR_EVENT_DB_DUMP_HR);
+			}
+		} else if (strcmp(p_cmd, "print_counters") == 0) {
+			p_cmd = next_token(p_last);
+			if (p_cmd) {
+				osm_perfmgr_print_counters(&(p_osm->perfmgr),
+							   p_cmd, out);
+			} else {
+				fprintf(out,
+					"print_counters requires a node name to be specified\n");
+			}
+		} else if (strcmp(p_cmd, "sweep_time") == 0) {
+			p_cmd = next_token(p_last);
+			if (p_cmd) {
+				uint16_t time_s = atoi(p_cmd);
+				osm_perfmgr_set_sweep_time_s(&(p_osm->perfmgr),
+							     time_s);
+			} else {
+				fprintf(out,
+					"sweep_time requires a time period (in seconds) to be specified\n");
+			}
+		} else {
+			fprintf(out, "\"%s\" option not found\n", p_cmd);
+		}
+	} else {
+		cl_list_item_t *item;
+		fprintf(out, "Performance Manager status:\n"
+			"state                   : %s\n"
+			"sweep state             : %s\n"
+			"sweep time              : %us\n"
+			"outstanding queries/max : %d/%u\n"
+			"loaded event plugin     :",
+			osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
+			osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)),
+			osm_perfmgr_get_sweep_time_s(&(p_osm->perfmgr)),
+			p_osm->perfmgr.outstanding_queries,
+			p_osm->perfmgr.max_outstanding_queries);
+		for (item = cl_qlist_head(&p_osm->plugin_list);
+		     item != cl_qlist_end(&p_osm->plugin_list);
+		     item = cl_qlist_next(item))
+			fprintf(out, " %s",
+				((osm_epi_plugin_t *)item)->plugin_name);
+		fprintf(out, "\n");
+	}
+}
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+static void quit_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	osm_console_exit(&p_osm->console, &p_osm->log);
+}
+
+static void help_version(FILE * out, int detail)
+{
+	fprintf(out, "version -- print the OSM version\n");
+}
+
+static void version_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+{
+	fprintf(out, "%s build %s %s\n", p_osm->osm_version, __DATE__, __TIME__);
+}
+
+/* more parse routines go here */
+
+static const struct command console_cmds[] = {
+	{"help", &help_command, &help_parse},
+	{"quit", &help_quit, &quit_parse},
+	{"loglevel", &help_loglevel, &loglevel_parse},
+	{"priority", &help_priority, &priority_parse},
+	{"resweep", &help_resweep, &resweep_parse},
+	{"reroute", &help_reroute, &reroute_parse},
+	{"status", &help_status, &status_parse},
+	{"logflush", &help_logflush, &logflush_parse},
+	{"querylid", &help_querylid, &querylid_parse},
+	{"portstatus", &help_portstatus, &portstatus_parse},
+	{"switchbalance", &help_switchbalance, &switchbalance_parse},
+	{"lidbalance", &help_lidbalance, &lidbalance_parse},
+	{"dump_conf", &help_dump_conf, &dump_conf_parse},
+	{"version", &help_version, &version_parse},
+#ifdef ENABLE_OSM_PERF_MGR
+	{"perfmgr", &help_perfmgr, &perfmgr_parse},
+#endif				/* ENABLE_OSM_PERF_MGR */
+	{NULL, NULL, NULL}	/* end of array */
+};
+
+static void parse_cmd_line(char *line, osm_opensm_t * p_osm)
+{
+	char *p_cmd, *p_last;
+	int i, found = 0;
+	FILE *out = p_osm->console.out;
+
+	while (isspace(*line))
+		line++;
+	if (!*line)
+		return;
+
+	/* find first token which is the command */
+	p_cmd = strtok_r(line, " \t\n\r", &p_last);
+	if (p_cmd) {
+		for (i = 0; console_cmds[i].name; i++) {
+			if (loop_command.on) {
+				if (!strcmp(p_cmd, "q")) {
+					loop_command.on = 0;
+				}
+				found = 1;
+				break;
+			}
+			if (!strcmp(p_cmd, console_cmds[i].name)) {
+				found = 1;
+				console_cmds[i].parse_function(&p_last, p_osm,
+							       out);
+				break;
+			}
+		}
+		if (!found) {
+			fprintf(out, "%s : Command not found\n\n", p_cmd);
+			help_command(out, 0);
+		}
+	} else {
+		fprintf(out, "Error parsing command line: `%s'\n", line);
+	}
+	if (loop_command.on) {
+		fprintf(out, "use \"q<ret>\" to quit loop\n");
+		fflush(out);
+	}
+}
+
+void osm_console(osm_opensm_t * p_osm)
+{
+	struct pollfd pollfd[2];
+	char *p_line;
+	size_t len;
+	ssize_t n;
+	struct pollfd *fds;
+	nfds_t nfds;
+	osm_console_t *p_oct = &p_osm->console;
+	osm_log_t *p_log = &p_osm->log;
+
+	pollfd[0].fd = p_oct->socket;
+	pollfd[0].events = POLLIN;
+	pollfd[0].revents = 0;
+
+	pollfd[1].fd = p_oct->in_fd;
+	pollfd[1].events = POLLIN;
+	pollfd[1].revents = 0;
+
+	fds = p_oct->socket < 0 ? &pollfd[1] : pollfd;
+	nfds = p_oct->socket < 0 || pollfd[1].fd < 0 ? 1 : 2;
+
+	if (loop_command.on && loop_command_check_time() &&
+	    loop_command.loop_function) {
+		if (p_oct->out) {
+			loop_command.loop_function(p_osm, p_oct->out);
+			fflush(p_oct->out);
+		} else {
+			loop_command.on = 0;
+		}
+	}
+
+	if (poll(fds, nfds, 1000) <= 0)
+		return;
+
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	if (pollfd[0].revents & POLLIN) {
+		int new_fd = 0;
+		struct sockaddr_in sin;
+		socklen_t len = sizeof(sin);
+		struct hostent *hent;
+		if ((new_fd = accept(p_oct->socket, &sin, &len)) < 0) {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"ERR 4B04: Failed to accept console socket: %s\n",
+				strerror(errno));
+			p_oct->in_fd = -1;
+			return;
+		}
+		if (inet_ntop
+		    (AF_INET, &sin.sin_addr, p_oct->client_ip,
+		     sizeof(p_oct->client_ip)) == NULL) {
+			snprintf(p_oct->client_ip, 64, "STRING_UNKNOWN");
+		}
+		if ((hent = gethostbyaddr((const char *)&sin.sin_addr,
+					  sizeof(struct in_addr),
+					  AF_INET)) == NULL) {
+			snprintf(p_oct->client_hn, 128, "STRING_UNKNOWN");
+		} else {
+			snprintf(p_oct->client_hn, 128, "%s", hent->h_name);
+		}
+		if (is_authorized(p_oct)) {
+			cio_open(p_oct, new_fd, p_log);
+		} else {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"ERR 4B05: Console connection denied: %s (%s)\n",
+				p_oct->client_hn, p_oct->client_ip);
+			close(new_fd);
+		}
+		return;
+	}
+#endif
+
+	if (pollfd[1].revents & POLLIN) {
+		p_line = NULL;
+		/* Get input line */
+		n = getline(&p_line, &len, p_oct->in);
+		if (n > 0) {
+			/* Parse and act on input */
+			parse_cmd_line(p_line, p_osm);
+			if (!loop_command.on) {
+				osm_console_prompt(p_oct->out);
+			}
+		} else
+			osm_console_exit(p_oct, p_log);
+		if (p_line)
+			free(p_line);
+	}
+}
diff --git a/opensm/osm_console_io.c b/opensm/osm_console_io.c
new file mode 100644
index 0000000..3d3ece4
--- /dev/null
+++ b/opensm/osm_console_io.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2005-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2008 HNR Consulting. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Provide a framework for the Console which decouples the connection
+ *    or I/O from the functionality, or commands.
+ *
+ *    Extensible - allows a variety of connection methods independent of
+ *    the console commands.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE		/* for getline */
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+#include <tcpd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <opensm/osm_console_io.h>
+
+static int is_local(char *str)
+{
+	// convenience - checks if just stdin/stdout
+	if (str)
+		return (strcmp(str, OSM_LOCAL_CONSOLE) == 0);
+	return 0;
+}
+
+static int is_loopback(char *str)
+{
+	// convenience - checks if socket based connection
+	if (str)
+		return (strcmp(str, OSM_LOOPBACK_CONSOLE) == 0);
+	return 0;
+}
+
+static int is_remote(char *str)
+{
+	// convenience - checks if socket based connection
+	if (str)
+		return (strcmp(str, OSM_REMOTE_CONSOLE) == 0)
+		    || is_loopback(str);
+	return 0;
+}
+
+int is_console_enabled(osm_subn_opt_t * p_opt)
+{
+	// checks for a variety of types of consoles - default is off or 0
+	if (p_opt)
+		return (is_local(p_opt->console)
+			|| is_loopback(p_opt->console)
+			|| is_remote(p_opt->console));
+	return 0;
+}
+
+
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+static int cio_close(osm_console_t * p_oct)
+{
+	int rtnval = -1;
+	if (p_oct && (p_oct->in_fd > 0)) {
+		rtnval = close(p_oct->in_fd);
+		p_oct->in_fd = -1;
+		p_oct->out_fd = -1;
+		p_oct->in = NULL;
+		p_oct->out = NULL;
+	}
+	return rtnval;
+}
+#endif
+
+/* close the connection */
+static void osm_console_close(osm_console_t * p_oct, osm_log_t * p_log)
+{
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	if ((p_oct->socket > 0) && (p_oct->in_fd != -1)) {
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Console connection closed: %s (%s)\n",
+			p_oct->client_hn, p_oct->client_ip);
+		cio_close(p_oct);
+	}
+	if (p_oct->socket > 0) {
+		close(p_oct->socket);
+		p_oct->socket = -1;
+	}
+#endif
+}
+
+
+/**********************************************************************
+ * Do authentication & authorization check
+ **********************************************************************/
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+int is_authorized(osm_console_t * p_oct)
+{
+	/* allowed to use the console? */
+	p_oct->authorized = !is_remote(p_oct->client_type) ||
+	    hosts_ctl(OSM_DAEMON_NAME, p_oct->client_hn, p_oct->client_ip,
+		      "STRING_UNKNOWN");
+	return p_oct->authorized;
+}
+#endif
+
+void osm_console_prompt(FILE * out)
+{
+	if (out) {
+		fprintf(out, "OpenSM %s", OSM_COMMAND_PROMPT);
+		fflush(out);
+	}
+}
+
+int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log)
+{
+	p_oct->socket = -1;
+	strncpy(p_oct->client_type, opt->console, sizeof(p_oct->client_type));
+
+	/* set up the file descriptors for the console */
+	if (strcmp(opt->console, OSM_LOCAL_CONSOLE) == 0) {
+		p_oct->in = stdin;
+		p_oct->out = stdout;
+		p_oct->in_fd = fileno(stdin);
+		p_oct->out_fd = fileno(stdout);
+
+		osm_console_prompt(p_oct->out);
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	} else if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0
+		   || strcmp(opt->console, OSM_LOOPBACK_CONSOLE) == 0) {
+		struct sockaddr_in sin;
+		int optval = 1;
+
+		if ((p_oct->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"ERR 4B01: Failed to open console socket: %s\n",
+				strerror(errno));
+			return -1;
+		}
+		setsockopt(p_oct->socket, SOL_SOCKET, SO_REUSEADDR,
+			   &optval, sizeof(optval));
+		sin.sin_family = AF_INET;
+		sin.sin_port = htons(opt->console_port);
+		if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0)
+			sin.sin_addr.s_addr = htonl(INADDR_ANY);
+		else
+			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+		if (bind(p_oct->socket, &sin, sizeof(sin)) < 0) {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"ERR 4B02: Failed to bind console socket: %s\n",
+				strerror(errno));
+			return -1;
+		}
+		if (listen(p_oct->socket, 1) < 0) {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"ERR 4B03: Failed to listen on socket: %s\n",
+				strerror(errno));
+			return -1;
+		}
+
+		signal(SIGPIPE, SIG_IGN);	/* protect ourselves from closed pipes */
+		p_oct->in = NULL;
+		p_oct->out = NULL;
+		p_oct->in_fd = -1;
+		p_oct->out_fd = -1;
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Console listening on port %d\n", opt->console_port);
+#endif
+	}
+
+	return 0;
+}
+
+/* clean up and release resources */
+void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log)
+{
+	// clean up and release resources, currently just close the socket
+	osm_console_close(p_oct, p_log);
+}
+
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log)
+{
+	// returns zero if opened fine, -1 otherwise
+	char *p_line;
+	size_t len;
+	ssize_t n;
+
+	if (p_oct->in_fd >= 0) {
+		FILE *file = fdopen(new_fd, "w+");
+
+		fprintf(file, "OpenSM Console connection already in use\n"
+			"   kill other session (y/n)? ");
+		fflush(file);
+		p_line = NULL;
+		n = getline(&p_line, &len, file);
+		if (n > 0 && (p_line[0] == 'y' || p_line[0] == 'Y')) {
+			osm_console_close(p_oct, p_log);
+		} else {
+			OSM_LOG(p_log, OSM_LOG_INFO,
+				"Console connection aborted: %s (%s)\n",
+				p_oct->client_hn, p_oct->client_ip);
+			close(new_fd);
+			return -1;
+		}
+	}
+	p_oct->in_fd = new_fd;
+	p_oct->out_fd = p_oct->in_fd;
+	p_oct->in = fdopen(p_oct->in_fd, "w+");
+	p_oct->out = p_oct->in;
+	osm_console_prompt(p_oct->out);
+	OSM_LOG(p_log, OSM_LOG_INFO,
+		"Console connection accepted: %s (%s)\n",
+		p_oct->client_hn, p_oct->client_ip);
+
+	return (p_oct->in == NULL) ? -1 : 0;
+}
+#endif
diff --git a/opensm/osm_db_files.c b/opensm/osm_db_files.c
new file mode 100644
index 0000000..907b7c7
--- /dev/null
+++ b/opensm/osm_db_files.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * Implementation of the osm_db interface using simple text files
+ */
+
+#if HAVE_CONFIG_H
+#  include <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);
+
+	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, "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);
+
+	/* 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, "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;
+	char *endptr = NULL;
+	unsigned int line_num;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* take the lock on the domain */
+	cl_spinlock_acquire(&p_domain_imp->lock);
+
+	/* open the file - read mode */
+	p_file = fopen(p_domain_imp->file_name, "r");
+
+	if (!p_file) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6103: "
+			"Failed to open the db file:%s\n",
+			p_domain_imp->file_name);
+		status = 1;
+		goto Exit;
+	}
+
+	/* parse the file allocating new hash tables as required */
+	/*
+	   states:
+	   before_key (0) -> in_key (1)
+
+	   before_key: if a word on the first byte - it is the key. state=in_key
+	   the rest of the line is start of the value.
+	   in_key: unless the line is empty - add it (with newlines) to the value.
+	   if empty: state=before_key
+	 */
+	status = 0;
+	before_key = TRUE;
+	line_num = 0;
+	/* if we got to EOF in the middle of a key we add a last newline */
+	while ((fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) ||
+	       ((before_key == FALSE) && strcpy(sLine, "\n"))
+	    ) {
+		line_num++;
+		if (before_key) {
+			if ((sLine[0] != ' ') && (sLine[0] != '\t')
+			    && (sLine[0] != '\n')) {
+				/* we got a new key */
+				before_key = FALSE;
+
+				/* handle the key */
+				p_first_word =
+				    strtok_r(sLine, " \t\n", &p_last);
+				if (!p_first_word) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6104: "
+						"Failed to get key from line:%u : %s (file:%s)\n",
+						line_num, sLine,
+						p_domain_imp->file_name);
+					status = 1;
+					goto EndParsing;
+				}
+				if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610A: "
+						"Illegal key from line:%u : %s (file:%s)\n",
+						line_num, sLine,
+						p_domain_imp->file_name);
+					status = 1;
+					goto EndParsing;
+				}
+
+				p_key =
+				    (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, "ERR 6105: "
+					"How did we get here? line:%u : %s (file:%s)\n",
+					line_num, sLine,
+					p_domain_imp->file_name);
+				status = 1;
+				goto EndParsing;
+			}
+		} /* before key */
+		else {
+			/* we already have a key */
+
+			if (sLine[0] == '\n') {
+				/* got an end of key */
+				before_key = TRUE;
+
+				/* make sure the key was not previously used */
+				if (st_lookup(p_domain_imp->p_hash,
+					      (st_data_t) p_key,
+					      (void *) & p_prev_val)) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6106: "
+						"Key:%s already exists in:%s with value:%s."
+						" Removing it\n",
+						p_key,
+						p_domain_imp->file_name,
+						p_prev_val);
+				} else {
+					p_prev_val = NULL;
+				}
+
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Got key:%s value:%s\n", p_key,
+					p_accum_val);
+
+				/* check that the key is a number */
+				if (!strtouq(p_key, &endptr, 0)
+				    && *endptr != '\0') {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610B: "
+						"Key:%s is invalid\n", p_key);
+				} else {
+					/* store our key and value */
+					st_insert(p_domain_imp->p_hash,
+						  (st_data_t) p_key,
+						  (st_data_t) p_accum_val);
+				}
+			} else {
+				/* accumulate into the value */
+				p_prev_val = p_accum_val;
+				p_accum_val =
+				    (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;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+static 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);
+
+	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, "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, "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, "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 */
+static 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;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+static 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, (void *) & p_val))
+		p_val = NULL;
+
+	cl_spinlock_release(&p_domain_imp->lock);
+
+	return p_val;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_update(IN osm_db_domain_t * p_domain,
+	      IN char *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, (void *) & p_prev_val)) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Key:%s previously exists in:%s with value:%s\n",
+			p_key, p_domain_imp->file_name, p_prev_val);
+		p_new_key = p_key;
+	} 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);
+
+	cl_spinlock_acquire(&p_domain_imp->lock);
+	if (st_delete(p_domain_imp->p_hash,
+		      (void *) & p_key, (void *) & p_prev_val)) {
+		if (st_lookup(p_domain_imp->p_hash,
+			      (st_data_t) p_key, (void *) & p_prev_val)) {
+			OSM_LOG(p_log, OSM_LOG_ERROR,
+				"key:%s still exists in:%s with value:%s\n",
+				p_key, p_domain_imp->file_name, p_prev_val);
+			res = 1;
+		} else {
+			free(p_key);
+			free(p_prev_val);
+			res = 0;
+		}
+	} else {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"fail to find key:%s. delete failed\n", p_key);
+		res = 1;
+	}
+	cl_spinlock_release(&p_domain_imp->lock);
+
+	OSM_LOG_EXIT(p_log);
+	return res;
+}
+
+#ifdef TEST_OSMDB
+#include <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
diff --git a/opensm/osm_db_pack.c b/opensm/osm_db_pack.c
new file mode 100644
index 0000000..bf56169
--- /dev/null
+++ b/opensm/osm_db_pack.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <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)
+{
+	return strtoull(p_guid_str, NULL, 0);
+}
+
+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));
+}
diff --git a/opensm/osm_drop_mgr.c b/opensm/osm_drop_mgr.c
new file mode 100644
index 0000000..215a155
--- /dev/null
+++ b/opensm/osm_drop_mgr.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_sm.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>
+#include <opensm/osm_ucast_mgr.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_router(osm_sm_t * sm, IN const ib_net64_t portguid)
+{
+	osm_router_t *p_rtr;
+	cl_qmap_t *p_rtr_guid_tbl;
+
+	p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl;
+	p_rtr = (osm_router_t *) cl_qmap_remove(p_rtr_guid_tbl, portguid);
+	if (p_rtr != (osm_router_t *) cl_qmap_end(p_rtr_guid_tbl)) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Cleaned router for port guid 0x%016" PRIx64 "\n",
+			cl_ntoh64(portguid));
+		osm_router_delete(&p_rtr);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void drop_mgr_clean_physp(osm_sm_t * sm, IN osm_physp_t * p_physp)
+{
+	osm_physp_t *p_remote_physp;
+	osm_port_t *p_remote_port;
+
+	p_remote_physp = osm_physp_get_remote(p_physp);
+	if (p_remote_physp) {
+		p_remote_port = osm_get_port_by_guid(sm->p_subn,
+						     p_remote_physp->port_guid);
+
+		if (p_remote_port) {
+			/* Let's check if this is a case of link that is lost (both ports
+			   weren't recognized), or a "hiccup" in the subnet - in which case
+			   the remote port was recognized, and its state is ACTIVE.
+			   If this is just a "hiccup" - force a heavy sweep in the next sweep.
+			   We don't want to lose that part of the subnet. */
+			if (p_remote_port->discovery_count &&
+			    osm_physp_get_port_state(p_remote_physp) ==
+			    IB_LINK_ACTIVE) {
+				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+					"Forcing new heavy sweep. Remote "
+					"port 0x%016" PRIx64 " port num: %u "
+					"was recognized in ACTIVE state\n",
+					cl_ntoh64(p_remote_physp->port_guid),
+					p_remote_physp->port_num);
+				sm->p_subn->force_heavy_sweep = TRUE;
+			}
+
+			/* If the remote node is ca or router - need to remove the remote port,
+			   since it is no longer reachable. This can be done if we reset the
+			   discovery count of the remote port. */
+			if (!p_remote_physp->p_node->sw) {
+				p_remote_port->discovery_count = 0;
+				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+					"Resetting discovery count of node: "
+					"0x%016" PRIx64 " port num:%u\n",
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_remote_physp->p_node)),
+					p_remote_physp->port_num);
+			}
+		}
+
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Unlinking local node 0x%016" PRIx64 ", port %u"
+			"\n\t\t\t\tand remote node 0x%016" PRIx64
+			", port %u\n",
+			cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)),
+			p_physp->port_num,
+			cl_ntoh64(osm_node_get_node_guid
+				  (p_remote_physp->p_node)),
+			p_remote_physp->port_num);
+
+		if (sm->ucast_mgr.cache_valid)
+			osm_ucast_cache_add_link(&sm->ucast_mgr,
+						 p_physp, p_remote_physp);
+
+		osm_physp_unlink(p_physp, p_remote_physp);
+
+	}
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Clearing node 0x%016" PRIx64 " physical port number %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)),
+		p_physp->port_num);
+
+	osm_physp_destroy(p_physp);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port)
+{
+	ib_net64_t port_guid;
+	osm_port_t *p_port_check;
+	cl_qmap_t *p_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;
+	osm_node_t *p_node;
+	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(sm->p_log);
+
+	port_guid = osm_port_get_guid(p_port);
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Unreachable port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	p_port_check =
+	    (osm_port_t *) cl_qmap_remove(&sm->p_subn->port_guid_tbl,
+					  port_guid);
+	if (p_port_check != p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0101: "
+			"Port 0x%016" PRIx64 " not in guid table\n",
+			cl_ntoh64(port_guid));
+		goto Exit;
+	}
+
+	p_sm_guid_tbl = &sm->p_subn->sm_guid_tbl;
+	p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_guid_tbl, port_guid);
+	if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl)) {
+		/* need to remove this item */
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Cleaned SM for port guid 0x%016" PRIx64 "\n",
+			cl_ntoh64(port_guid));
+
+		free(p_sm);
+	}
+
+	__osm_drop_mgr_remove_router(sm, port_guid);
+
+	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Clearing abandoned LID range [%u,%u]\n",
+		min_lid_ho, max_lid_ho);
+
+	p_port_lid_tbl = &sm->p_subn->port_lid_tbl;
+	for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
+		cl_ptr_vector_set(p_port_lid_tbl, lid_ho, NULL);
+
+	drop_mgr_clean_physp(sm, p_port->p_physp);
+
+	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_get_mgrp_by_mlid(sm->p_subn, p_mcm->mlid);
+		if (p_mgrp) {
+			osm_mgrp_delete_port(sm->p_subn, sm->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(&notice, 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 = sm->p_subn->sm_base_lid;
+	/* following C14-72.1.2 and table 119 p725 */
+	/* we need to provide the GID */
+	port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
+	port_gid.unicast.interface_id = port_guid;
+	memcpy(&(notice.data_details.ntc_64_67.gid),
+	       &(port_gid), sizeof(ib_gid_t));
+
+	/* According to page 653 - the issuer gid in this case of trap
+	   is the SM gid, since the SM is the initiator of this trap. */
+	notice.issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
+	notice.issuer_gid.unicast.interface_id = sm->p_subn->sm_port_guid;
+
+	status = osm_report_notice(sm->p_log, sm->p_subn, &notice);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0103: "
+			"Error sending trap reports (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	OSM_LOG(sm->p_log, OSM_LOG_INFO,
+		"Removed port with GUID:0x%016" PRIx64
+		" LID range [%u, %u] of node:%s\n",
+		cl_ntoh64(port_gid.unicast.interface_id),
+		min_lid_ho, max_lid_ho,
+		p_node ? p_node->print_desc : "UNKNOWN");
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_drop_mgr_remove_switch(osm_sm_t * sm, IN osm_node_t * p_node)
+{
+	osm_switch_t *p_sw;
+	cl_qmap_t *p_sw_guid_tbl;
+	ib_net64_t node_guid;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	node_guid = osm_node_get_node_guid(p_node);
+	p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl;
+
+	p_sw = (osm_switch_t *) cl_qmap_remove(p_sw_guid_tbl, node_guid);
+	if (p_sw == (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl)) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0102: "
+			"Node 0x%016" PRIx64 " not in switch table\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+	} else {
+		p_node->sw = NULL;
+		osm_switch_delete(&p_sw);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_drop_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node)
+{
+	osm_physp_t *p_physp;
+	osm_port_t *p_port;
+	osm_node_t *p_node_check;
+	uint32_t port_num;
+	uint32_t max_ports;
+	ib_net64_t port_guid;
+	boolean_t return_val = FALSE;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Unreachable node 0x%016" PRIx64 "\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+	if (sm->ucast_mgr.cache_valid)
+		osm_ucast_cache_add_node(&sm->ucast_mgr, p_node);
+
+	/*
+	   Delete all the logical and physical port objects
+	   associated with this node.
+	 */
+	max_ports = osm_node_get_num_physp(p_node);
+	for (port_num = 0; port_num < max_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		if (p_physp) {
+			port_guid = osm_physp_get_port_guid(p_physp);
+
+			p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+
+			if (p_port)
+				__osm_drop_mgr_remove_port(sm, p_port);
+			else
+				drop_mgr_clean_physp(sm, p_physp);
+		}
+	}
+
+	return_val = TRUE;
+
+	if (p_node->sw)
+		__osm_drop_mgr_remove_switch(sm, p_node);
+
+	p_node_check =
+	    (osm_node_t *) cl_qmap_remove(&sm->p_subn->node_guid_tbl,
+					  osm_node_get_node_guid(p_node));
+	if (p_node_check != p_node) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0105: "
+			"Node 0x%016" PRIx64 " not in guid table\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+	}
+
+	/* free memory allocated to node */
+	osm_node_delete(&p_node);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (return_val);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_drop_mgr_check_node(osm_sm_t * sm, IN osm_node_t * p_node)
+{
+	ib_net64_t node_guid;
+	osm_physp_t *p_physp;
+	osm_port_t *p_port;
+	ib_net64_t port_guid;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	node_guid = osm_node_get_node_guid(p_node);
+
+	if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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(sm->p_log, OSM_LOG_VERBOSE,
+			"Node 0x%016" PRIx64 " no switch in table\n",
+			cl_ntoh64(node_guid));
+
+		__osm_drop_mgr_process_node(sm, p_node);
+		goto Exit;
+	}
+
+	/* Make sure we have a port object for port zero */
+	p_physp = osm_node_get_physp_ptr(p_node, 0);
+	if (!p_physp) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Node 0x%016" PRIx64 " no valid physical port 0\n",
+			cl_ntoh64(node_guid));
+
+		__osm_drop_mgr_process_node(sm, p_node);
+		goto Exit;
+	}
+
+	port_guid = osm_physp_get_port_guid(p_physp);
+
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Node 0x%016" PRIx64 " has no port object\n",
+			cl_ntoh64(node_guid));
+
+		__osm_drop_mgr_process_node(sm, p_node);
+		goto Exit;
+	}
+
+	if (p_port->discovery_count == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Node 0x%016" PRIx64 " port has discovery count zero\n",
+			cl_ntoh64(node_guid));
+
+		__osm_drop_mgr_process_node(sm, p_node);
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_drop_mgr_process(osm_sm_t * sm)
+{
+	cl_qmap_t *p_node_guid_tbl;
+	cl_qmap_t *p_port_guid_tbl;
+	osm_port_t *p_port;
+	osm_port_t *p_next_port;
+	osm_node_t *p_node;
+	osm_node_t *p_next_node;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_node_guid_tbl = &sm->p_subn->node_guid_tbl;
+	p_port_guid_tbl = &sm->p_subn->port_guid_tbl;
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+
+	p_next_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl);
+	while (p_next_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl)) {
+		p_node = p_next_node;
+		p_next_node =
+		    (osm_node_t *) cl_qmap_next(&p_next_node->map_item);
+
+		CL_ASSERT(cl_qmap_key(&p_node->map_item) ==
+			  osm_node_get_node_guid(p_node));
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Checking node 0x%016" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+		/*
+		   Check if this node was discovered during the last sweep.
+		   If not, it is unreachable in the current subnet, and
+		   should therefore be removed from the subnet object.
+		 */
+		if (p_node->discovery_count == 0)
+			__osm_drop_mgr_process_node(sm, 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);
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Checking full discovery of node 0x%016" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH)
+			continue;
+
+		/* We are handling a switch node */
+		__osm_drop_mgr_check_node(sm, p_node);
+	}
+
+	p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
+	while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) {
+		p_port = p_next_port;
+		p_next_port =
+		    (osm_port_t *) cl_qmap_next(&p_next_port->map_item);
+
+		CL_ASSERT(cl_qmap_key(&p_port->map_item) ==
+			  osm_port_get_guid(p_port));
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Checking port 0x%016" PRIx64 "\n",
+			cl_ntoh64(osm_port_get_guid(p_port)));
+
+		/*
+		   If the port is unreachable, remove it from the guid table.
+		 */
+		if (p_port->discovery_count == 0)
+			__osm_drop_mgr_remove_port(sm, p_port);
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_dump.c b/opensm/osm_dump.c
new file mode 100644
index 0000000..7e0ba47
--- /dev/null
+++ b/opensm/osm_dump.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Various OpenSM dumpers
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.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>
+
+static void dump_ucast_path_distribution(cl_map_item_t * p_map_item,
+					 FILE *file, void *cxt)
+{
+	osm_node_t *p_node;
+	osm_node_t *p_remote_node;
+	uint8_t i;
+	uint8_t num_ports;
+	uint32_t num_paths;
+	ib_net64_t remote_guid_ho;
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+
+	p_node = p_sw->p_node;
+	num_ports = p_sw->num_ports;
+
+	fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n"
+		"Port : Path Count Through Port",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+	for (i = 0; i < num_ports; i++) {
+		num_paths = osm_switch_path_count_get(p_sw, i);
+		fprintf(file, "\n %03u : %u", i, num_paths);
+		if (i == 0) {
+			fprintf(file, " (switch management port)");
+			continue;
+		}
+
+		p_remote_node = osm_node_get_remote_node(p_node, i, NULL);
+		if (p_remote_node == NULL)
+			continue;
+
+		remote_guid_ho =
+		    cl_ntoh64(osm_node_get_node_guid(p_remote_node));
+
+		switch (osm_node_get_type(p_remote_node)) {
+		case IB_NODE_TYPE_SWITCH:
+			fprintf(file, " (link to switch");
+			break;
+		case IB_NODE_TYPE_ROUTER:
+			fprintf(file, " (link to router");
+			break;
+		case IB_NODE_TYPE_CA:
+			fprintf(file, " (link to CA");
+			break;
+		default:
+			fprintf(file, " (link to unknown node type");
+			break;
+		}
+
+		fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho);
+	}
+
+	fprintf(file, "\n");
+}
+
+static void dump_ucast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	const osm_node_t *p_node;
+	osm_port_t *p_port;
+	uint8_t port_num;
+	uint8_t num_hops;
+	uint8_t best_hops;
+	uint8_t best_port;
+	uint16_t max_lid_ho;
+	uint16_t lid_ho, base_lid;
+	boolean_t direct_route_exists = FALSE;
+	boolean_t dor;
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+	osm_opensm_t *p_osm = cxt;
+
+	p_node = p_sw->p_node;
+
+	max_lid_ho = p_sw->max_lid_ho;
+
+	fprintf(file, "__osm_ucast_mgr_dump_ucast_routes: "
+		"Switch 0x%016" PRIx64 "\nLID    : Port : Hops : Optimal\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+	dor = (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_DOR);
+
+	for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) {
+		fprintf(file, "0x%04X : ", lid_ho);
+
+		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid_ho);
+		if (!p_port) {
+			fprintf(file, "UNREACHABLE\n");
+			continue;
+		}
+
+		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.
+		 */
+		if (p_port->p_node->sw) {
+			/* Target LID is switch.
+			   Get its base lid and check hop count for this base LID only. */
+			base_lid = osm_node_get_base_lid(p_port->p_node, 0);
+			base_lid = cl_ntoh16(base_lid);
+			num_hops =
+			    osm_switch_get_hop_count(p_sw, base_lid, port_num);
+		} else {
+			/* Target LID is not switch (CA or router).
+			   Check if we have route to this target from current switch. */
+			num_hops =
+			    osm_switch_get_hop_count(p_sw, lid_ho, port_num);
+			if (num_hops != OSM_NO_PATH) {
+				direct_route_exists = TRUE;
+				base_lid = lid_ho;
+			} else {
+				osm_physp_t *p_physp = p_port->p_physp;
+
+				if (!p_physp || !p_physp->p_remote_physp ||
+				    !p_physp->p_remote_physp->p_node->sw)
+					num_hops = OSM_NO_PATH;
+				else {
+					base_lid =
+					    osm_node_get_base_lid(p_physp->
+								  p_remote_physp->
+								  p_node, 0);
+					base_lid = cl_ntoh16(base_lid);
+					num_hops =
+					    p_physp->p_remote_physp->p_node->
+					    sw ==
+					    p_sw ? 0 :
+					    osm_switch_get_hop_count(p_sw,
+								     base_lid,
+								     port_num);
+				}
+			}
+		}
+
+		if (num_hops == OSM_NO_PATH) {
+			fprintf(file, "UNREACHABLE\n");
+			continue;
+		}
+
+		best_hops = osm_switch_get_least_hops(p_sw, base_lid);
+		if (!p_port->p_node->sw && !direct_route_exists) {
+			best_hops++;
+			num_hops++;
+		}
+
+		fprintf(file, "%03u  : %02u   : ", port_num, num_hops);
+
+		if (best_hops == num_hops)
+			fprintf(file, "yes");
+		else {
+			/* No LMC Optimization */
+			best_port = osm_switch_recommend_path(p_sw, p_port,
+							      lid_ho, 1, TRUE,
+							      dor);
+			fprintf(file, "No %u hop path possible via port %u!",
+				best_hops, best_port);
+		}
+
+		fprintf(file, "\n");
+	}
+}
+
+static void dump_mcast_routes(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+	osm_mcast_tbl_t *p_tbl;
+	int16_t mlid_ho = 0;
+	int16_t mlid_start_ho;
+	uint8_t position = 0;
+	int16_t block_num = 0;
+	boolean_t first_mlid;
+	boolean_t first_port;
+	const osm_node_t *p_node;
+	uint16_t i, j;
+	uint16_t mask_entry;
+	char sw_hdr[256];
+	char mlid_hdr[32];
+
+	p_node = p_sw->p_node;
+
+	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
+
+	sprintf(sw_hdr, "\nSwitch 0x%016" PRIx64 "\nLID    : Out Port(s)\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+	first_mlid = TRUE;
+	while (block_num <= p_tbl->max_block_in_use) {
+		mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
+		for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) {
+			mlid_ho = mlid_start_ho + i;
+			position = 0;
+			first_port = TRUE;
+			sprintf(mlid_hdr, "0x%04X :",
+				mlid_ho + IB_LID_MCAST_START_HO);
+			while (position <= p_tbl->max_position) {
+				mask_entry =
+				    cl_ntoh16((*p_tbl->
+					       p_mask_tbl)[mlid_ho][position]);
+				if (mask_entry == 0) {
+					position++;
+					continue;
+				}
+				for (j = 0; j < 16; j++) {
+					if ((1 << j) & mask_entry) {
+						if (first_mlid) {
+							fprintf(file, "%s",
+								sw_hdr);
+							first_mlid = FALSE;
+						}
+						if (first_port) {
+							fprintf(file, "%s",
+								mlid_hdr);
+							first_port = FALSE;
+						}
+						fprintf(file, " 0x%03X ",
+							j + (position * 16));
+					}
+				}
+				position++;
+			}
+			if (first_port == FALSE)
+				fprintf(file, "\n");
+		}
+		block_num++;
+	}
+}
+
+static void dump_lid_matrix(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+	osm_opensm_t *p_osm = cxt;
+	osm_node_t *p_node = p_sw->p_node;
+	unsigned max_lid = p_sw->max_lid_ho;
+	unsigned max_port = p_sw->num_ports;
+	uint16_t lid;
+	uint8_t port;
+
+	fprintf(file, "Switch: guid 0x%016" PRIx64 "\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+	for (lid = 1; lid <= max_lid; lid++) {
+		osm_port_t *p_port;
+		if (osm_switch_get_least_hops(p_sw, lid) == OSM_NO_PATH)
+			continue;
+		fprintf(file, "0x%04x:", lid);
+		for (port = 0; port < max_port; port++)
+			fprintf(file, " %02x",
+				osm_switch_get_hop_count(p_sw, lid, port));
+		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
+		if (p_port)
+			fprintf(file, " # portguid 0x016%" PRIx64,
+				cl_ntoh64(osm_port_get_guid(p_port)));
+		fprintf(file, "\n");
+	}
+}
+
+static void dump_ucast_lfts(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+	osm_opensm_t *p_osm = cxt;
+	osm_node_t *p_node = p_sw->p_node;
+	unsigned max_lid = p_sw->max_lid_ho;
+	unsigned max_port = p_sw->num_ports;
+	uint16_t lid;
+	uint8_t port;
+
+	fprintf(file, "Unicast lids [0-%u] of switch Lid %u guid 0x%016"
+		PRIx64 " (\'%s\'):\n",
+		max_lid, cl_ntoh16(osm_node_get_base_lid(p_node, 0)),
+		cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc);
+	for (lid = 0; lid <= max_lid; lid++) {
+		osm_port_t *p_port;
+		port = osm_switch_get_port_by_lid(p_sw, lid);
+
+		if (port >= max_port)
+			continue;
+
+		fprintf(file, "0x%04x %03u # ", lid, port);
+
+		p_port = cl_ptr_vector_get(&p_osm->subn.port_lid_tbl, lid);
+		if (p_port) {
+			p_node = p_port->p_node;
+			fprintf(file, "%s portguid 0x%016" PRIx64 ": \'%s\'",
+				ib_get_node_type_str(osm_node_get_type(p_node)),
+				cl_ntoh64(osm_port_get_guid(p_port)),
+				p_node->print_desc);
+		} else
+			fprintf(file, "unknown node and type");
+		fprintf(file, "\n");
+	}
+	fprintf(file, "%u lids dumped\n", max_lid);
+}
+
+static void dump_topology_node(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	osm_node_t *p_node = (osm_node_t *) p_map_item;
+	uint32_t cPort;
+	osm_node_t *p_nbnode;
+	osm_physp_t *p_physp, *p_default_physp, *p_rphysp;
+	uint8_t link_speed_act;
+
+	if (!p_node->node_info.num_ports)
+		return;
+
+	for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) {
+		uint8_t port_state;
+
+		p_physp = osm_node_get_physp_ptr(p_node, cPort);
+		if (!p_physp)
+			continue;
+
+		p_rphysp = p_physp->p_remote_physp;
+		if (!p_rphysp)
+			continue;
+
+		CL_ASSERT(cPort == p_physp->port_num);
+
+		if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+			p_default_physp = osm_node_get_physp_ptr(p_node, 0);
+		else
+			p_default_physp = p_physp;
+
+		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
+			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
+			" VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+			p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ?
+			"SW" : p_node->node_info.node_type ==
+			IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type ==
+			IB_NODE_TYPE_ROUTER ? "Rt" : "**",
+			p_default_physp->port_info.base_lid ==
+			p_default_physp->port_info.
+			master_sm_base_lid ? "-SM" : "",
+			p_node->node_info.num_ports,
+			cl_ntoh64(p_node->node_info.sys_guid),
+			cl_ntoh64(p_node->node_info.node_guid),
+			cl_ntoh64(p_physp->port_guid),
+			cl_ntoh32(ib_node_info_get_vendor_id
+				  (&p_node->node_info)),
+			cl_ntoh16(p_node->node_info.device_id),
+			cl_ntoh32(p_node->node_info.revision),
+			p_node->print_desc,
+			cl_ntoh16(p_default_physp->port_info.base_lid), cPort);
+
+		p_nbnode = p_rphysp->p_node;
+
+		if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH)
+			p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0);
+		else
+			p_default_physp = p_rphysp;
+
+		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
+			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
+			" VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+			p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ?
+			"SW" : p_nbnode->node_info.node_type ==
+			IB_NODE_TYPE_CA ? "CA" :
+			p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ?
+			"Rt" : "**",
+			p_default_physp->port_info.base_lid ==
+			p_default_physp->port_info.
+			master_sm_base_lid ? "-SM" : "",
+			p_nbnode->node_info.num_ports,
+			cl_ntoh64(p_nbnode->node_info.sys_guid),
+			cl_ntoh64(p_nbnode->node_info.node_guid),
+			cl_ntoh64(p_rphysp->port_guid),
+			cl_ntoh32(ib_node_info_get_vendor_id
+				  (&p_nbnode->node_info)),
+			cl_ntoh32(p_nbnode->node_info.device_id),
+			cl_ntoh32(p_nbnode->node_info.revision),
+			p_nbnode->print_desc,
+			cl_ntoh16(p_default_physp->port_info.base_lid),
+			p_rphysp->port_num);
+
+		port_state = ib_port_info_get_port_state(&p_physp->port_info);
+		link_speed_act =
+		    ib_port_info_get_link_speed_active(&p_physp->port_info);
+
+		fprintf(file, "PHY=%s LOG=%s SPD=%s\n",
+			p_physp->port_info.link_width_active == 1 ? "1x" :
+			p_physp->port_info.link_width_active == 2 ? "4x" :
+			p_physp->port_info.link_width_active == 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" : "??");
+	}
+}
+
+static void print_node_report(cl_map_item_t *p_map_item, FILE *file, void *cxt)
+{
+	osm_node_t *p_node = (osm_node_t *) p_map_item;
+	osm_opensm_t *osm = cxt;
+	const osm_physp_t *p_physp, *p_remote_physp;
+	const ib_port_info_t *p_pi;
+	uint8_t port_num;
+	uint32_t num_ports;
+	uint8_t node_type;
+
+	node_type = osm_node_get_type(p_node);
+
+	num_ports = osm_node_get_num_physp(p_node);
+	port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1;
+	for (; port_num < num_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		if (!p_physp)
+			continue;
+
+		fprintf(file, "%-11s : %s : %02X :",
+			osm_get_manufacturer_str(cl_ntoh64
+						 (osm_node_get_node_guid
+						  (p_node))),
+			osm_get_node_type_str_fixed_width(node_type), port_num);
+
+		p_pi = &p_physp->port_info;
+
+		/*
+		 * Port state is not defined for switch port 0
+		 */
+		if (port_num == 0)
+			fprintf(file, "     :");
+		else
+			fprintf(file, " %s :",
+				osm_get_port_state_str_fixed_width
+				(ib_port_info_get_port_state(p_pi)));
+
+		/*
+		 * LID values are only meaningful in select cases.
+		 */
+		if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN
+		    && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0)
+			|| node_type != IB_NODE_TYPE_SWITCH))
+			fprintf(file, " %04X :  %01X  :",
+				cl_ntoh16(p_pi->base_lid),
+				ib_port_info_get_lmc(p_pi));
+		else
+			fprintf(file, "      :     :");
+
+		if (port_num != 0)
+			fprintf(file, " %s : %s : %s ",
+				osm_get_mtu_str
+				(ib_port_info_get_neighbor_mtu(p_pi)),
+				osm_get_lwa_str(p_pi->link_width_active),
+				osm_get_lsa_str
+				(ib_port_info_get_link_speed_active(p_pi)));
+		else
+			fprintf(file, "      :     :     ");
+
+		if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid)
+			fprintf(file, "* %016" PRIx64 " *",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
+		else
+			fprintf(file, ": %016" PRIx64 " :",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
+
+		if (port_num
+		    && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) {
+			p_remote_physp = osm_physp_get_remote(p_physp);
+			if (p_remote_physp)
+				fprintf(file, " %016" PRIx64 " (%02X)",
+					cl_ntoh64(osm_physp_get_port_guid
+					 (p_remote_physp)),
+					osm_physp_get_port_num(p_remote_physp));
+			else
+				fprintf(file, " UNKNOWN");
+		}
+
+		fprintf(file, "\n");
+	}
+
+	fprintf(file, "------------------------------------------------------"
+		"------------------------------------------------\n");
+}
+
+/**********************************************************************
+ **********************************************************************/
+struct dump_context {
+	osm_opensm_t *p_osm;
+	FILE *file;
+	void (*func) (cl_map_item_t *, FILE *, void *);
+	void *cxt;
+};
+
+static void dump_item(cl_map_item_t *item, void *cxt)
+{
+	((struct dump_context *)cxt)->func(item,
+					   ((struct dump_context *)cxt)->file,
+					   ((struct dump_context *)cxt)->cxt);
+}
+
+static void dump_qmap(FILE *file, cl_qmap_t *map,
+		      void (*func)(cl_map_item_t *, FILE *, void *), void *cxt)
+{
+	struct dump_context dump_context;
+
+	dump_context.file = file;
+	dump_context.func = func;
+	dump_context.cxt = cxt;
+
+	cl_qmap_apply_func(map, dump_item, &dump_context);
+}
+
+void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name,
+			   cl_qmap_t * map,
+			   void (*func) (cl_map_item_t *, FILE *, void *),
+			   void *cxt)
+{
+	char path[1024];
+	FILE *file;
+
+	snprintf(path, sizeof(path), "%s/%s",
+		 p_osm->subn.opt.dump_files_dir, file_name);
+
+	file = fopen(path, "w");
+	if (!file) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
+			"cannot create file \'%s\': %s\n",
+			path, strerror(errno));
+		return;
+	}
+
+	dump_qmap(file, map, func, cxt);
+
+	fclose(file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void print_report(osm_opensm_t *osm, FILE *file)
+{
+	fprintf(file, "\n==================================================="
+		"====================================================\n"
+		"Vendor      : Ty : #  : Sta : LID  : LMC : MTU  : LWA :"
+		" LSA : Port GUID        : Neighbor Port (Port #)\n");
+	dump_qmap(stdout, &osm->subn.node_guid_tbl, print_node_report, osm);
+}
+
+void osm_dump_mcast_routes(osm_opensm_t * osm)
+{
+	if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING))
+		/* multicast routes */
+		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
+				      &osm->subn.sw_guid_tbl,
+				      dump_mcast_routes, osm);
+}
+
+void osm_dump_all(osm_opensm_t * osm)
+{
+	if (osm_log_is_active(&osm->log, OSM_LOG_ROUTING)) {
+		/* unicast routes */
+		osm_dump_qmap_to_file(osm, "opensm-lid-matrix.dump",
+				      &osm->subn.sw_guid_tbl, dump_lid_matrix,
+				      osm);
+		osm_dump_qmap_to_file(osm, "opensm-lfts.dump",
+				      &osm->subn.sw_guid_tbl, dump_ucast_lfts,
+				      osm);
+		if (osm_log_is_active(&osm->log, OSM_LOG_DEBUG))
+			dump_qmap(stdout, &osm->subn.sw_guid_tbl,
+				  dump_ucast_path_distribution, osm);
+		osm_dump_qmap_to_file(osm, "opensm.fdbs",
+				      &osm->subn.sw_guid_tbl,
+				      dump_ucast_routes, osm);
+		/* multicast routes */
+		osm_dump_qmap_to_file(osm, "opensm.mcfdbs",
+				      &osm->subn.sw_guid_tbl,
+				      dump_mcast_routes, osm);
+	}
+	osm_dump_qmap_to_file(osm, "opensm-subnet.lst",
+			      &osm->subn.node_guid_tbl, dump_topology_node,
+			      osm);
+	if (osm_log_is_active(&osm->log, OSM_LOG_VERBOSE))
+		print_report(osm, stdout);
+}
diff --git a/opensm/osm_event_plugin.c b/opensm/osm_event_plugin.c
new file mode 100644
index 0000000..b0dc549
--- /dev/null
+++ b/opensm/osm_event_plugin.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 The Regents of the University of California.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/****h* OpenSM Event plugin interface
+* DESCRIPTION
+*       Database interface to record subnet events
+*
+*       Implementations of this object _MUST_ be thread safe.
+*
+* AUTHOR
+*	Ira Weiny, LLNL
+*
+*********/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <opensm/osm_event_plugin.h>
+#include <opensm/osm_opensm.h>
+
+#if defined(PATH_MAX)
+#define OSM_PATH_MAX	(PATH_MAX + 1)
+#elif defined (_POSIX_PATH_MAX)
+#define OSM_PATH_MAX	(_POSIX_PATH_MAX + 1)
+#else
+#define OSM_PATH_MAX	256
+#endif
+
+/**
+ * functions
+ */
+osm_epi_plugin_t *osm_epi_construct(osm_opensm_t *osm, char *plugin_name)
+{
+	char lib_name[OSM_PATH_MAX];
+	struct old_if { unsigned ver; } *old_impl;
+	osm_epi_plugin_t *rc = NULL;
+
+	if (!plugin_name || !*plugin_name)
+		return (NULL);
+
+	/* find the plugin */
+	snprintf(lib_name, OSM_PATH_MAX, "lib%s.so", plugin_name);
+
+	rc = malloc(sizeof(*rc));
+	if (!rc)
+		return (NULL);
+
+	rc->handle = dlopen(lib_name, RTLD_LAZY);
+	if (!rc->handle) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"Failed to open event plugin \"%s\" : \"%s\"\n",
+			lib_name, dlerror());
+		goto DLOPENFAIL;
+	}
+
+	rc->impl =
+	    (osm_event_plugin_t *) dlsym(rc->handle,
+					 OSM_EVENT_PLUGIN_IMPL_NAME);
+	if (!rc->impl) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"Failed to find \"%s\" symbol in \"%s\" : \"%s\"\n",
+			OSM_EVENT_PLUGIN_IMPL_NAME, lib_name, dlerror());
+		goto Exit;
+	}
+
+	/* check for old interface */
+	old_impl = (struct old_if *) rc->impl;
+	if (old_impl->ver == OSM_ORIG_EVENT_PLUGIN_INTERFACE_VER) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR, "Error loading plugin: "
+			"\'%s\' contains a depricated interface version %d\n"
+			"   Please recompile with the new interface.\n",
+			plugin_name, old_impl->ver);
+		goto Exit;
+	}
+
+	/* Check the version to make sure this module will work with us */
+	if (strcmp(rc->impl->osm_version, osm->osm_version)) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR, "Error loading plugin"
+			" \'%s\': OpenSM version mismatch - plugin was built"
+			" against %s version of OpenSM. Skip loading.\n",
+			plugin_name, rc->impl->osm_version);
+		goto Exit;
+	}
+
+	if (!rc->impl->create) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"Error loading plugin \'%s\': no create() method.\n",
+			plugin_name);
+		goto Exit;
+	}
+
+	rc->plugin_data = rc->impl->create(osm);
+
+	if (!rc->plugin_data)
+		goto Exit;
+
+	rc->plugin_name = strdup(plugin_name);
+	return (rc);
+
+Exit:
+	dlclose(rc->handle);
+DLOPENFAIL:
+	free(rc);
+	return (NULL);
+}
+
+void osm_epi_destroy(osm_epi_plugin_t * plugin)
+{
+	if (plugin) {
+		if (plugin->impl->delete)
+			plugin->impl->delete(plugin->plugin_data);
+		dlclose(plugin->handle);
+		free(plugin->plugin_name);
+		free(plugin);
+	}
+}
diff --git a/opensm/osm_helper.c b/opensm/osm_helper.c
new file mode 100644
index 0000000..0443987
--- /dev/null
+++ b/opensm/osm_helper.c
@@ -0,0 +1,2333 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of opensm helper functions.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_log.h>
+
+#define LINE_LENGTH 256
+
+#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+/* we use two tables - one for queries and one for responses */
+static const char *const __ib_sa_method_str[] = {
+	"RESERVED",		/* 0 */
+	"SubnAdmGet",		/* 1 */
+	"SubnAdmSet",		/* 2 */
+	"RESERVED",		/* 3 */
+	"RESERVED",		/* 4 */
+	"RESERVED",		/* 5 */
+	"SubnAdmReport",	/* 6 */
+	"RESERVED",		/* 7 */
+	"RESERVED",		/* 8 */
+	"RESERVED",		/* 9 */
+	"RESERVED",		/* A */
+	"RESERVED",		/* B */
+	"RESERVED",		/* C */
+	"RESERVED",		/* D */
+	"RESERVED",		/* E */
+	"RESERVED",		/* F */
+	"RESERVED",		/* 10 */
+	"RESERVED",		/* 11 */
+	"SubnAdmGetTable",	/* 12 */
+	"SubnAdmGetTraceTable",	/* 13 */
+	"SubnAdmGetMulti",	/* 14 */
+	"SubnAdmDelete",	/* 15 */
+	"UNKNOWN"		/* 16 */
+};
+
+static const char *const __ib_sa_resp_method_str[] = {
+	"RESERVED",		/* 80 */
+	"SubnAdmGetResp",	/* 81 */
+	"RESERVED (SetResp?)",	/* 82 */
+	"RESERVED",		/* 83 */
+	"RESERVED",		/* 84 */
+	"RESERVED",		/* 85 */
+	"SubnAdmReportResp",	/* 86 */
+	"RESERVED",		/* 87 */
+	"RESERVED",		/* 88 */
+	"RESERVED",		/* 89 */
+	"RESERVED",		/* 8A */
+	"RESERVED",		/* 8B */
+	"RESERVED",		/* 8C */
+	"RESERVED",		/* 8D */
+	"RESERVED",		/* 8E */
+	"RESERVED",		/* 8F */
+	"RESERVED",		/* 90 */
+	"RESERVED",		/* 91 */
+	"SubnAdmGetTableResp",	/* 92 */
+	"RESERVED",		/* 93 */
+	"SubnAdmGetMultiResp",	/* 94 */
+	"SubnAdmDeleteResp",	/* 95 */
+	"UNKNOWN"
+};
+
+#define OSM_SA_METHOD_STR_UNKNOWN_VAL 0x16
+
+static const char *const __ib_sm_method_str[] = {
+	"RESERVED0",		/* 0 */
+	"SubnGet",		/* 1 */
+	"SubnSet",		/* 2 */
+	"RESERVED3",		/* 3 */
+	"RESERVED4",		/* 4 */
+	"SubnTrap",		/* 5 */
+	"RESERVED6",		/* 6 */
+	"SubnTrapRepress",	/* 7 */
+	"RESERVED8",		/* 8 */
+	"RESERVED9",		/* 9 */
+	"RESERVEDA",		/* A */
+	"RESERVEDB",		/* B */
+	"RESERVEDC",		/* C */
+	"RESERVEDD",		/* D */
+	"RESERVEDE",		/* E */
+	"RESERVEDF",		/* F */
+	"RESERVED10",		/* 10 */
+	"SubnGetResp",		/* 11 */
+	"RESERVED12",		/* 12 */
+	"RESERVED13",		/* 13 */
+	"RESERVED14",		/* 14 */
+	"RESERVED15",		/* 15 */
+	"RESERVED16",		/* 16 */
+	"RESERVED17",		/* 17 */
+	"RESERVED18",		/* 18 */
+	"RESERVED19",		/* 19 */
+	"RESERVED1A",		/* 1A */
+	"RESERVED1B",		/* 1B */
+	"RESERVED1C",		/* 1C */
+	"RESERVED1D",		/* 1D */
+	"RESERVED1E",		/* 1E */
+	"RESERVED1F",		/* 1F */
+	"UNKNOWN"		/* 20 */
+};
+
+#define OSM_SM_METHOD_STR_UNKNOWN_VAL 0x21
+
+static const char *const __ib_sm_attr_str[] = {
+	"RESERVED",		/* 0 */
+	"ClassPortInfo",	/* 1 */
+	"Notice",		/* 2 */
+	"InformInfo",		/* 3 */
+	"RESERVED",		/* 4 */
+	"RESERVED",		/* 5 */
+	"RESERVED",		/* 6 */
+	"RESERVED",		/* 7 */
+	"RESERVED",		/* 8 */
+	"RESERVED",		/* 9 */
+	"RESERVED",		/* A */
+	"RESERVED",		/* B */
+	"RESERVED",		/* C */
+	"RESERVED",		/* D */
+	"RESERVED",		/* E */
+	"RESERVED",		/* F */
+	"NodeDescription",	/* 10 */
+	"NodeInfo",		/* 11 */
+	"SwitchInfo",		/* 12 */
+	"UNKNOWN",		/* 13 */
+	"GUIDInfo",		/* 14 */
+	"PortInfo",		/* 15 */
+	"P_KeyTable",		/* 16 */
+	"SLtoVLMappingTable",	/* 17 */
+	"VLArbitrationTable",	/* 18 */
+	"LinearForwardingTable",	/* 19 */
+	"RandomForwardingTable",	/* 1A */
+	"MulticastForwardingTable",	/* 1B */
+	"UNKNOWN",		/* 1C */
+	"UNKNOWN",		/* 1D */
+	"UNKNOWN",		/* 1E */
+	"UNKNOWN",		/* 1F */
+	"SMInfo",		/* 20 */
+	"UNKNOWN"		/* 21 - always highest value */
+};
+
+#define OSM_SM_ATTR_STR_UNKNOWN_VAL 0x21
+
+static const char *const __ib_sa_attr_str[] = {
+	"RESERVED",		/* 0 */
+	"ClassPortInfo",	/* 1 */
+	"Notice",		/* 2 */
+	"InformInfo",		/* 3 */
+	"RESERVED",		/* 4 */
+	"RESERVED",		/* 5 */
+	"RESERVED",		/* 6 */
+	"RESERVED",		/* 7 */
+	"RESERVED",		/* 8 */
+	"RESERVED",		/* 9 */
+	"RESERVED",		/* A */
+	"RESERVED",		/* B */
+	"RESERVED",		/* C */
+	"RESERVED",		/* D */
+	"RESERVED",		/* E */
+	"RESERVED",		/* F */
+	"RESERVED",		/* 10 */
+	"NodeRecord",		/* 11 */
+	"PortInfoRecord",	/* 12 */
+	"SLtoVLMappingTableRecord",	/* 13 */
+	"SwitchInfoRecord",	/* 14 */
+	"LinearForwardingTableRecord",	/* 15 */
+	"RandomForwardingTableRecord",	/* 16 */
+	"MulticastForwardingTableRecord",	/* 17 */
+	"SMInfoRecord",		/* 18 */
+	"RESERVED",		/* 19 */
+	"RandomForwardingTable",	/* 1A */
+	"MulticastForwardingTable",	/* 1B */
+	"UNKNOWN",		/* 1C */
+	"UNKNOWN",		/* 1D */
+	"UNKNOWN",		/* 1E */
+	"UNKNOWN",		/* 1F */
+	"LinkRecord",		/* 20 */
+	"UNKNOWN",		/* 21 */
+	"UNKNOWN",		/* 22 */
+	"UNKNOWN",		/* 23 */
+	"UNKNOWN",		/* 24 */
+	"UNKNOWN",		/* 25 */
+	"UNKNOWN",		/* 26 */
+	"UNKNOWN",		/* 27 */
+	"UNKNOWN",		/* 28 */
+	"UNKNOWN",		/* 29 */
+	"UNKNOWN",		/* 2A */
+	"UNKNOWN",		/* 2B */
+	"UNKNOWN",		/* 2C */
+	"UNKNOWN",		/* 2D */
+	"UNKNOWN",		/* 2E */
+	"UNKNOWN",		/* 2F */
+	"GuidInfoRecord",	/* 30 */
+	"ServiceRecord",	/* 31 */
+	"UNKNOWN",		/* 32 */
+	"P_KeyTableRecord",	/* 33 */
+	"UNKNOWN",		/* 34 */
+	"PathRecord",		/* 35 */
+	"VLArbitrationTableRecord",	/* 36 */
+	"UNKNOWN",		/* 37 */
+	"MCMemberRecord",	/* 38 */
+	"TraceRecord",		/* 39 */
+	"MultiPathRecord",	/* 3A */
+	"ServiceAssociationRecord",	/* 3B */
+	"UNKNOWN",		/* 3C */
+	"UNKNOWN",		/* 3D */
+	"UNKNOWN",		/* 3E */
+	"UNKNOWN",		/* 3F */
+	"UNKNOWN",		/* 40 */
+	"UNKNOWN",		/* 41 */
+	"UNKNOWN",		/* 42 */
+	"UNKNOWN",		/* 43 */
+	"UNKNOWN",		/* 44 */
+	"UNKNOWN",		/* 45 */
+	"UNKNOWN",		/* 46 */
+	"UNKNOWN",		/* 47 */
+	"UNKNOWN",		/* 48 */
+	"UNKNOWN",		/* 49 */
+	"UNKNOWN",		/* 4A */
+	"UNKNOWN",		/* 4B */
+	"UNKNOWN",		/* 4C */
+	"UNKNOWN",		/* 4D */
+	"UNKNOWN",		/* 4E */
+	"UNKNOWN",		/* 4F */
+	"UNKNOWN",		/* 50 */
+	"UNKNOWN",		/* 51 */
+	"UNKNOWN",		/* 52 */
+	"UNKNOWN",		/* 53 */
+	"UNKNOWN",		/* 54 */
+	"UNKNOWN",		/* 55 */
+	"UNKNOWN",		/* 56 */
+	"UNKNOWN",		/* 57 */
+	"UNKNOWN",		/* 58 */
+	"UNKNOWN",		/* 59 */
+	"UNKNOWN",		/* 5A */
+	"UNKNOWN",		/* 5B */
+	"UNKNOWN",		/* 5C */
+	"UNKNOWN",		/* 5D */
+	"UNKNOWN",		/* 5E */
+	"UNKNOWN",		/* 5F */
+	"UNKNOWN",		/* 60 */
+	"UNKNOWN",		/* 61 */
+	"UNKNOWN",		/* 62 */
+	"UNKNOWN",		/* 63 */
+	"UNKNOWN",		/* 64 */
+	"UNKNOWN",		/* 65 */
+	"UNKNOWN",		/* 66 */
+	"UNKNOWN",		/* 67 */
+	"UNKNOWN",		/* 68 */
+	"UNKNOWN",		/* 69 */
+	"UNKNOWN",		/* 6A */
+	"UNKNOWN",		/* 6B */
+	"UNKNOWN",		/* 6C */
+	"UNKNOWN",		/* 6D */
+	"UNKNOWN",		/* 6E */
+	"UNKNOWN",		/* 6F */
+	"UNKNOWN",		/* 70 */
+	"UNKNOWN",		/* 71 */
+	"UNKNOWN",		/* 72 */
+	"UNKNOWN",		/* 73 */
+	"UNKNOWN",		/* 74 */
+	"UNKNOWN",		/* 75 */
+	"UNKNOWN",		/* 76 */
+	"UNKNOWN",		/* 77 */
+	"UNKNOWN",		/* 78 */
+	"UNKNOWN",		/* 79 */
+	"UNKNOWN",		/* 7A */
+	"UNKNOWN",		/* 7B */
+	"UNKNOWN",		/* 7C */
+	"UNKNOWN",		/* 7D */
+	"UNKNOWN",		/* 7E */
+	"UNKNOWN",		/* 7F */
+	"UNKNOWN",		/* 80 */
+	"UNKNOWN",		/* 81 */
+	"UNKNOWN",		/* 82 */
+	"UNKNOWN",		/* 83 */
+	"UNKNOWN",		/* 84 */
+	"UNKNOWN",		/* 85 */
+	"UNKNOWN",		/* 86 */
+	"UNKNOWN",		/* 87 */
+	"UNKNOWN",		/* 88 */
+	"UNKNOWN",		/* 89 */
+	"UNKNOWN",		/* 8A */
+	"UNKNOWN",		/* 8B */
+	"UNKNOWN",		/* 8C */
+	"UNKNOWN",		/* 8D */
+	"UNKNOWN",		/* 8E */
+	"UNKNOWN",		/* 8F */
+	"UNKNOWN",		/* 90 */
+	"UNKNOWN",		/* 91 */
+	"UNKNOWN",		/* 92 */
+	"UNKNOWN",		/* 93 */
+	"UNKNOWN",		/* 94 */
+	"UNKNOWN",		/* 95 */
+	"UNKNOWN",		/* 96 */
+	"UNKNOWN",		/* 97 */
+	"UNKNOWN",		/* 98 */
+	"UNKNOWN",		/* 99 */
+	"UNKNOWN",		/* 9A */
+	"UNKNOWN",		/* 9B */
+	"UNKNOWN",		/* 9C */
+	"UNKNOWN",		/* 9D */
+	"UNKNOWN",		/* 9E */
+	"UNKNOWN",		/* 9F */
+	"UNKNOWN",		/* A0 */
+	"UNKNOWN",		/* A1 */
+	"UNKNOWN",		/* A2 */
+	"UNKNOWN",		/* A3 */
+	"UNKNOWN",		/* A4 */
+	"UNKNOWN",		/* A5 */
+	"UNKNOWN",		/* A6 */
+	"UNKNOWN",		/* A7 */
+	"UNKNOWN",		/* A8 */
+	"UNKNOWN",		/* A9 */
+	"UNKNOWN",		/* AA */
+	"UNKNOWN",		/* AB */
+	"UNKNOWN",		/* AC */
+	"UNKNOWN",		/* AD */
+	"UNKNOWN",		/* AE */
+	"UNKNOWN",		/* AF */
+	"UNKNOWN",		/* B0 */
+	"UNKNOWN",		/* B1 */
+	"UNKNOWN",		/* B2 */
+	"UNKNOWN",		/* B3 */
+	"UNKNOWN",		/* B4 */
+	"UNKNOWN",		/* B5 */
+	"UNKNOWN",		/* B6 */
+	"UNKNOWN",		/* B7 */
+	"UNKNOWN",		/* B8 */
+	"UNKNOWN",		/* B9 */
+	"UNKNOWN",		/* BA */
+	"UNKNOWN",		/* BB */
+	"UNKNOWN",		/* BC */
+	"UNKNOWN",		/* BD */
+	"UNKNOWN",		/* BE */
+	"UNKNOWN",		/* BF */
+	"UNKNOWN",		/* C0 */
+	"UNKNOWN",		/* C1 */
+	"UNKNOWN",		/* C2 */
+	"UNKNOWN",		/* C3 */
+	"UNKNOWN",		/* C4 */
+	"UNKNOWN",		/* C5 */
+	"UNKNOWN",		/* C6 */
+	"UNKNOWN",		/* C7 */
+	"UNKNOWN",		/* C8 */
+	"UNKNOWN",		/* C9 */
+	"UNKNOWN",		/* CA */
+	"UNKNOWN",		/* CB */
+	"UNKNOWN",		/* CC */
+	"UNKNOWN",		/* CD */
+	"UNKNOWN",		/* CE */
+	"UNKNOWN",		/* CF */
+	"UNKNOWN",		/* D0 */
+	"UNKNOWN",		/* D1 */
+	"UNKNOWN",		/* D2 */
+	"UNKNOWN",		/* D3 */
+	"UNKNOWN",		/* D4 */
+	"UNKNOWN",		/* D5 */
+	"UNKNOWN",		/* D6 */
+	"UNKNOWN",		/* D7 */
+	"UNKNOWN",		/* D8 */
+	"UNKNOWN",		/* D9 */
+	"UNKNOWN",		/* DA */
+	"UNKNOWN",		/* DB */
+	"UNKNOWN",		/* DC */
+	"UNKNOWN",		/* DD */
+	"UNKNOWN",		/* DE */
+	"UNKNOWN",		/* DF */
+	"UNKNOWN",		/* E0 */
+	"UNKNOWN",		/* E1 */
+	"UNKNOWN",		/* E2 */
+	"UNKNOWN",		/* E3 */
+	"UNKNOWN",		/* E4 */
+	"UNKNOWN",		/* E5 */
+	"UNKNOWN",		/* E6 */
+	"UNKNOWN",		/* E7 */
+	"UNKNOWN",		/* E8 */
+	"UNKNOWN",		/* E9 */
+	"UNKNOWN",		/* EA */
+	"UNKNOWN",		/* EB */
+	"UNKNOWN",		/* EC */
+	"UNKNOWN",		/* ED */
+	"UNKNOWN",		/* EE */
+	"UNKNOWN",		/* EF */
+	"UNKNOWN",		/* F0 */
+	"UNKNOWN",		/* F1 */
+	"UNKNOWN",		/* F2 */
+	"InformInfoRecord",	/* F3 */
+	"UNKNOWN"		/* F4 - always highest value */
+};
+
+#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0xF4
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_sa_method_str(IN uint8_t method)
+{
+	if (method & 0x80) {
+		method = method & 0x7f;
+		if (method >= OSM_SA_METHOD_STR_UNKNOWN_VAL)
+			method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+		/* it is a response - use the response table */
+		return (__ib_sa_resp_method_str[method]);
+	} else {
+		if (method >= OSM_SA_METHOD_STR_UNKNOWN_VAL)
+			method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+		return (__ib_sa_method_str[method]);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_sm_method_str(IN uint8_t method)
+{
+	if (method & 0x80)
+		method = (method & 0x0F) | 0x10;
+	if (method >= OSM_SM_METHOD_STR_UNKNOWN_VAL)
+		method = OSM_SM_METHOD_STR_UNKNOWN_VAL;
+	return (__ib_sm_method_str[method]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_sm_attr_str(IN ib_net16_t attr)
+{
+	uint16_t host_attr;
+	host_attr = cl_ntoh16(attr);
+
+	if (host_attr >= OSM_SM_ATTR_STR_UNKNOWN_VAL)
+		host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL;
+
+	return (__ib_sm_attr_str[host_attr]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_sa_attr_str(IN ib_net16_t attr)
+{
+	uint16_t host_attr;
+	host_attr = cl_ntoh16(attr);
+
+	if (host_attr >= OSM_SA_ATTR_STR_UNKNOWN_VAL)
+		host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL;
+
+	return (__ib_sa_attr_str[host_attr]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_trap_str(ib_net16_t trap_num)
+{
+	switch(cl_ntoh16(trap_num))
+	{
+		case 64:
+			return "GID in service";
+		case 65:
+			return "GID out of service";
+		case 66:
+			return "New mcast group created";
+		case 67:
+			return "Mcast group deleted";
+		case 68:
+			return "UnPath, Path no longer valid";
+		case 69:
+			return "RePath, Path recomputed";
+		case 128:
+			return "Link state change";
+		case 129:
+			return "Local Link integrity threshold reached";
+		case 130:
+			return "Excessive Buffer Overrun Threshold reached";
+		case 131:
+			return "Flow Control Update watchdog timer expired";
+		case 144:
+			return "CapabilityMask, NodeDescription, Link [Width|Speed] Enabled changed";
+		case 145:
+			return "System Image GUID changed";
+		case 256:
+			return "Bad M_Key";
+		case 257:
+			return "Bad P_Key";
+		case 258:
+			return "Bad Q_Key";
+		case 259:
+			return "Bad P_Key (switch external port)";
+		default:
+			break;
+	}
+	return "Unknown";
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+dbg_do_line(IN char **pp_local,
+	    IN const uint32_t buf_size,
+	    IN const char *const p_prefix_str,
+	    IN const char *const p_new_str, IN uint32_t * const p_total_len)
+{
+	char line[LINE_LENGTH];
+	uint32_t len;
+
+	sprintf(line, "%s%s", p_prefix_str, p_new_str);
+	len = (uint32_t) strlen(line);
+	*p_total_len += len;
+	if (*p_total_len + sizeof('\0') > buf_size)
+		return (IB_INSUFFICIENT_MEMORY);
+
+	strcpy(*pp_local, line);
+	*pp_local += len;
+	return (IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+dbg_get_capabilities_str(IN char *p_buf,
+			 IN const uint32_t buf_size,
+			 IN const char *const p_prefix_str,
+			 IN const ib_port_info_t * const p_pi)
+{
+	uint32_t total_len = 0;
+	char *p_local = p_buf;
+
+	strcpy(p_local, "Capability Mask:\n");
+	p_local += strlen(p_local);
+
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV0) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV0\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_IS_SM\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_NOTICE\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_TRAP\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_IPD) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_IPD\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_AUTO_MIG\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_SL_MAP\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_NV_MKEY\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_NV_PKEY\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_LED_INFO\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_SM_DISAB) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_SM_DISAB\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_SYS_IMG_GUID\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV13) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV13\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV14) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV14\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV15) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV15\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_COM_MGT\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_SNMP\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_REINIT) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_REINIT\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_DEV_MGT\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_VEND_CLS\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_DR_NTC\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_CAP_NTC\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_BM) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_BM\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_LINK_RT_LATENCY\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_CLIENT_REREG\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV28) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV28\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV29) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV29\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV30) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV30\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+	if (p_pi->capability_mask & IB_PORT_CAP_RESV31) {
+		if (dbg_do_line(&p_local, buf_size, p_prefix_str,
+				"IB_PORT_CAP_RESV31\n",
+				&total_len) != IB_SUCCESS)
+			return;
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE];
+
+		osm_log(p_log, log_level,
+			"PortInfo dump:\n"
+			"\t\t\t\tport number.............%u\n"
+			"\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+			"\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+			"\t\t\t\tbase_lid................%u\n"
+			"\t\t\t\tmaster_sm_base_lid......%u\n"
+			"\t\t\t\tcapability_mask.........0x%X\n"
+			"\t\t\t\tdiag_code...............0x%X\n"
+			"\t\t\t\tm_key_lease_period......0x%X\n"
+			"\t\t\t\tlocal_port_num..........%u\n"
+			"\t\t\t\tlink_width_enabled......0x%X\n"
+			"\t\t\t\tlink_width_supported....0x%X\n"
+			"\t\t\t\tlink_width_active.......0x%X\n"
+			"\t\t\t\tlink_speed_supported....0x%X\n"
+			"\t\t\t\tport_state..............%s\n"
+			"\t\t\t\tstate_info2.............0x%X\n"
+			"\t\t\t\tm_key_protect_bits......0x%X\n"
+			"\t\t\t\tlmc.....................0x%X\n"
+			"\t\t\t\tlink_speed..............0x%X\n"
+			"\t\t\t\tmtu_smsl................0x%X\n"
+			"\t\t\t\tvl_cap_init_type........0x%X\n"
+			"\t\t\t\tvl_high_limit...........0x%X\n"
+			"\t\t\t\tvl_arb_high_cap.........0x%X\n"
+			"\t\t\t\tvl_arb_low_cap..........0x%X\n"
+			"\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+			"\t\t\t\tvl_stall_life...........0x%X\n"
+			"\t\t\t\tvl_enforce..............0x%X\n"
+			"\t\t\t\tm_key_violations........0x%X\n"
+			"\t\t\t\tp_key_violations........0x%X\n"
+			"\t\t\t\tq_key_violations........0x%X\n"
+			"\t\t\t\tguid_cap................0x%X\n"
+			"\t\t\t\tclient_reregister.......0x%X\n"
+			"\t\t\t\tsubnet_timeout..........0x%X\n"
+			"\t\t\t\tresp_time_value.........0x%X\n"
+			"\t\t\t\terror_threshold.........0x%X\n",
+			port_num,
+			cl_ntoh64(node_guid),
+			cl_ntoh64(port_guid),
+			cl_ntoh64(p_pi->m_key),
+			cl_ntoh64(p_pi->subnet_prefix),
+			cl_ntoh16(p_pi->base_lid),
+			cl_ntoh16(p_pi->master_sm_base_lid),
+			cl_ntoh32(p_pi->capability_mask),
+			cl_ntoh16(p_pi->diag_code),
+			cl_ntoh16(p_pi->m_key_lease_period),
+			p_pi->local_port_num,
+			p_pi->link_width_enabled,
+			p_pi->link_width_supported,
+			p_pi->link_width_active,
+			ib_port_info_get_link_speed_sup(p_pi),
+			ib_get_port_state_str(ib_port_info_get_port_state
+					      (p_pi)), p_pi->state_info2,
+			ib_port_info_get_mpb(p_pi), ib_port_info_get_lmc(p_pi),
+			p_pi->link_speed, p_pi->mtu_smsl, p_pi->vl_cap,
+			p_pi->vl_high_limit, p_pi->vl_arb_high_cap,
+			p_pi->vl_arb_low_cap, p_pi->mtu_cap,
+			p_pi->vl_stall_life, p_pi->vl_enforce,
+			cl_ntoh16(p_pi->m_key_violations),
+			cl_ntoh16(p_pi->p_key_violations),
+			cl_ntoh16(p_pi->q_key_violations), p_pi->guid_cap,
+			ib_port_info_get_client_rereg(p_pi),
+			ib_port_info_get_timeout(p_pi), p_pi->resp_time_value,
+			p_pi->error_threshold);
+
+		/*  show the capabilities mask */
+		if (p_pi->capability_mask) {
+			dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t",
+						 p_pi);
+			osm_log(p_log, log_level, "%s", buf);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_portinfo_record(IN osm_log_t * const p_log,
+			 IN const ib_portinfo_record_t * const p_pir,
+			 IN const osm_log_level_t log_level)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE];
+		const ib_port_info_t *const p_pi = &p_pir->port_info;
+
+		osm_log(p_log, log_level,
+			"PortInfo Record dump:\n"
+			"\t\t\t\tRID\n"
+			"\t\t\t\tEndPortLid..............%u\n"
+			"\t\t\t\tPortNum.................0x%X\n"
+			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tPortInfo dump:\n"
+			"\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+			"\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+			"\t\t\t\tbase_lid................%u\n"
+			"\t\t\t\tmaster_sm_base_lid......%u\n"
+			"\t\t\t\tcapability_mask.........0x%X\n"
+			"\t\t\t\tdiag_code...............0x%X\n"
+			"\t\t\t\tm_key_lease_period......0x%X\n"
+			"\t\t\t\tlocal_port_num..........%u\n"
+			"\t\t\t\tlink_width_enabled......0x%X\n"
+			"\t\t\t\tlink_width_supported....0x%X\n"
+			"\t\t\t\tlink_width_active.......0x%X\n"
+			"\t\t\t\tlink_speed_supported....0x%X\n"
+			"\t\t\t\tport_state..............%s\n"
+			"\t\t\t\tstate_info2.............0x%X\n"
+			"\t\t\t\tm_key_protect_bits......0x%X\n"
+			"\t\t\t\tlmc.....................0x%X\n"
+			"\t\t\t\tlink_speed..............0x%X\n"
+			"\t\t\t\tmtu_smsl................0x%X\n"
+			"\t\t\t\tvl_cap_init_type........0x%X\n"
+			"\t\t\t\tvl_high_limit...........0x%X\n"
+			"\t\t\t\tvl_arb_high_cap.........0x%X\n"
+			"\t\t\t\tvl_arb_low_cap..........0x%X\n"
+			"\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+			"\t\t\t\tvl_stall_life...........0x%X\n"
+			"\t\t\t\tvl_enforce..............0x%X\n"
+			"\t\t\t\tm_key_violations........0x%X\n"
+			"\t\t\t\tp_key_violations........0x%X\n"
+			"\t\t\t\tq_key_violations........0x%X\n"
+			"\t\t\t\tguid_cap................0x%X\n"
+			"\t\t\t\tsubnet_timeout..........0x%X\n"
+			"\t\t\t\tresp_time_value.........0x%X\n"
+			"\t\t\t\terror_threshold.........0x%X\n",
+			cl_ntoh16(p_pir->lid),
+			p_pir->port_num,
+			p_pir->resv,
+			cl_ntoh64(p_pi->m_key),
+			cl_ntoh64(p_pi->subnet_prefix),
+			cl_ntoh16(p_pi->base_lid),
+			cl_ntoh16(p_pi->master_sm_base_lid),
+			cl_ntoh32(p_pi->capability_mask),
+			cl_ntoh16(p_pi->diag_code),
+			cl_ntoh16(p_pi->m_key_lease_period),
+			p_pi->local_port_num,
+			p_pi->link_width_enabled,
+			p_pi->link_width_supported,
+			p_pi->link_width_active,
+			ib_port_info_get_link_speed_sup(p_pi),
+			ib_get_port_state_str(ib_port_info_get_port_state
+					      (p_pi)), p_pi->state_info2,
+			ib_port_info_get_mpb(p_pi), ib_port_info_get_lmc(p_pi),
+			p_pi->link_speed, p_pi->mtu_smsl, p_pi->vl_cap,
+			p_pi->vl_high_limit, p_pi->vl_arb_high_cap,
+			p_pi->vl_arb_low_cap, p_pi->mtu_cap,
+			p_pi->vl_stall_life, p_pi->vl_enforce,
+			cl_ntoh16(p_pi->m_key_violations),
+			cl_ntoh16(p_pi->p_key_violations),
+			cl_ntoh16(p_pi->q_key_violations), p_pi->guid_cap,
+			ib_port_info_get_timeout(p_pi), p_pi->resp_time_value,
+			p_pi->error_threshold);
+
+		/*  show the capabilities mask */
+		if (p_pi->capability_mask) {
+			dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t",
+						 p_pi);
+			osm_log(p_log, log_level, "%s", buf);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		const ib_guid_info_t *const p_gi = &p_gir->guid_info;
+
+		osm_log(p_log, log_level,
+			"GUIDInfo Record dump:\n"
+			"\t\t\t\tRID\n"
+			"\t\t\t\tLid.....................%u\n"
+			"\t\t\t\tBlockNum................0x%X\n"
+			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tGUIDInfo dump:\n"
+			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tGUID 0..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 1..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 2..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 3..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 4..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 5..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 6..................0x%016" PRIx64 "\n"
+			"\t\t\t\tGUID 7..................0x%016" PRIx64 "\n",
+			cl_ntoh16(p_gir->lid),
+			p_gir->block_num,
+			p_gir->resv,
+			cl_ntoh32(p_gir->reserved),
+			cl_ntoh64(p_gi->guid[0]),
+			cl_ntoh64(p_gi->guid[1]),
+			cl_ntoh64(p_gi->guid[2]),
+			cl_ntoh64(p_gi->guid[3]),
+			cl_ntoh64(p_gi->guid[4]),
+			cl_ntoh64(p_gi->guid[5]),
+			cl_ntoh64(p_gi->guid[6]), cl_ntoh64(p_gi->guid[7]));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, log_level,
+			"NodeInfo dump:\n"
+			"\t\t\t\tbase_version............0x%X\n"
+			"\t\t\t\tclass_version...........0x%X\n"
+			"\t\t\t\tnode_type...............%s\n"
+			"\t\t\t\tnum_ports...............%u\n"
+			"\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+			"\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tpartition_cap...........0x%X\n"
+			"\t\t\t\tdevice_id...............0x%X\n"
+			"\t\t\t\trevision................0x%X\n"
+			"\t\t\t\tport_num................%u\n"
+			"\t\t\t\tvendor_id...............0x%X\n",
+			p_ni->base_version,
+			p_ni->class_version,
+			ib_get_node_type_str(p_ni->node_type),
+			p_ni->num_ports,
+			cl_ntoh64(p_ni->sys_guid),
+			cl_ntoh64(p_ni->node_guid),
+			cl_ntoh64(p_ni->port_guid),
+			cl_ntoh16(p_ni->partition_cap),
+			cl_ntoh16(p_ni->device_id),
+			cl_ntoh32(p_ni->revision),
+			ib_node_info_get_local_port_num(p_ni),
+			cl_ntoh32(ib_node_info_get_vendor_id(p_ni)));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_node_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char desc[sizeof(p_nr->node_desc.description) + 1];
+		const ib_node_info_t *const p_ni = &p_nr->node_info;
+
+		memcpy(desc, p_nr->node_desc.description,
+		       sizeof(p_nr->node_desc.description));
+		desc[sizeof(desc) - 1] = '\0';
+		osm_log(p_log, log_level,
+			"Node Record dump:\n"
+			"\t\t\t\tRID\n"
+			"\t\t\t\tLid.....................%u\n"
+			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tNodeInfo dump:\n"
+			"\t\t\t\tbase_version............0x%X\n"
+			"\t\t\t\tclass_version...........0x%X\n"
+			"\t\t\t\tnode_type...............%s\n"
+			"\t\t\t\tnum_ports...............%u\n"
+			"\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+			"\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+			"\t\t\t\tpartition_cap...........0x%X\n"
+			"\t\t\t\tdevice_id...............0x%X\n"
+			"\t\t\t\trevision................0x%X\n"
+			"\t\t\t\tport_num................%u\n"
+			"\t\t\t\tvendor_id...............0x%X\n"
+			"\t\t\t\tNodeDescription\n"
+			"\t\t\t\t%s\n",
+			cl_ntoh16(p_nr->lid),
+			cl_ntoh16(p_nr->resv),
+			p_ni->base_version,
+			p_ni->class_version,
+			ib_get_node_type_str(p_ni->node_type),
+			p_ni->num_ports,
+			cl_ntoh64(p_ni->sys_guid),
+			cl_ntoh64(p_ni->node_guid),
+			cl_ntoh64(p_ni->port_guid),
+			cl_ntoh16(p_ni->partition_cap),
+			cl_ntoh16(p_ni->device_id),
+			cl_ntoh32(p_ni->revision),
+			ib_node_info_get_local_port_num(p_ni),
+			cl_ntoh32(ib_node_info_get_vendor_id(p_ni)), desc);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, log_level,
+			"PathRecord dump:\n"
+			"\t\t\t\tservice_id..............0x%016" PRIx64 "\n"
+			"\t\t\t\tdgid....................0x%016" PRIx64 " : "
+			"0x%016" PRIx64 "\n"
+			"\t\t\t\tsgid....................0x%016" PRIx64 " : "
+			"0x%016" PRIx64 "\n"
+			"\t\t\t\tdlid....................%u\n"
+			"\t\t\t\tslid....................%u\n"
+			"\t\t\t\thop_flow_raw............0x%X\n"
+			"\t\t\t\ttclass..................0x%X\n"
+			"\t\t\t\tnum_path_revers.........0x%X\n"
+			"\t\t\t\tpkey....................0x%X\n"
+			"\t\t\t\tqos_class...............0x%X\n"
+			"\t\t\t\tsl......................0x%X\n"
+			"\t\t\t\tmtu.....................0x%X\n"
+			"\t\t\t\trate....................0x%X\n"
+			"\t\t\t\tpkt_life................0x%X\n"
+			"\t\t\t\tpreference..............0x%X\n"
+			"\t\t\t\tresv2...................0x%X\n"
+			"\t\t\t\tresv3...................0x%X\n",
+			cl_ntoh64(p_pr->service_id),
+			cl_ntoh64(p_pr->dgid.unicast.prefix),
+			cl_ntoh64(p_pr->dgid.unicast.interface_id),
+			cl_ntoh64(p_pr->sgid.unicast.prefix),
+			cl_ntoh64(p_pr->sgid.unicast.interface_id),
+			cl_ntoh16(p_pr->dlid),
+			cl_ntoh16(p_pr->slid),
+			cl_ntoh32(p_pr->hop_flow_raw),
+			p_pr->tclass,
+			p_pr->num_path,
+			cl_ntoh16(p_pr->pkey),
+			ib_path_rec_qos_class(p_pr),
+			ib_path_rec_sl(p_pr),
+			p_pr->mtu,
+			p_pr->rate,
+			p_pr->pkt_life,
+			p_pr->preference,
+			*(uint32_t *) & p_pr->resv2,
+			*((uint16_t *) & p_pr->resv2 + 2));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf_line[1024];
+		ib_gid_t const *p_gid = p_mpr->gids;
+		int i, n = 0;
+
+		if (p_mpr->sgid_count) {
+			for (i = 0; i < p_mpr->sgid_count; i++) {
+				n += sprintf(buf_line + n,
+					     "\t\t\t\tsgid%02d.................."
+					     "0x%016" PRIx64 " : 0x%016" PRIx64
+					     "\n", i + 1,
+					     cl_ntoh64(p_gid->unicast.prefix),
+					     cl_ntoh64(p_gid->unicast.
+						       interface_id));
+				p_gid++;
+			}
+		}
+		if (p_mpr->dgid_count) {
+			for (i = 0; i < p_mpr->dgid_count; i++) {
+				n += sprintf(buf_line + n,
+					     "\t\t\t\tdgid%02d.................."
+					     "0x%016" PRIx64 " : 0x%016" PRIx64
+					     "\n", i + 1,
+					     cl_ntoh64(p_gid->unicast.prefix),
+					     cl_ntoh64(p_gid->unicast.
+						       interface_id));
+				p_gid++;
+			}
+		}
+		osm_log(p_log, log_level,
+			"MultiPath Record dump:\n"
+			"\t\t\t\thop_flow_raw............0x%X\n"
+			"\t\t\t\ttclass..................0x%X\n"
+			"\t\t\t\tnum_path_revers.........0x%X\n"
+			"\t\t\t\tpkey....................0x%X\n"
+			"\t\t\t\tqos_class...............0x%X\n"
+			"\t\t\t\tsl......................0x%X\n"
+			"\t\t\t\tmtu.....................0x%X\n"
+			"\t\t\t\trate....................0x%X\n"
+			"\t\t\t\tpkt_life................0x%X\n"
+			"\t\t\t\tindependence............0x%X\n"
+			"\t\t\t\tsgid_count..............0x%X\n"
+			"\t\t\t\tdgid_count..............0x%X\n"
+			"\t\t\t\tservice_id..............0x%016" PRIx64 "\n"
+			"%s\n",
+			cl_ntoh32(p_mpr->hop_flow_raw),
+			p_mpr->tclass,
+			p_mpr->num_path,
+			cl_ntoh16(p_mpr->pkey),
+			ib_multipath_rec_qos_class(p_mpr),
+			ib_multipath_rec_sl(p_mpr),
+			p_mpr->mtu,
+			p_mpr->rate,
+			p_mpr->pkt_life,
+			p_mpr->independence,
+			p_mpr->sgid_count, p_mpr->dgid_count,
+			cl_ntoh64(ib_multipath_rec_service_id(p_mpr)),
+			buf_line);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		char gid_str2[INET6_ADDRSTRLEN];
+		osm_log(p_log, log_level,
+			"MCMember Record dump:\n"
+			"\t\t\t\tMGID....................%s\n"
+			"\t\t\t\tPortGid.................%s\n"
+			"\t\t\t\tqkey....................0x%X\n"
+			"\t\t\t\tmlid....................0x%X\n"
+			"\t\t\t\tmtu.....................0x%X\n"
+			"\t\t\t\tTClass..................0x%X\n"
+			"\t\t\t\tpkey....................0x%X\n"
+			"\t\t\t\trate....................0x%X\n"
+			"\t\t\t\tpkt_life................0x%X\n"
+			"\t\t\t\tSLFlowLabelHopLimit.....0x%X\n"
+			"\t\t\t\tScopeState..............0x%X\n"
+			"\t\t\t\tProxyJoin...............0x%X\n",
+			inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,
+				sizeof gid_str),
+			inet_ntop(AF_INET6, p_mcmr->port_gid.raw, gid_str2,
+				sizeof gid_str2),
+			cl_ntoh32(p_mcmr->qkey),
+			cl_ntoh16(p_mcmr->mlid),
+			p_mcmr->mtu,
+			p_mcmr->tclass,
+			cl_ntoh16(p_mcmr->pkey),
+			p_mcmr->rate,
+			p_mcmr->pkt_life,
+			cl_ntoh32(p_mcmr->sl_flow_hop),
+			p_mcmr->scope_state, p_mcmr->proxy_join);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		char buf_service_key[35];
+		char buf_service_name[65];
+
+		sprintf(buf_service_key,
+			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+			p_sr->service_key[0],
+			p_sr->service_key[1],
+			p_sr->service_key[2],
+			p_sr->service_key[3],
+			p_sr->service_key[4],
+			p_sr->service_key[5],
+			p_sr->service_key[6],
+			p_sr->service_key[7],
+			p_sr->service_key[8],
+			p_sr->service_key[9],
+			p_sr->service_key[10],
+			p_sr->service_key[11],
+			p_sr->service_key[12],
+			p_sr->service_key[13],
+			p_sr->service_key[14], p_sr->service_key[15]);
+		strncpy(buf_service_name, (char *)p_sr->service_name, 64);
+		buf_service_name[64] = '\0';
+
+		osm_log(p_log, log_level,
+			"Service Record dump:\n"
+			"\t\t\t\tServiceID...............0x%016" PRIx64 "\n"
+			"\t\t\t\tServiceGID..............%s\n"
+			"\t\t\t\tServiceP_Key............0x%X\n"
+			"\t\t\t\tServiceLease............0x%X\n"
+			"\t\t\t\tServiceKey..............%s\n"
+			"\t\t\t\tServiceName.............%s\n"
+			"\t\t\t\tServiceData8.1..........0x%X\n"
+			"\t\t\t\tServiceData8.2..........0x%X\n"
+			"\t\t\t\tServiceData8.3..........0x%X\n"
+			"\t\t\t\tServiceData8.4..........0x%X\n"
+			"\t\t\t\tServiceData8.5..........0x%X\n"
+			"\t\t\t\tServiceData8.6..........0x%X\n"
+			"\t\t\t\tServiceData8.7..........0x%X\n"
+			"\t\t\t\tServiceData8.8..........0x%X\n"
+			"\t\t\t\tServiceData8.9..........0x%X\n"
+			"\t\t\t\tServiceData8.10.........0x%X\n"
+			"\t\t\t\tServiceData8.11.........0x%X\n"
+			"\t\t\t\tServiceData8.12.........0x%X\n"
+			"\t\t\t\tServiceData8.13.........0x%X\n"
+			"\t\t\t\tServiceData8.14.........0x%X\n"
+			"\t\t\t\tServiceData8.15.........0x%X\n"
+			"\t\t\t\tServiceData8.16.........0x%X\n"
+			"\t\t\t\tServiceData16.1.........0x%X\n"
+			"\t\t\t\tServiceData16.2.........0x%X\n"
+			"\t\t\t\tServiceData16.3.........0x%X\n"
+			"\t\t\t\tServiceData16.4.........0x%X\n"
+			"\t\t\t\tServiceData16.5.........0x%X\n"
+			"\t\t\t\tServiceData16.6.........0x%X\n"
+			"\t\t\t\tServiceData16.7.........0x%X\n"
+			"\t\t\t\tServiceData16.8.........0x%X\n"
+			"\t\t\t\tServiceData32.1.........0x%X\n"
+			"\t\t\t\tServiceData32.2.........0x%X\n"
+			"\t\t\t\tServiceData32.3.........0x%X\n"
+			"\t\t\t\tServiceData32.4.........0x%X\n"
+			"\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n"
+			"\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\n",
+			cl_ntoh64(p_sr->service_id),
+			inet_ntop(AF_INET6, p_sr->service_gid.raw, gid_str,
+				sizeof gid_str),
+			cl_ntoh16(p_sr->service_pkey),
+			cl_ntoh32(p_sr->service_lease),
+			buf_service_key,
+			buf_service_name,
+			p_sr->service_data8[0], p_sr->service_data8[1],
+			p_sr->service_data8[2], p_sr->service_data8[3],
+			p_sr->service_data8[4], p_sr->service_data8[5],
+			p_sr->service_data8[6], p_sr->service_data8[7],
+			p_sr->service_data8[8], p_sr->service_data8[9],
+			p_sr->service_data8[10], p_sr->service_data8[11],
+			p_sr->service_data8[12], p_sr->service_data8[13],
+			p_sr->service_data8[14], p_sr->service_data8[15],
+			cl_ntoh16(p_sr->service_data16[0]),
+			cl_ntoh16(p_sr->service_data16[1]),
+			cl_ntoh16(p_sr->service_data16[2]),
+			cl_ntoh16(p_sr->service_data16[3]),
+			cl_ntoh16(p_sr->service_data16[4]),
+			cl_ntoh16(p_sr->service_data16[5]),
+			cl_ntoh16(p_sr->service_data16[6]),
+			cl_ntoh16(p_sr->service_data16[7]),
+			cl_ntoh32(p_sr->service_data32[0]),
+			cl_ntoh32(p_sr->service_data32[1]),
+			cl_ntoh32(p_sr->service_data32[2]),
+			cl_ntoh32(p_sr->service_data32[3]),
+			cl_ntoh64(p_sr->service_data64[0]),
+			cl_ntoh64(p_sr->service_data64[1]));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		uint32_t qpn;
+		uint8_t resp_time_val;
+
+		ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.
+						 qpn_resp_time_val, &qpn,
+						 &resp_time_val);
+		if (p_ii->is_generic) {
+			osm_log(p_log, log_level,
+				"InformInfo dump:\n"
+				"\t\t\t\tgid.....................0x%016" PRIx64
+				" : 0x%016" PRIx64 "\n"
+				"\t\t\t\tlid_range_begin.........%u\n"
+				"\t\t\t\tlid_range_end...........%u\n"
+				"\t\t\t\tis_generic..............0x%X\n"
+				"\t\t\t\tsubscribe...............0x%X\n"
+				"\t\t\t\ttrap_type...............0x%X\n"
+				"\t\t\t\ttrap_num................%u\n"
+				"\t\t\t\tqpn.....................0x%06X\n"
+				"\t\t\t\tresp_time_val...........0x%X\n"
+				"\t\t\t\tnode_type...............0x%06X\n" "",
+				cl_ntoh64(p_ii->gid.unicast.prefix),
+				cl_ntoh64(p_ii->gid.unicast.interface_id),
+				cl_ntoh16(p_ii->lid_range_begin),
+				cl_ntoh16(p_ii->lid_range_end),
+				p_ii->is_generic, p_ii->subscribe,
+				cl_ntoh16(p_ii->trap_type),
+				cl_ntoh16(p_ii->g_or_v.generic.trap_num),
+				cl_ntoh32(qpn), resp_time_val,
+				cl_ntoh32(ib_inform_info_get_prod_type(p_ii)));
+		} else {
+			osm_log(p_log, log_level,
+				"InformInfo dump:\n"
+				"\t\t\t\tgid.....................0x%016" PRIx64
+				" : 0x%016" PRIx64 "\n"
+				"\t\t\t\tlid_range_begin.........%u\n"
+				"\t\t\t\tlid_range_end...........%u\n"
+				"\t\t\t\tis_generic..............0x%X\n"
+				"\t\t\t\tsubscribe...............0x%X\n"
+				"\t\t\t\ttrap_type...............0x%X\n"
+				"\t\t\t\tdev_id..................0x%X\n"
+				"\t\t\t\tqpn.....................0x%06X\n"
+				"\t\t\t\tresp_time_val...........0x%X\n"
+				"\t\t\t\tvendor_id...............0x%06X\n" "",
+				cl_ntoh64(p_ii->gid.unicast.prefix),
+				cl_ntoh64(p_ii->gid.unicast.interface_id),
+				cl_ntoh16(p_ii->lid_range_begin),
+				cl_ntoh16(p_ii->lid_range_end),
+				p_ii->is_generic, p_ii->subscribe,
+				cl_ntoh16(p_ii->trap_type),
+				cl_ntoh16(p_ii->g_or_v.vend.dev_id),
+				cl_ntoh32(qpn), resp_time_val,
+				cl_ntoh32(ib_inform_info_get_prod_type(p_ii)));
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_inform_info_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		char gid_str2[INET6_ADDRSTRLEN];
+		uint32_t qpn;
+		uint8_t resp_time_val;
+
+		ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.
+						 generic.qpn_resp_time_val,
+						 &qpn, &resp_time_val);
+		if (p_iir->inform_info.is_generic) {
+			osm_log(p_log, log_level,
+				"InformInfo Record dump:\n"
+				"\t\t\t\tRID\n"
+				"\t\t\t\tSubscriberGID...........%s\n"
+				"\t\t\t\tSubscriberEnum..........0x%X\n"
+				"\t\t\t\tInformInfo dump:\n"
+				"\t\t\t\tgid.....................%s\n"
+				"\t\t\t\tlid_range_begin.........%u\n"
+				"\t\t\t\tlid_range_end...........%u\n"
+				"\t\t\t\tis_generic..............0x%X\n"
+				"\t\t\t\tsubscribe...............0x%X\n"
+				"\t\t\t\ttrap_type...............0x%X\n"
+				"\t\t\t\ttrap_num................%u\n"
+				"\t\t\t\tqpn.....................0x%06X\n"
+				"\t\t\t\tresp_time_val...........0x%X\n"
+				"\t\t\t\tnode_type...............0x%06X\n" "",
+				inet_ntop(AF_INET6, p_iir->subscriber_gid.raw,
+					gid_str, sizeof gid_str),
+				cl_ntoh16(p_iir->subscriber_enum),
+				inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
+					gid_str2, sizeof gid_str2),
+				cl_ntoh16(p_iir->inform_info.lid_range_begin),
+				cl_ntoh16(p_iir->inform_info.lid_range_end),
+				p_iir->inform_info.is_generic,
+				p_iir->inform_info.subscribe,
+				cl_ntoh16(p_iir->inform_info.trap_type),
+				cl_ntoh16(p_iir->inform_info.g_or_v.generic.
+					  trap_num), cl_ntoh32(qpn),
+				resp_time_val,
+				cl_ntoh32(ib_inform_info_get_prod_type
+					  (&p_iir->inform_info)));
+		} else {
+			osm_log(p_log, log_level,
+				"InformInfo Record dump:\n"
+				"\t\t\t\tRID\n"
+				"\t\t\t\tSubscriberGID...........%s\n"
+				"\t\t\t\tSubscriberEnum..........0x%X\n"
+				"\t\t\t\tInformInfo dump:\n"
+				"\t\t\t\tgid.....................%s\n"
+				"\t\t\t\tlid_range_begin.........%u\n"
+				"\t\t\t\tlid_range_end...........%u\n"
+				"\t\t\t\tis_generic..............0x%X\n"
+				"\t\t\t\tsubscribe...............0x%X\n"
+				"\t\t\t\ttrap_type...............0x%X\n"
+				"\t\t\t\tdev_id..................0x%X\n"
+				"\t\t\t\tqpn.....................0x%06X\n"
+				"\t\t\t\tresp_time_val...........0x%X\n"
+				"\t\t\t\tvendor_id...............0x%06X\n" "",
+				inet_ntop(AF_INET6, p_iir->subscriber_gid.raw,
+					gid_str, sizeof gid_str),
+				cl_ntoh16(p_iir->subscriber_enum),
+				inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
+					gid_str2, sizeof gid_str2),
+				cl_ntoh16(p_iir->inform_info.lid_range_begin),
+				cl_ntoh16(p_iir->inform_info.lid_range_end),
+				p_iir->inform_info.is_generic,
+				p_iir->inform_info.subscribe,
+				cl_ntoh16(p_iir->inform_info.trap_type),
+				cl_ntoh16(p_iir->inform_info.g_or_v.vend.
+					  dev_id), cl_ntoh32(qpn),
+				resp_time_val,
+				cl_ntoh32(ib_inform_info_get_prod_type
+					  (&p_iir->inform_info)));
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, log_level,
+			"Link Record dump:\n"
+			"\t\t\t\tfrom_lid................%u\n"
+			"\t\t\t\tfrom_port_num...........%u\n"
+			"\t\t\t\tto_port_num.............%u\n"
+			"\t\t\t\tto_lid..................%u\n",
+			cl_ntoh16(p_lr->from_lid),
+			p_lr->from_port_num,
+			p_lr->to_port_num, cl_ntoh16(p_lr->to_lid));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, OSM_LOG_VERBOSE,
+			"SwitchInfo dump:\n"
+			"\t\t\t\tlin_cap.................0x%X\n"
+			"\t\t\t\trand_cap................0x%X\n"
+			"\t\t\t\tmcast_cap...............0x%X\n"
+			"\t\t\t\tlin_top.................0x%X\n"
+			"\t\t\t\tdef_port................%u\n"
+			"\t\t\t\tdef_mcast_pri_port......%u\n"
+			"\t\t\t\tdef_mcast_not_port......%u\n"
+			"\t\t\t\tlife_state..............0x%X\n"
+			"\t\t\t\tlids_per_port...........%u\n"
+			"\t\t\t\tpartition_enf_cap.......0x%X\n"
+			"\t\t\t\tflags...................0x%X\n",
+			cl_ntoh16(p_si->lin_cap),
+			cl_ntoh16(p_si->rand_cap),
+			cl_ntoh16(p_si->mcast_cap),
+			cl_ntoh16(p_si->lin_top),
+			p_si->def_port,
+			p_si->def_mcast_pri_port,
+			p_si->def_mcast_not_port,
+			p_si->life_state,
+			cl_ntoh16(p_si->lids_per_port),
+			cl_ntoh16(p_si->enforce_cap), p_si->flags);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, log_level,
+			"SwitchInfo Record dump:\n"
+			"\t\t\t\tRID\n"
+			"\t\t\t\tlid.....................%u\n"
+			"\t\t\t\tSwitchInfo dump:\n"
+			"\t\t\t\tlin_cap.................0x%X\n"
+			"\t\t\t\trand_cap................0x%X\n"
+			"\t\t\t\tmcast_cap...............0x%X\n"
+			"\t\t\t\tlin_top.................0x%X\n"
+			"\t\t\t\tdef_port................%u\n"
+			"\t\t\t\tdef_mcast_pri_port......%u\n"
+			"\t\t\t\tdef_mcast_not_port......%u\n"
+			"\t\t\t\tlife_state..............0x%X\n"
+			"\t\t\t\tlids_per_port...........%u\n"
+			"\t\t\t\tpartition_enf_cap.......0x%X\n"
+			"\t\t\t\tflags...................0x%X\n",
+			cl_ntoh16(p_sir->lid),
+			cl_ntoh16(p_sir->switch_info.lin_cap),
+			cl_ntoh16(p_sir->switch_info.rand_cap),
+			cl_ntoh16(p_sir->switch_info.mcast_cap),
+			cl_ntoh16(p_sir->switch_info.lin_top),
+			p_sir->switch_info.def_port,
+			p_sir->switch_info.def_mcast_pri_port,
+			p_sir->switch_info.def_mcast_not_port,
+			p_sir->switch_info.life_state,
+			cl_ntoh16(p_sir->switch_info.lids_per_port),
+			cl_ntoh16(p_sir->switch_info.enforce_cap),
+			p_sir->switch_info.flags);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf_line[1024];
+		int i, n;
+
+		for (i = 0, n = 0; i < 32; i++)
+			n += sprintf(buf_line + n, " 0x%04x |",
+				     cl_ntoh16(p_pkey_tbl->pkey_entry[i]));
+
+		osm_log(p_log, log_level,
+			"P_Key table dump:\n"
+			"\t\t\tport_guid...........0x%016" PRIx64 "\n"
+			"\t\t\tblock_num...........0x%X\n"
+			"\t\t\tport_num............%u\n\tP_Key Table: %s\n",
+			cl_ntoh64(port_guid), block_num, port_num, buf_line);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf_line1[1024], buf_line2[1024];
+		int n;
+		uint8_t i;
+
+		for (i = 0, n = 0; i < 16; i++)
+			n += sprintf(buf_line1 + n, " %-2u |", i);
+		for (i = 0, n = 0; i < 16; i++)
+			n += sprintf(buf_line2 + n, "0x%01X |",
+				     ib_slvl_table_get(p_slvl_tbl, i));
+		osm_log(p_log, log_level,
+			"SLtoVL dump:\n"
+			"\t\t\tport_guid............0x%016" PRIx64 "\n"
+			"\t\t\tin_port_num..........%u\n"
+			"\t\t\tout_port_num.........%u\n\tSL: | %s\n\tVL: | %s\n",
+			cl_ntoh64(port_guid),
+			in_port_num, out_port_num, buf_line1, buf_line2);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf_line1[1024], buf_line2[1024];
+		int i, n;
+
+		for (i = 0, n = 0; i < 32; i++)
+			n += sprintf(buf_line1 + n, " 0x%01X |",
+				     p_vla_tbl->vl_entry[i].vl);
+		for (i = 0, n = 0; i < 32; i++)
+			n += sprintf(buf_line2 + n, " 0x%01X |",
+				     p_vla_tbl->vl_entry[i].weight);
+		osm_log(p_log, log_level,
+			"VLArb dump:\n" "\t\t\tport_guid...........0x%016"
+			PRIx64 "\n" "\t\t\tblock_num...........0x%X\n"
+			"\t\t\tport_num............%u\n\tVL    : | %s\n\tWEIGHT:| %s\n",
+			cl_ntoh64(port_guid), block_num, port_num, buf_line1,
+			buf_line2);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, OSM_LOG_DEBUG,
+			"SMInfo dump:\n"
+			"\t\t\t\tguid....................0x%016" PRIx64 "\n"
+			"\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+			"\t\t\t\tact_count...............%u\n"
+			"\t\t\t\tpriority................%u\n"
+			"\t\t\t\tsm_state................%u\n",
+			cl_ntoh64(p_smi->guid),
+			cl_ntoh64(p_smi->sm_key),
+			cl_ntoh32(p_smi->act_count),
+			ib_sminfo_get_priority(p_smi),
+			ib_sminfo_get_state(p_smi));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_sm_info_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		osm_log(p_log, OSM_LOG_DEBUG,
+			"SMInfo Record dump:\n"
+			"\t\t\t\tRID\n"
+			"\t\t\t\tLid.....................%u\n"
+			"\t\t\t\tReserved................0x%X\n"
+			"\t\t\t\tSMInfo dump:\n"
+			"\t\t\t\tguid....................0x%016" PRIx64 "\n"
+			"\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+			"\t\t\t\tact_count...............%u\n"
+			"\t\t\t\tpriority................%u\n"
+			"\t\t\t\tsm_state................%u\n",
+			cl_ntoh16(p_smir->lid),
+			cl_ntoh16(p_smir->resv0),
+			cl_ntoh64(p_smir->sm_info.guid),
+			cl_ntoh64(p_smir->sm_info.sm_key),
+			cl_ntoh32(p_smir->sm_info.act_count),
+			ib_sminfo_get_priority(&p_smir->sm_info),
+			ib_sminfo_get_state(&p_smir->sm_info));
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_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)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		if (ib_notice_is_generic(p_ntci)) {
+			char buff[1024];
+			buff[0] = '\0';
+
+			/* immediate data based on the trap */
+			switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) {
+			case 64:
+			case 65:
+			case 66:
+			case 67:
+				sprintf(buff,
+					"\t\t\t\tsrc_gid..................0x%016"
+					PRIx64 ":0x%016" PRIx64 "\n",
+					cl_ntoh64(p_ntci->data_details.
+						  ntc_64_67.gid.unicast.prefix),
+					cl_ntoh64(p_ntci->data_details.
+						  ntc_64_67.gid.unicast.
+						  interface_id));
+				break;
+			case 128:
+				sprintf(buff,
+					"\t\t\t\tsw_lid...................%u\n",
+					cl_ntoh16(p_ntci->data_details.ntc_128.
+						  sw_lid));
+				break;
+			case 129:
+			case 130:
+			case 131:
+				sprintf(buff,
+					"\t\t\t\tlid......................%u\n"
+					"\t\t\t\tport_num.................%u\n",
+					cl_ntoh16(p_ntci->data_details.
+						  ntc_129_131.lid),
+					p_ntci->data_details.ntc_129_131.
+					port_num);
+				break;
+			case 144:
+				sprintf(buff,
+					"\t\t\t\tlid......................%u\n"
+					"\t\t\t\tnew_cap_mask.............0x%08x\n",
+					cl_ntoh16(p_ntci->data_details.ntc_144.
+						  lid),
+					cl_ntoh32(p_ntci->data_details.ntc_144.
+						  new_cap_mask));
+				break;
+			case 145:
+				sprintf(buff,
+					"\t\t\t\tlid......................%u\n"
+					"\t\t\t\tnew_sys_guid.............0x%016"
+					PRIx64 "\n",
+					cl_ntoh16(p_ntci->data_details.ntc_145.
+						  lid),
+					cl_ntoh64(p_ntci->data_details.ntc_145.
+						  new_sys_guid));
+				break;
+			}
+
+			osm_log(p_log, log_level,
+				"Generic Notice dump:\n"
+				"\t\t\t\ttype.....................%u\n"
+				"\t\t\t\tprod_type................%u (%s)\n"
+				"\t\t\t\ttrap_num.................%u\n%s",
+				ib_notice_get_type(p_ntci),
+				cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+				ib_get_producer_type_str(ib_notice_get_prod_type
+							 (p_ntci)),
+				cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+				buff);
+		} else {
+			osm_log(p_log, log_level,
+				"Vendor Notice dump:\n"
+				"\t\t\t\ttype.....................%u\n"
+				"\t\t\t\tvendor...................%u\n"
+				"\t\t\t\tdevice_id................%u\n",
+				cl_ntoh16(ib_notice_get_type(p_ntci)),
+				cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
+				cl_ntoh16(p_ntci->g_or_v.vend.dev_id));
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_dr_smp(IN osm_log_t * const p_log,
+		IN const ib_smp_t * const p_smp,
+		IN const osm_log_level_t log_level)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE], line[BUF_SIZE];
+		uint32_t i;
+
+		sprintf(buf,
+			"SMP dump:\n"
+			"\t\t\t\tbase_ver................0x%X\n"
+			"\t\t\t\tmgmt_class..............0x%X\n"
+			"\t\t\t\tclass_ver...............0x%X\n"
+			"\t\t\t\tmethod..................0x%X (%s)\n",
+			p_smp->base_ver,
+			p_smp->mgmt_class,
+			p_smp->class_ver,
+			p_smp->method, ib_get_sm_method_str(p_smp->method));
+
+		if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) {
+			sprintf(line,
+				"\t\t\t\tD bit...................0x%X\n"
+				"\t\t\t\tstatus..................0x%X\n",
+				ib_smp_is_d(p_smp), ib_smp_get_status(p_smp));
+		} else {
+			sprintf(line,
+				"\t\t\t\tstatus..................0x%X\n",
+				cl_ntoh16(p_smp->status));
+		}
+		strcat(buf, line);
+
+		sprintf(line,
+			"\t\t\t\thop_ptr.................0x%X\n"
+			"\t\t\t\thop_count...............0x%X\n"
+			"\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+			"\t\t\t\tattr_id.................0x%X (%s)\n"
+			"\t\t\t\tresv....................0x%X\n"
+			"\t\t\t\tattr_mod................0x%X\n"
+			"\t\t\t\tm_key...................0x%016" PRIx64 "\n",
+			p_smp->hop_ptr,
+			p_smp->hop_count,
+			cl_ntoh64(p_smp->trans_id),
+			cl_ntoh16(p_smp->attr_id),
+			ib_get_sm_attr_str(p_smp->attr_id),
+			cl_ntoh16(p_smp->resv),
+			cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->m_key));
+		strcat(buf, line);
+
+		if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) {
+			sprintf(line,
+				"\t\t\t\tdr_slid.................%u\n"
+				"\t\t\t\tdr_dlid.................%u\n",
+				cl_ntoh16(p_smp->dr_slid),
+				cl_ntoh16(p_smp->dr_dlid));
+			strcat(buf, line);
+
+			strcat(buf, "\n\t\t\t\tInitial path: ");
+
+			for (i = 0; i <= p_smp->hop_count; i++) {
+				if (i == 0)
+					sprintf(line, "%d",
+						p_smp->initial_path[i]);
+				else
+					sprintf(line, ",%d",
+						p_smp->initial_path[i]);
+				strcat(buf, line);
+			}
+
+			strcat(buf, "\n\t\t\t\tReturn path:  ");
+
+			for (i = 0; i <= p_smp->hop_count; i++) {
+				if (i == 0)
+					sprintf(line, "%d",
+						p_smp->return_path[i]);
+				else
+					sprintf(line, ",%d",
+						p_smp->return_path[i]);
+				strcat(buf, line);
+			}
+
+			strcat(buf, "\n\t\t\t\tReserved:     ");
+
+			for (i = 0; i < 7; i++) {
+				sprintf(line, "[%0X]", p_smp->resv1[i]);
+				strcat(buf, line);
+			}
+
+			strcat(buf, "\n");
+
+			for (i = 0; i < 64; i += 16) {
+				sprintf(line, "\n\t\t\t\t%02X %02X %02X %02X "
+					"%02X %02X %02X %02X"
+					"   %02X %02X %02X %02X %02X %02X %02X %02X\n",
+					p_smp->data[i],
+					p_smp->data[i + 1],
+					p_smp->data[i + 2],
+					p_smp->data[i + 3],
+					p_smp->data[i + 4],
+					p_smp->data[i + 5],
+					p_smp->data[i + 6],
+					p_smp->data[i + 7],
+					p_smp->data[i + 8],
+					p_smp->data[i + 9],
+					p_smp->data[i + 10],
+					p_smp->data[i + 11],
+					p_smp->data[i + 12],
+					p_smp->data[i + 13],
+					p_smp->data[i + 14],
+					p_smp->data[i + 15]);
+
+				strcat(buf, line);
+			}
+		} else {
+			/* not a Direct Route so provide source and destination lids */
+			strcat(buf, "\t\t\t\tMAD IS LID ROUTED\n");
+		}
+
+		osm_log(p_log, log_level, "%s\n", buf);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_sa_mad(IN osm_log_t * const p_log,
+		IN const ib_sa_mad_t * const p_mad,
+		IN const osm_log_level_t log_level)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE];
+
+		/* make sure the mad is valid */
+		if (p_mad == NULL) {
+			OSM_LOG(p_log, log_level, "NULL MAD POINTER\n");
+			return;
+		}
+
+		sprintf(buf,
+			"SA MAD dump:\n"
+			"\t\t\t\tbase_ver................0x%X\n"
+			"\t\t\t\tmgmt_class..............0x%X\n"
+			"\t\t\t\tclass_ver...............0x%X\n"
+			"\t\t\t\tmethod..................0x%X (%s)\n"
+			"\t\t\t\tstatus..................0x%X\n"
+			"\t\t\t\tresv....................0x%X\n"
+			"\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+			"\t\t\t\tattr_id.................0x%X (%s)\n"
+			"\t\t\t\tresv1...................0x%X\n"
+			"\t\t\t\tattr_mod................0x%X\n"
+			"\t\t\t\trmpp_version............0x%X\n"
+			"\t\t\t\trmpp_type...............0x%X\n"
+			"\t\t\t\trmpp_flags..............0x%X\n"
+			"\t\t\t\trmpp_status.............0x%X\n"
+			"\t\t\t\tseg_num.................0x%X\n"
+			"\t\t\t\tpayload_len/new_win.....0x%X\n"
+			"\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+			"\t\t\t\tattr_offset.............0x%X\n"
+			"\t\t\t\tresv2...................0x%X\n"
+			"\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n",
+			p_mad->base_ver,
+			p_mad->mgmt_class,
+			p_mad->class_ver,
+			p_mad->method, ib_get_sa_method_str(p_mad->method),
+			cl_ntoh16(p_mad->status),
+			cl_ntoh16(p_mad->resv),
+			cl_ntoh64(p_mad->trans_id),
+			cl_ntoh16(p_mad->attr_id),
+			ib_get_sa_attr_str(p_mad->attr_id),
+			cl_ntoh16(p_mad->resv1),
+			cl_ntoh32(p_mad->attr_mod),
+			p_mad->rmpp_version,
+			p_mad->rmpp_type,
+			p_mad->rmpp_flags,
+			p_mad->rmpp_status,
+			cl_ntoh32(p_mad->seg_num),
+			cl_ntoh32(p_mad->paylen_newwin),
+			cl_ntoh64(p_mad->sm_key),
+			cl_ntoh16(p_mad->attr_offset),
+			cl_ntoh16(p_mad->resv3), cl_ntoh64(p_mad->comp_mask));
+
+		strcat(buf, "\n");
+
+		osm_log(p_log, log_level, "%s\n", buf);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 log_level)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE], line[BUF_SIZE];
+		uint32_t i;
+
+		sprintf(buf, "Directed Path Dump of %u hop path:"
+			"\n\t\t\t\tPath = ", p_path->hop_count);
+
+		for (i = 0; i <= p_path->hop_count; i++) {
+			if (i == 0)
+				sprintf(line, "%d", p_path->path[i]);
+			else
+				sprintf(line, ",%d", p_path->path[i]);
+			strcat(buf, line);
+		}
+		osm_log(p_log, log_level, "%s\n", buf);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 log_level)
+{
+	if (osm_log_is_active(p_log, log_level)) {
+		char buf[BUF_SIZE], line[BUF_SIZE];
+		uint32_t i;
+
+		sprintf(buf, "Received SMP on a %u hop path:"
+			"\n\t\t\t\tInitial path = ", p_smp->hop_count);
+
+		for (i = 0; i <= p_smp->hop_count; i++) {
+			if (i == 0)
+				sprintf(line, "%d", p_smp->initial_path[i]);
+			else
+				sprintf(line, ",%d", p_smp->initial_path[i]);
+			strcat(buf, line);
+		}
+
+		strcat(buf, "\n\t\t\t\tReturn path  = ");
+
+		for (i = 0; i <= p_smp->hop_count; i++) {
+			if (i == 0)
+				sprintf(line, "%d", p_smp->return_path[i]);
+			else
+				sprintf(line, ",%d", p_smp->return_path[i]);
+			strcat(buf, line);
+		}
+
+		osm_log(p_log, log_level, "%s\n", buf);
+	}
+}
+
+static const char *const __osm_sm_signal_str[] = {
+	"OSM_SIGNAL_NONE",	/* 0 */
+	"OSM_SIGNAL_SWEEP",	/* 1 */
+	"OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST",	/* 2 */
+	"OSM_SIGNAL_EXIT_STBY",	/* 3 */
+	"OSM_SIGNAL_PERFMGR_SWEEP",	/* 4 */
+	"UNKNOWN SIGNAL!!"	/* 5 */
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_sm_signal_str(IN osm_signal_t signal)
+{
+	if (signal > OSM_SIGNAL_MAX)
+		signal = OSM_SIGNAL_MAX;
+	return (__osm_sm_signal_str[signal]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static const char *const __osm_disp_msg_str[] = {
+	"OSM_MSG_NONE",
+	"OSM_MSG_MAD_NODE_INFO",
+	"OSM_MSG_MAD_PORT_INFO",
+	"OSM_MSG_MAD_SWITCH_INFO",
+	"OSM_MSG_MAD_NODE_DESC",
+	"OSM_MSG_MAD_NODE_RECORD",
+	"OSM_MSG_MAD_PORTINFO_RECORD",
+	"OSM_MSG_MAD_SERVICE_RECORD",
+	"OSM_MSG_MAD_PATH_RECORD",
+	"OSM_MSG_MAD_MCMEMBER_RECORD",
+	"OSM_MSG_MAD_LINK_RECORD",
+	"OSM_MSG_MAD_SMINFO_RECORD",
+	"OSM_MSG_MAD_CLASS_PORT_INFO",
+	"OSM_MSG_MAD_INFORM_INFO",
+	"OSM_MSG_MAD_LFT_RECORD",
+	"OSM_MSG_MAD_LFT",
+	"OSM_MSG_MAD_SM_INFO",
+	"OSM_MSG_MAD_NOTICE",
+	"OSM_MSG_LIGHT_SWEEP_FAIL",
+	"OSM_MSG_MAD_MFT",
+	"OSM_MSG_MAD_PKEY_TBL_RECORD",
+	"OSM_MSG_MAD_VL_ARB_RECORD",
+	"OSM_MSG_MAD_SLVL_TBL_RECORD",
+	"OSM_MSG_MAD_PKEY",
+	"OSM_MSG_MAD_VL_ARB",
+	"OSM_MSG_MAD_SLVL",
+	"OSM_MSG_MAD_GUIDINFO_RECORD",
+	"OSM_MSG_MAD_INFORM_INFO_RECORD",
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	"OSM_MSG_MAD_MULTIPATH_RECORD",
+#endif
+	"UNKNOWN!!"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_disp_msg_str(IN cl_disp_msgid_t msg)
+{
+	if (msg > OSM_MSG_MAX)
+		msg = OSM_MSG_MAX;
+	return (__osm_disp_msg_str[msg]);
+}
+
+static const char *const __osm_port_state_str_fixed_width[] = {
+	"NOC",
+	"DWN",
+	"INI",
+	"ARM",
+	"ACT",
+	"???"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_port_state_str_fixed_width(IN uint8_t port_state)
+{
+	if (port_state > IB_LINK_ACTIVE)
+		port_state = IB_LINK_ACTIVE + 1;
+	return (__osm_port_state_str_fixed_width[port_state]);
+}
+
+static const char *const __osm_node_type_str_fixed_width[] = {
+	"??",
+	"CA",
+	"SW",
+	"RT",
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_node_type_str_fixed_width(IN uint8_t node_type)
+{
+	if (node_type > IB_NODE_TYPE_ROUTER)
+		node_type = 0;
+	return (__osm_node_type_str_fixed_width[node_type]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_manufacturer_str(IN uint64_t const guid_ho)
+{
+	/* note that the max vendor string length is 11 */
+	static const char *intel_str = "Intel";
+	static const char *mellanox_str = "Mellanox";
+	static const char *redswitch_str = "Redswitch";
+	static const char *silverstorm_str = "SilverStorm";
+	static const char *topspin_str = "Topspin";
+	static const char *fujitsu_str = "Fujitsu";
+	static const char *voltaire_str = "Voltaire";
+	static const char *yotta_str = "YottaYotta";
+	static const char *pathscale_str = "PathScale";
+	static const char *ibm_str = "IBM";
+	static const char *divergenet_str = "DivergeNet";
+	static const char *flextronics_str = "Flextronics";
+	static const char *agilent_str = "Agilent";
+	static const char *obsidian_str = "Obsidian";
+	static const char *baymicro_str = "BayMicro";
+	static const char *lsilogic_str = "LSILogic";
+	static const char *ddn_str = "DataDirect";
+	static const char *panta_str = "Panta";
+	static const char *hp_str = "HP";
+	static const char *rioworks_str = "Rioworks";
+	static const char *sun_str = "Sun";
+	static const char *leafntwks_str = "3LeafNtwks";
+	static const char *xsigo_str = "Xsigo";
+	static const char *unknown_str = "Unknown";
+
+	switch ((uint32_t) (guid_ho >> (5 * 8))) {
+	case OSM_VENDOR_ID_INTEL:
+		return (intel_str);
+	case OSM_VENDOR_ID_MELLANOX:
+		return (mellanox_str);
+	case OSM_VENDOR_ID_REDSWITCH:
+		return (redswitch_str);
+	case OSM_VENDOR_ID_SILVERSTORM:
+		return (silverstorm_str);
+	case OSM_VENDOR_ID_TOPSPIN:
+		return (topspin_str);
+	case OSM_VENDOR_ID_FUJITSU:
+	case OSM_VENDOR_ID_FUJITSU2:
+		return (fujitsu_str);
+	case OSM_VENDOR_ID_VOLTAIRE:
+		return (voltaire_str);
+	case OSM_VENDOR_ID_YOTTAYOTTA:
+		return (yotta_str);
+	case OSM_VENDOR_ID_PATHSCALE:
+		return (pathscale_str);
+	case OSM_VENDOR_ID_IBM:
+		return (ibm_str);
+	case OSM_VENDOR_ID_DIVERGENET:
+		return (divergenet_str);
+	case OSM_VENDOR_ID_FLEXTRONICS:
+		return (flextronics_str);
+	case OSM_VENDOR_ID_AGILENT:
+		return (agilent_str);
+	case OSM_VENDOR_ID_OBSIDIAN:
+		return (obsidian_str);
+	case OSM_VENDOR_ID_BAYMICRO:
+		return (baymicro_str);
+	case OSM_VENDOR_ID_LSILOGIC:
+		return (lsilogic_str);
+	case OSM_VENDOR_ID_DDN:
+		return (ddn_str);
+	case OSM_VENDOR_ID_PANTA:
+		return (panta_str);
+	case OSM_VENDOR_ID_HP:
+	case OSM_VENDOR_ID_HP2:
+		return (hp_str);
+	case OSM_VENDOR_ID_RIOWORKS:
+		return (rioworks_str);
+	case OSM_VENDOR_ID_SUN:
+		return (sun_str);
+	case OSM_VENDOR_ID_3LEAFNTWKS:
+		return (leafntwks_str);
+	case OSM_VENDOR_ID_XSIGO:
+		return (xsigo_str);
+	default:
+		return (unknown_str);
+	}
+}
+
+static const char *const __osm_mtu_str_fixed_width[] = {
+	"??? ",
+	"256 ",
+	"512 ",
+	"1024",
+	"2048",
+	"4096"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_mtu_str(IN uint8_t const mtu)
+{
+	if (mtu > IB_MTU_LEN_4096)
+		return (__osm_mtu_str_fixed_width[0]);
+	else
+		return (__osm_mtu_str_fixed_width[mtu]);
+}
+
+static const char *const __osm_lwa_str_fixed_width[] = {
+	"???",
+	"1x ",
+	"4x ",
+	"???",
+	"8x ",
+	"???",
+	"???",
+	"???",
+	"12x"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_lwa_str(IN uint8_t const lwa)
+{
+	if (lwa > 8)
+		return (__osm_lwa_str_fixed_width[0]);
+	else
+		return (__osm_lwa_str_fixed_width[lwa]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const char *const __osm_lsa_str_fixed_width[] = {
+	"???",
+	"2.5",
+	"5  ",
+	"???",
+	"10 "
+};
+
+const char *osm_get_lsa_str(IN uint8_t const lsa)
+{
+	if (lsa > 4)
+		return (__osm_lsa_str_fixed_width[0]);
+	else
+		return (__osm_lsa_str_fixed_width[lsa]);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static const char *const __osm_sm_mgr_signal_str[] = {
+	"OSM_SM_SIGNAL_NONE",	/* 0 */
+	"OSM_SM_SIGNAL_DISCOVERY_COMPLETED",	/* 2 */
+	"OSM_SM_SIGNAL_POLLING_TIMEOUT",	/* 3 */
+	"OSM_SM_SIGNAL_DISCOVER",	/* 4 */
+	"OSM_SM_SIGNAL_DISABLE",	/* 5 */
+	"OSM_SM_SIGNAL_HANDOVER",	/* 6 */
+	"OSM_SM_SIGNAL_HANDOVER_SENT",	/* 7 */
+	"OSM_SM_SIGNAL_ACKNOWLEDGE",	/* 8 */
+	"OSM_SM_SIGNAL_STANDBY",	/* 9 */
+	"OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED",	/* 10 */
+	"OSM_SM_SIGNAL_WAIT_FOR_HANDOVER",	/* 11 */
+	"UNKNOWN STATE!!"	/* 12 */
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_get_sm_mgr_signal_str(IN osm_sm_signal_t signal)
+{
+	if (signal > OSM_SM_SIGNAL_MAX)
+		signal = OSM_SM_SIGNAL_MAX;
+	return (__osm_sm_mgr_signal_str[signal]);
+}
+
+static const char *const __osm_sm_mgr_state_str[] = {
+	"NOTACTIVE",	/* 0 */
+	"DISCOVERING",	/* 1 */
+	"STANDBY",	/* 2 */
+	"MASTER",	/* 3 */
+	"UNKNOWN STATE!!"	/* 4 */
+};
+
+const char *osm_get_sm_mgr_state_str(IN uint16_t state)
+{
+	return state < ARR_SIZE(__osm_sm_mgr_state_str) ?
+		__osm_sm_mgr_state_str[state] :
+		__osm_sm_mgr_state_str[ARR_SIZE(__osm_sm_mgr_state_str) - 1];
+}
diff --git a/opensm/osm_inform.c b/opensm/osm_inform.c
new file mode 100644
index 0000000..f3c8ed7
--- /dev/null
+++ b/opensm/osm_inform.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of inform record functions.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_inform.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.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_delete(IN osm_infr_t * const p_infr)
+{
+	free(p_infr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec)
+{
+	osm_infr_t *p_infr;
+
+	CL_ASSERT(p_infr_rec);
+
+	p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t));
+	if (p_infr)
+		memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t));
+
+	return (p_infr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void dump_all_informs(IN osm_subn_t const *p_subn, IN osm_log_t * p_log)
+{
+	cl_list_item_t *p_list_item;
+
+	if (!osm_log_is_active(p_log, OSM_LOG_DEBUG))
+		return;
+
+	p_list_item = cl_qlist_head(&p_subn->sa_infr_list);
+	while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) {
+		osm_dump_inform_info(p_log,
+				     &((osm_infr_t *) p_list_item)->
+				     inform_record.inform_info, OSM_LOG_DEBUG);
+		p_list_item = cl_qlist_next(p_list_item);
+	}
+}
+
+/**********************************************************************
+ * Match an infr by the InformInfo and Address vector
+ **********************************************************************/
+static cl_status_t
+__match_inf_rec(IN const cl_list_item_t * 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->sa->p_log;
+	cl_status_t status = CL_NOT_FOUND;
+	ib_gid_t all_zero_gid;
+
+	OSM_LOG_ENTER(p_log);
+
+	if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr,
+		   sizeof(p_infr_rec->report_addr))) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n");
+		goto Exit;
+	}
+
+	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,
+				"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,
+				"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,
+			"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,
+			"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,
+				"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,
+				"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,
+				"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,
+				"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,
+				"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,
+				"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,
+				"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,
+				"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);
+
+	dump_all_informs(p_subn, p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "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, "InformInfo list size %d\n",
+		cl_qlist_count(&p_subn->sa_infr_list));
+
+	p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list,
+					      __match_inf_rec, p_infr_rec);
+
+	if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list))
+		p_list_item = NULL;
+
+	OSM_LOG_EXIT(p_log);
+	return (osm_infr_t *) p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_insert_to_db(IN osm_subn_t * p_subn,
+		      IN osm_log_t * p_log, IN osm_infr_t * p_infr)
+{
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Inserting new InformInfo Record into Database\n");
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n",
+		cl_qlist_count(&p_subn->sa_infr_list));
+	dump_all_informs(p_subn, p_log);
+
+#if 0
+	osm_dump_inform_info(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, "Dump after insertion (size %d)\n",
+		cl_qlist_count(&p_subn->sa_infr_list));
+	dump_all_informs(p_subn, p_log);
+	OSM_LOG_EXIT(p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_remove_from_db(IN osm_subn_t * p_subn,
+			IN osm_log_t * p_log, IN osm_infr_t * p_infr)
+{
+	char gid_str[INET6_ADDRSTRLEN];
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s"
+		" Enum:0x%X from Database\n",
+		inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw,
+			gid_str, sizeof gid_str),
+		p_infr->inform_record.subscriber_enum);
+
+	osm_dump_inform_info(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_delete(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 = IB_SUCCESS;
+	osm_log_t *p_log = p_infr_rec->sa->p_log;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */
+
+	/* it is better to use LIDs since the GIDs might not be there for SMI traps */
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID:%u"
+		" to InformInfo LID: %u 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->sa->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, "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 */
+	osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE);
+
+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->sa->p_log;
+	osm_subn_t *p_subn = p_infr_rec->sa->p_subn;
+	ib_gid_t source_gid;
+	osm_port_t *p_src_port;
+	osm_port_t *p_dest_port;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* matching rules
+	 * InformInfo   Notice
+	 * GID          IssuerGID    if non zero must match the trap
+	 * LIDRange     IssuerLID    apply only if GID=0
+	 * IsGeneric    IsGeneric    is compulsory and must match the trap
+	 * Type         Type         if not 0xFFFF must match
+	 * TrapNumber   TrapNumber   if not 0xFFFF must match
+	 * DeviceId     DeviceID     if not 0xFFFF must match
+	 * QPN dont care
+	 * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation
+	 * VendorID     VendorID     match or 0xFFFFFF
+	 */
+
+	/* GID          IssuerGID    if non zero must match the trap  */
+	if (p_ii->gid.unicast.prefix != 0
+	    || p_ii->gid.unicast.interface_id != 0) {
+		/* match by GID */
+		if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid),
+			   sizeof(ib_gid_t))) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n");
+			goto Exit;
+		}
+	} else {
+		/* LIDRange     IssuerLID    apply only if GID=0 */
+		/* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */
+		if (p_ii->lid_range_begin != 0xFFFF) {
+			/* a real lid range is given - check it */
+			if ((cl_hton16(p_ii->lid_range_begin) >
+			     cl_hton16(p_ntc->issuer_lid))
+			    || (cl_hton16(p_ntc->issuer_lid) >
+				cl_hton16(p_ii->lid_range_end))) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Mismatch by LID Range. Needed: %u <= %u <= %u\n",
+					cl_hton16(p_ii->lid_range_begin),
+					cl_hton16(p_ntc->issuer_lid),
+					cl_hton16(p_ii->lid_range_end));
+				goto Exit;
+			}
+		}
+	}
+
+	/* IsGeneric    IsGeneric    is compulsory and must match the trap  */
+	if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) ||
+	    (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n");
+		goto Exit;
+	}
+
+	/* Type         Type         if not 0xFFFF must match */
+	if ((p_ii->trap_type != 0xFFFF) &&
+	    (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n");
+		goto Exit;
+	}
+
+	/* based on generic type */
+	if (p_ii->is_generic) {
+		/* TrapNumber   TrapNumber   if not 0xFFFF must match */
+		if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) &&
+		    (p_ii->g_or_v.generic.trap_num !=
+		     p_ntc->g_or_v.generic.trap_num)) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n");
+			goto Exit;
+		}
+
+		/* ProducerType ProducerType match or 0xFFFFFF  */
+		if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF)
+		    && (ib_inform_info_get_prod_type(p_ii) !=
+			ib_notice_get_prod_type(p_ntc))) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG,
+				"Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n",
+				cl_ntoh32(ib_inform_info_get_prod_type(p_ii)),
+				ib_get_producer_type_str
+				(ib_inform_info_get_prod_type(p_ii)),
+				cl_ntoh32(ib_notice_get_prod_type(p_ntc)),
+				ib_get_producer_type_str(ib_notice_get_prod_type
+							 (p_ntc)));
+			goto Exit;
+		}
+	} else {
+		/* DeviceId     DeviceID     if not 0xFFFF must match */
+		if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) &&
+		    (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n");
+			goto Exit;
+		}
+
+		/* VendorID     VendorID     match or 0xFFFFFF  */
+		if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) &&
+		    (ib_inform_info_get_vend_id(p_ii) !=
+		     ib_notice_get_vend_id(p_ntc))) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Vendor ID\n");
+			goto Exit;
+		}
+	}
+
+	/* 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_get_port_by_guid(p_subn, source_gid.unicast.interface_id);
+	if (!p_src_port) {
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Cannot find source port with GUID:0x%016" PRIx64 "\n",
+			cl_ntoh64(source_gid.unicast.interface_id));
+		goto Exit;
+	}
+
+	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,
+			"Cannot find destination port with LID:%u\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, "Mismatch by Pkey\n");
+		/* According to o13-17.1.2 - If this informInfo does not have
+		   lid_range_begin of 0xFFFF, then this informInfo request
+		   should be removed from database */
+		if (p_ii->lid_range_begin != 0xFFFF) {
+			OSM_LOG(p_log, OSM_LOG_VERBOSE,
+				"Pkey mismatch on lid_range_begin != 0xFFFF. "
+				"Need to remove this informInfo from db\n");
+			/* add the informInfo record to the remove_infr list */
+			cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec);
+		}
+		goto Exit;
+	}
+
+	/* send the report to the address provided in the inform record */
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "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)
+{
+	char gid_str[INET6_ADDRSTRLEN];
+	osm_infr_match_ctxt_t context;
+	cl_list_t infr_to_remove_list;
+	osm_infr_t *p_infr_rec;
+	osm_infr_t *p_next_infr_rec;
+
+	OSM_LOG_ENTER(p_log);
+
+	/*
+	 * we must make sure we are ready for this...
+	 * note that the trap receivers might be initialized before
+	 * the osm_infr_init call is performed.
+	 */
+	if (p_subn->sa_infr_list.state != CL_INITIALIZED) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Ignoring Notice Reports since Inform List is not initialized yet!\n");
+		return (IB_ERROR);
+	}
+
+	/* an official Event information log */
+	if (ib_notice_is_generic(p_ntc))
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Reporting Generic Notice type:%u num:%u (%s)"
+			" from LID:%u GID:%s\n",
+			ib_notice_get_type(p_ntc),
+			cl_ntoh16(p_ntc->g_or_v.generic.trap_num),
+			ib_get_trap_str(p_ntc->g_or_v.generic.trap_num),
+			cl_ntoh16(p_ntc->issuer_lid),
+			inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str,
+				sizeof gid_str));
+	else
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Reporting Vendor Notice type:%u vend:%u dev:%u"
+			" from LID:%u GID:%s\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),
+			inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str,
+				sizeof gid_str));
+
+	/* 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);
+}
diff --git a/opensm/osm_lid_mgr.c b/opensm/osm_lid_mgr.c
new file mode 100644
index 0000000..b74aba5
--- /dev/null
+++ b/opensm/osm_lid_mgr.c
@@ -0,0 +1,1321 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_lid_mgr_t.
+ * This file implements the LID Manager object which is responsible for
+ * assigning LIDs to all ports on the subnet.
+ *
+ * DATA STRUCTURES:
+ *  p_subn->port_lid_tbl : a vector pointing from lid to its port.
+ *  osm db guid2lid domain : a hash from guid to lid (min lid).
+ *  p_subn->port_guid_tbl : a map from guid to discovered port obj.
+ *
+ * ALGORITHM:
+ *
+ * 0. we define a function to obtain the correct port lid:
+ *    __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
+ */
+
+#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_sm.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>
+
+/**********************************************************************
+  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);
+
+	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);
+
+	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, "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, "ERR 0311: "
+				"could not get lid for guid:0x%016" PRIx64 "\n",
+				p_item->guid);
+		else {
+			lids_ok = TRUE;
+
+			if ((min_lid > max_lid) || (min_lid == 0)
+			    || (p_item->guid == 0)
+			    || (max_lid > p_mgr->p_subn->max_ucast_lid_ho)) {
+				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0312: "
+					"Illegal LID range [%u:%u] for "
+					"guid:0x%016" PRIx64 "\n", min_lid,
+					max_lid, p_item->guid);
+				lids_ok = FALSE;
+			} else if ((min_lid != max_lid)
+				   && ((min_lid & lmc_mask) != min_lid)) {
+				/* check that if the lids define a range that is valid
+				   for the current LMC mask */
+				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0313: "
+					"LID range [%u:%u] for guid:0x%016"
+					PRIx64
+					" is not aligned according to mask:0x%04x\n",
+					min_lid, max_lid, p_item->guid,
+					lmc_mask);
+				lids_ok = FALSE;
+			} else {
+				/* check if the lids were not previously assigned */
+				for (lid = min_lid; lid <= max_lid; lid++) {
+					if ((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, "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,
+						"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 */
+		free(p_item);
+		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_sm_t *sm)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	osm_lid_mgr_construct(p_mgr);
+
+	p_mgr->sm = sm;
+	p_mgr->p_log = sm->p_log;
+	p_mgr->p_subn = sm->p_subn;
+	p_mgr->p_db = sm->p_db;
+	p_mgr->p_lock = sm->p_lock;
+
+	/* we initialize and restore the db domain of guid to lid map */
+	p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "/guid2lid");
+	if (!p_mgr->p_g2l) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0316: "
+			"Error initializing Guid-to-Lid persistent database\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	cl_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, so we might see corrupted guid2lid file.
+			 */
+			if (p_mgr->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,
+					"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);
+
+	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,
+				"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,
+				"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, "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,
+			"Skipping all lids as we are reassigning them\n");
+		p_range =
+		    (osm_lid_mgr_range_t *) malloc(sizeof(osm_lid_mgr_range_t));
+		if (p_range)
+			p_range->min_lid = 1;
+		goto AfterScanningLids;
+	}
+
+	/* go over all discovered ports and mark their entries */
+	p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+	for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
+	     p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl);
+	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
+		osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+		disc_min_lid = __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,
+					"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,
+				"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,
+						"0x%04x is free as it was "
+						"discovered but mapped by the "
+						"persistent db to [0x%04x:0x%04x]\n",
+						lid, db_min_lid, db_max_lid);
+				} else {
+					/* can the port keep its assignment ? */
+					/* get the lid range of that port, and the required number
+					   of lids we are about to assign to it */
+					osm_port_get_lid_range_ho(p_port,
+								  &disc_min_lid,
+								  &disc_max_lid);
+					if (!p_port->p_node->sw
+					    ||
+					    osm_switch_sp0_is_lmc_capable
+					    (p_port->p_node->sw,
+					     p_mgr->p_subn)) {
+						disc_max_lid =
+						    disc_min_lid +
+						    lmc_num_lids - 1;
+						num_lids = lmc_num_lids;
+					} else
+						num_lids = 1;
+
+					/* Make sure the lid is aligned */
+					if ((num_lids != 1)
+					    && ((disc_min_lid & lmc_mask) !=
+						disc_min_lid)) {
+						/* The lid cannot be used */
+						OSM_LOG(p_mgr->p_log,
+							OSM_LOG_DEBUG,
+							"0x%04x is free as it was "
+							"discovered but not aligned\n",
+							lid);
+					} else {
+						/* check that all needed lids are not persistently mapped */
+						is_free = FALSE;
+						for (req_lid = disc_min_lid + 1;
+						     req_lid <= disc_max_lid;
+						     req_lid++) {
+							if ((req_lid <=
+							     max_persistent_lid)
+							    &&
+							    cl_ptr_vector_get
+							    (p_persistent_vec,
+							     req_lid)) {
+								OSM_LOG(p_mgr->
+									p_log,
+									OSM_LOG_DEBUG,
+									"0x%04x is free as it was discovered "
+									"but mapped\n",
+									lid);
+								is_free = TRUE;
+								break;
+							}
+						}
+
+						if (is_free == FALSE) {
+							/* This port will use its local lid, and consume the entire required lid range.
+							   Thus we can skip that range. */
+							/* If the disc_max_lid is greater then lid, we can skip right to it,
+							   since we've done all neccessary checks on the lids in between. */
+							if (disc_max_lid > lid)
+								lid =
+								    disc_max_lid;
+						}
+					}
+				}
+			}
+		}
+
+		if (is_free) {
+			if (p_range)
+				p_range->max_lid = lid;
+			else {
+				p_range = (osm_lid_mgr_range_t *)
+				    malloc(sizeof(osm_lid_mgr_range_t));
+				if (p_range) {
+					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,
+					"new free lid range [%u:%u]\n",
+					p_range->min_lid, p_range->max_lid);
+				p_range = NULL;
+			}
+		}
+	}
+
+AfterScanningLids:
+	/* after scanning all known lids we need to extend the last range
+	   to the max allowed lid */
+	if (!p_range) {
+		p_range =
+		    (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.
+		 */
+		if (p_range)
+			p_range->min_lid = lid;
+	}
+	if (p_range) {
+		p_range->max_lid = p_mgr->p_subn->max_ucast_lid_ho;
+		cl_qlist_insert_tail(&p_mgr->free_ranges, &p_range->item);
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"final free lid range [%u:%u]\n",
+			p_range->min_lid, p_range->max_lid);
+	}
+
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return status;
+}
+
+/**********************************************************************
+ check if the given range of lids is free
+**********************************************************************/
+static boolean_t
+__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, "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, "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);
+
+	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, "0x%016" PRIx64
+				" matches its known lid:%u\n", guid, min_lid);
+			goto Exit;
+		} else {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"0x%016" PRIx64 " with lid:%u "
+				"does not match its known lid:%u\n",
+				guid, cl_ntoh16(osm_port_get_base_lid(p_port)),
+				min_lid);
+			__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,
+			"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,
+					"0x%016" PRIx64
+					" lid range:[%u-%u] is free\n",
+					guid, *p_min_lid, *p_max_lid);
+				goto NewLidSet;
+			} else
+				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+					"0x%016" PRIx64 " existing lid "
+					"range:[%u:%u] is not free\n",
+					guid, min_lid, min_lid + num_lids - 1);
+		} else
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"0x%016" PRIx64 " existing lid range:"
+				"[%u:%u] is not lmc aligned\n",
+				guid, min_lid, min_lid + num_lids - 1);
+	}
+
+	/* 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,
+		"0x%016" PRIx64 " assigned a new lid range:[%u-%u]\n",
+		guid, *p_min_lid, *p_max_lid);
+	lid_changed = 1;
+
+NewLidSet:
+	/* update the guid2lid db and used_lids */
+	osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid);
+	for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
+		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)
+{
+	osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp);
+
+	if (p_rem_physp == NULL)
+		return;
+
+	/* but in some rare cases the remote side might be non responsive */
+	ib_port_info_set_port_state(&p_rem_physp->port_info, IB_LINK_INIT);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static 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;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	/*
+	   Don't bother doing anything if this Physical Port is not valid.
+	   This allows simplified code in the caller.
+	 */
+	if (!p_physp)
+		goto Exit;
+
+	port_num = osm_physp_get_port_num(p_physp);
+	p_node = osm_physp_get_node_ptr(p_physp);
+
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0) {
+		/*
+		   Switch ports that are not numbered 0 should not be set
+		   with the following attributes as they are set later
+		   (during NO_CHANGE state in link mgr).
+		 */
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Skipping switch port %u, GUID 0x%016" PRIx64 "\n",
+			port_num, cl_ntoh64(osm_physp_get_port_guid(p_physp)));
+		goto Exit;
+	}
+
+	p_old_pi = &p_physp->port_info;
+
+	/*
+	   First, copy existing parameters from the PortInfo attribute we
+	   already have for this node.
+
+	   Second, update with default values that we know must be set for
+	   every Physical Port and the LID and set the neighbor MTU field
+	   appropriately.
+
+	   Third, send the SMP to this physical port.
+	 */
+
+	memset(payload, 0, IB_SMP_DATA_SIZE);
+	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));
+
+	/*
+	   Should never write back a value that is bigger then 3 in
+	   the PortPhysicalState field, so cannot simply copy!
+
+	   Actually we want to write there:
+	   port physical state - no change
+	   link down default state = polling
+	   port state - no change
+	 */
+	p_pi->state_info2 = 0x02;
+	ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE);
+
+	if (ib_port_info_get_link_down_def_state(p_pi) !=
+	    ib_port_info_get_link_down_def_state(p_old_pi))
+		send_set = TRUE;
+
+	/* didn't get PortInfo before */
+	if (!ib_port_info_get_port_state(p_old_pi))
+		send_set = TRUE;
+
+	p_pi->m_key = p_mgr->p_subn->opt.m_key;
+	if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key)))
+		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 = lid;
+	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;
+	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;
+
+	/*
+	   we want to set the timeout for both the switch port 0
+	   and the CA ports
+	 */
+	ib_port_info_set_timeout(p_pi, p_mgr->p_subn->opt.subnet_timeout);
+	if (ib_port_info_get_timeout(p_pi) !=
+	    ib_port_info_get_timeout(p_old_pi))
+		send_set = TRUE;
+
+	if (port_num != 0) {
+		/*
+		   CAs don't have a port 0, and for switch port 0,
+		   the state bits are ignored.
+		   This is not the switch management port
+		 */
+		p_pi->link_width_enabled = p_old_pi->link_width_supported;
+		if (memcmp(&p_pi->link_width_enabled,
+			   &p_old_pi->link_width_enabled,
+			   sizeof(p_pi->link_width_enabled)))
+			send_set = TRUE;
+
+		/* M_KeyProtectBits are always zero */
+		p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+		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))) {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"Sending Link Down to GUID 0x%016"
+				PRIx64 " port %d due to op_vls or "
+				"mtu change. MTU:%u,%u VL_CAP:%u,%u\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+				port_num, mtu,
+				ib_port_info_get_neighbor_mtu(p_old_pi),
+				op_vls, ib_port_info_get_op_vls(p_old_pi));
+
+			/*
+			   we need to make sure the internal DB will follow the
+			   fact that the remote port is also going through
+			   "down" state into "init"...
+			 */
+			__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,
+			"Updating neighbor_mtu on switch GUID 0x%016" PRIx64
+			" port 0 to:%u\n",
+			cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+			ib_port_info_get_neighbor_mtu(p_pi));
+
+		/* 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;
+			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.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 its
+	   is_new field is set.
+	 */
+	if ((p_mgr->p_subn->first_time_master_sweep == TRUE || p_port->is_new)
+	    && !p_mgr->p_subn->opt.no_clients_rereg
+	    && (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG)) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Seting client rereg on %s, port %d\n",
+			p_port->p_node->print_desc, p_port->p_physp->port_num);
+		ib_port_info_set_client_rereg(p_pi, 1);
+		send_set = TRUE;
+	} 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.
+	 */
+	if (p_mgr->p_subn->first_time_master_sweep == TRUE)
+		send_set = TRUE;
+
+	if (send_set) {
+		p_mgr->send_set_reqs = TRUE;
+		status = osm_req_set(p_mgr->sm,
+				     osm_physp_get_dr_path_ptr(p_physp),
+				     payload,
+				     sizeof(payload),
+				     IB_MAD_ATTR_PORT_INFO,
+				     cl_hton32(osm_physp_get_port_num(p_physp)),
+				     CL_DISP_MSGID_NONE, &context);
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return send_set;
+}
+
+/**********************************************************************
+ 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;
+	boolean_t res = TRUE;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	/*
+	   Acquire our own port object.
+	 */
+	p_port =
+	    osm_get_port_by_guid(p_mgr->p_subn, p_mgr->p_subn->sm_port_guid);
+	if (!p_port) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0308: "
+			"Can't acquire SM's port object, GUID 0x%016" PRIx64
+			"\n", cl_ntoh64(p_mgr->p_subn->sm_port_guid));
+		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,
+		"Current base LID is %u\n", min_lid_ho);
+	/*
+	   Update subnet object.
+	 */
+	p_mgr->p_subn->master_sm_base_lid = cl_hton16(min_lid_ho);
+	p_mgr->p_subn->sm_base_lid = cl_hton16(min_lid_ho);
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
+		"Assigning SM's port 0x%016" PRIx64
+		"\n\t\t\t\tto LID range [%u,%u]\n",
+		cl_ntoh64(osm_port_get_guid(p_port)), min_lid_ho, max_lid_ho);
+
+	/*
+	   Set the PortInfo the Physical Port associated with this Port.
+	 */
+	__osm_lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp,
+				   cl_hton16(min_lid_ho));
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return 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);
+
+	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);
+
+	/* 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;
+	int lid_changed;
+
+	CL_ASSERT(p_mgr);
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
+
+	CL_ASSERT(p_mgr->p_subn->sm_port_guid);
+
+	/* 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,
+				"Skipping our own port 0x%016" PRIx64 "\n",
+				cl_ntoh64(port_guid));
+			continue;
+		}
+
+		/*
+		   get the port lid range - we need to send it on first active
+		   sweep or if there was a change (the result of
+		   __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,
+			"Assigned port 0x%016" PRIx64
+			", LID [%u,%u]\n", cl_ntoh64(port_guid),
+			min_lid_ho, max_lid_ho);
+
+		/* the proc returns the fact it sent a set port info */
+		if (__osm_lid_mgr_set_physp_pi
+		    (p_mgr, p_port, 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);
+}
diff --git a/opensm/osm_lin_fwd_rcv.c b/opensm/osm_lin_fwd_rcv.c
new file mode 100644
index 0000000..c3d8633
--- /dev/null
+++ b/opensm/osm_lin_fwd_rcv.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_lft_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_lft_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_smp_t *p_smp;
+	uint32_t block_num;
+	osm_switch_t *p_sw;
+	osm_lft_context_t *p_lft_context;
+	uint8_t *p_block;
+	ib_net64_t node_guid;
+	ib_api_status_t status;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_block = (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(sm->p_lock);
+	p_sw = osm_get_switch_by_guid(sm->p_subn, node_guid);
+
+	if (!p_sw) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0401: "
+			"LFT received for nonexistent node "
+			"0x%" PRIx64 "\n", cl_ntoh64(node_guid));
+	} else {
+		status = osm_switch_set_lft_block(p_sw, p_block, block_num);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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(sm->p_lock);
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_link_mgr.c b/opensm/osm_link_mgr.c
new file mode 100644
index 0000000..37e3e1b
--- /dev/null
+++ b/opensm/osm_link_mgr.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_link_mgr_t.
+ * This file implements the Link Manager object.
+ */
+
+#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_sm.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_link_mgr_set_physp_pi(osm_sm_t * sm,
+			    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(sm->p_log);
+
+	p_node = osm_physp_get_node_ptr(p_physp);
+
+	port_num = osm_physp_get_port_num(p_physp);
+
+	if (port_num == 0) {
+		/*
+		   CAs don't have a port 0, and for switch port 0,
+		   we need to check if this is enhanced or base port 0.
+		   For base port 0 the following parameters are not valid (p822, table 145).
+		 */
+		if (!p_node->sw) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: "
+				"Cannot find switch by guid: 0x%" PRIx64 "\n",
+				cl_ntoh64(p_node->node_info.node_guid));
+			goto Exit;
+		}
+
+		if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)
+		    == FALSE) {
+			/* This means the switch doesn't support enhanced port 0.
+			   Can skip it. */
+			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+				"Skipping port 0, GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
+			goto Exit;
+		}
+		esp0 = TRUE;
+	}
+
+	/*
+	   PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
+	 */
+
+	p_old_pi = &p_physp->port_info;
+
+	memset(payload, 0, IB_SMP_DATA_SIZE);
+	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));
+
+	/*
+	   Should never write back a value that is bigger then 3 in
+	   the PortPhysicalState field - so can not simply copy!
+
+	   Actually we want to write there:
+	   port physical state - no change,
+	   link down default state = polling
+	   port state - as requested.
+	 */
+	p_pi->state_info2 = 0x02;
+	ib_port_info_set_port_state(p_pi, port_state);
+
+	if (ib_port_info_get_link_down_def_state(p_pi) !=
+	    ib_port_info_get_link_down_def_state(p_old_pi))
+		send_set = TRUE;
+
+	/* didn't get PortInfo before */
+	if (!ib_port_info_get_port_state(p_old_pi))
+		send_set = TRUE;
+
+	/* we only change port fields if we do not change state */
+	if (port_state == IB_LINK_NO_CHANGE) {
+		/* The following fields are relevant only for CA port, router, or Enh. SP0 */
+		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
+		    port_num == 0) {
+			p_pi->m_key = sm->p_subn->opt.m_key;
+			if (memcmp(&p_pi->m_key, &p_old_pi->m_key,
+				   sizeof(p_pi->m_key)))
+				send_set = TRUE;
+
+			p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix;
+			if (memcmp(&p_pi->subnet_prefix,
+				   &p_old_pi->subnet_prefix,
+				   sizeof(p_pi->subnet_prefix)))
+				send_set = TRUE;
+
+			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 = sm->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 =
+			    sm->p_subn->opt.m_key_lease_period;
+			if (memcmp(&p_pi->m_key_lease_period,
+				   &p_old_pi->m_key_lease_period,
+				   sizeof(p_pi->m_key_lease_period)))
+				send_set = TRUE;
+
+			if (esp0 == FALSE)
+				p_pi->mkey_lmc = sm->p_subn->opt.lmc;
+			else {
+				if (sm->p_subn->opt.lmc_esp0)
+					p_pi->mkey_lmc = sm->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,
+						 sm->p_subn->opt.
+						 subnet_timeout);
+			if (ib_port_info_get_timeout(p_pi) !=
+			    ib_port_info_get_timeout(p_old_pi))
+				send_set = TRUE;
+		}
+
+		/*
+		   Several timeout mechanisms:
+		 */
+		p_remote_physp = osm_physp_get_remote(p_physp);
+		if (port_num != 0 && p_remote_physp) {
+			if (osm_node_get_type(osm_physp_get_node_ptr(p_physp))
+			    == IB_NODE_TYPE_ROUTER) {
+				ib_port_info_set_hoq_lifetime(p_pi,
+							      sm->p_subn->
+							      opt.
+							      leaf_head_of_queue_lifetime);
+			} else
+			    if (osm_node_get_type
+				(osm_physp_get_node_ptr(p_physp)) ==
+				IB_NODE_TYPE_SWITCH) {
+				/* Is remote end CA or router (a leaf port) ? */
+				if (osm_node_get_type
+				    (osm_physp_get_node_ptr(p_remote_physp)) !=
+				    IB_NODE_TYPE_SWITCH) {
+					ib_port_info_set_hoq_lifetime(p_pi,
+								      sm->
+								      p_subn->
+								      opt.
+								      leaf_head_of_queue_lifetime);
+					ib_port_info_set_vl_stall_count(p_pi,
+									sm->
+									p_subn->
+									opt.
+									leaf_vl_stall_count);
+				} else {
+					ib_port_info_set_hoq_lifetime(p_pi,
+								      sm->
+								      p_subn->
+								      opt.
+								      head_of_queue_lifetime);
+					ib_port_info_set_vl_stall_count(p_pi,
+									sm->
+									p_subn->
+									opt.
+									vl_stall_count);
+				}
+			}
+			if (ib_port_info_get_hoq_lifetime(p_pi) !=
+			    ib_port_info_get_hoq_lifetime(p_old_pi) ||
+			    ib_port_info_get_vl_stall_count(p_pi) !=
+			    ib_port_info_get_vl_stall_count(p_old_pi))
+				send_set = TRUE;
+		}
+
+		ib_port_info_set_phy_and_overrun_err_thd(p_pi,
+							 sm->p_subn->opt.
+							 local_phy_errors_threshold,
+							 sm->p_subn->opt.
+							 overrun_errors_threshold);
+		if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold,
+			   sizeof(p_pi->error_threshold)))
+			send_set = TRUE;
+
+		/*
+		   Set the easy common parameters for all port types,
+		   then determine the neighbor MTU.
+		 */
+		p_pi->link_width_enabled = p_old_pi->link_width_supported;
+		if (memcmp(&p_pi->link_width_enabled,
+			   &p_old_pi->link_width_enabled,
+			   sizeof(p_pi->link_width_enabled)))
+			send_set = TRUE;
+
+		if (sm->p_subn->opt.force_link_speed &&
+		    (sm->p_subn->opt.force_link_speed != 15 ||
+		     ib_port_info_get_link_speed_enabled(p_pi) !=
+		     ib_port_info_get_link_speed_sup(p_pi))) {
+			ib_port_info_set_link_speed_enabled(p_pi,
+							    sm->p_subn->opt.
+							    force_link_speed);
+			if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed,
+				   sizeof(p_pi->link_speed)))
+				send_set = TRUE;
+		}
+
+		/* calc new op_vls and mtu */
+		op_vls =
+		    osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp);
+		mtu = osm_physp_calc_link_mtu(sm->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;
+
+		/* provide the vl_high_limit from the qos mgr */
+		if (sm->p_subn->opt.qos &&
+		    p_physp->vl_high_limit != p_old_pi->vl_high_limit) {
+			send_set = TRUE;
+			p_pi->vl_high_limit = p_physp->vl_high_limit;
+		}
+	}
+
+	if (port_state != IB_LINK_NO_CHANGE &&
+	    port_state != ib_port_info_get_port_state(p_old_pi)) {
+		send_set = TRUE;
+		if (port_state == IB_LINK_ACTIVE)
+			context.pi_context.active_transition = TRUE;
+		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.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 a switch external port (so it wasn't handled yet by
+	   osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE,
+	   which means the SM just became master, and it then needs to send at
+	   PortInfoSet to every port.
+	 */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num
+	    && sm->p_subn->first_time_master_sweep == TRUE)
+		send_set = TRUE;
+
+	if (send_set)
+		status = osm_req_set(sm, 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(sm->p_log);
+	return send_set;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_link_mgr_process_node(osm_sm_t * sm,
+			    IN osm_node_t * const p_node,
+			    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(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Node 0x%" PRIx64 " going to %s\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)),
+		ib_get_port_state_str(link_state));
+
+	/*
+	   Set the PortInfo for every Physical Port associated
+	   with this Port.  Start iterating with port 1, since the linkstate
+	   is not applicable to the management port on switches.
+	 */
+	num_physp = osm_node_get_num_physp(p_node);
+	for (i = 0; i < num_physp; i++) {
+		/*
+		   Don't bother doing anything if this Physical Port is not valid.
+		   or if the state of the port is already better then the
+		   specified state.
+		 */
+		p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i);
+		if (!p_physp)
+			continue;
+
+		current_state = osm_physp_get_port_state(p_physp);
+		if (current_state == IB_LINK_DOWN)
+			continue;
+
+		/*
+		   Normally we only send state update if state is lower
+		   then required state. However, we need to send update if
+		   no state change required.
+		 */
+		if (link_state != IB_LINK_NO_CHANGE &&
+		    link_state <= current_state)
+			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+				"Physical port %u already %s. Skipping\n",
+				p_physp->port_num,
+				ib_get_port_state_str(current_state));
+		else if (__osm_link_mgr_set_physp_pi(sm, p_physp, link_state))
+			signal = OSM_SIGNAL_DONE_PENDING;
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (signal);
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t osm_link_mgr_process(osm_sm_t * sm, IN const uint8_t link_state)
+{
+	cl_qmap_t *p_node_guid_tbl;
+	osm_node_t *p_node;
+	osm_signal_t signal = OSM_SIGNAL_DONE;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_node_guid_tbl = &sm->p_subn->node_guid_tbl;
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+
+	for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl);
+	     p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl);
+	     p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) {
+		if (__osm_link_mgr_process_node(sm, p_node, link_state) ==
+		    OSM_SIGNAL_DONE_PENDING)
+			signal = OSM_SIGNAL_DONE_PENDING;
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (signal);
+}
diff --git a/opensm/osm_log.c b/opensm/osm_log.c
new file mode 100644
index 0000000..88633ab
--- /dev/null
+++ b/opensm/osm_log.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 */
+
+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;
+#endif				/* WIN32 */
+
+	/* If this is a call to syslog - always print it */
+	if (!(verbosity & (OSM_LOG_SYS | p_log->level)))
+		return;
+
+	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) {
+		syslog(LOG_INFO, "%s\n", buffer);
+
+		/* SYSLOG should go to stdout too */
+		if (p_log->out_port != stdout) {
+			printf("%s\n", buffer);
+			fflush(stdout);
+		}
+#ifdef 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] 0x%02x -> %s",
+		    st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+		    pid, verbosity, buffer);
+#else
+	time_usecs = cl_get_time_stamp();
+	tim = time_usecs / 1000000;
+	usecs = time_usecs % 1000000;
+	localtime_r(&tim, &result);
+	pid = pthread_self();
+_retry:
+	ret =
+	    fprintf(p_log->out_port,
+		    "%s %02d %02d:%02d:%02d %06d [%04X] 0x%02x -> %s",
+		    (result.tm_mon <
+		     12 ? month_str[result.tm_mon] : "???"),
+		    result.tm_mday, result.tm_hour, result.tm_min,
+		    result.tm_sec, usecs, pid, verbosity, buffer);
+#endif
+
+	/*  flush log */
+	if (ret > 0 &&
+	    (p_log->flush || (verbosity & (OSM_LOG_ERROR | OSM_LOG_SYS)))
+	    && fflush(p_log->out_port) < 0)
+		ret = -1;
+
+	if (ret >= 0) {
+		log_exit_count = 0;
+		p_log->count += ret;
+	} else if (log_exit_count < 3) {
+		log_exit_count++;
+		if (errno == ENOSPC && p_log->max_size) {
+			fprintf(stderr,
+				"osm_log: write failed: %s. Truncating log file.\n",
+				strerror(errno));
+			truncate_log_file(p_log);
+			goto _retry;
+		}
+		fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno));
+	}
+
+	cl_spinlock_release(&p_log->lock);
+}
+
+void osm_log_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);
+	}
+}
+
+void osm_log_msg_box(IN osm_log_t * log, osm_log_level_t level,
+		     const char *func_name, const char *msg)
+{
+#define MSG_BOX_LENGTH 66
+	char buf[MSG_BOX_LENGTH + 1];
+	int i, n;
+
+	if (!osm_log_is_active(log, level))
+		return;
+
+	n = (MSG_BOX_LENGTH - strlen(msg)) / 2 - 1;
+	if (n < 0)
+		n = 0;
+	for (i = 0; i < n; i++)
+		sprintf(buf + i, "*");
+	n += snprintf(buf + n, sizeof(buf) - n, " %s ", msg);
+	for (i = n; i < MSG_BOX_LENGTH; i++)
+		buf[i] = '*';
+	buf[i] = '\0';
+
+	osm_log(log, level, "%s:\n\n\n"
+		"*********************************************"
+		"*********************\n%s\n"
+		"*********************************************"
+		"*********************\n\n\n", func_name, buf);
+}
+
+boolean_t osm_is_debug(void)
+{
+#if defined( _DEBUG_ )
+	return TRUE;
+#else
+	return FALSE;
+#endif				/* defined( _DEBUG_ ) */
+}
+
+static int open_out_port(IN osm_log_t * p_log)
+{
+	struct stat st;
+
+	if (p_log->accum_log_file)
+		p_log->out_port = fopen(p_log->log_file_name, "a+");
+	else
+		p_log->out_port = fopen(p_log->log_file_name, "w+");
+
+	if (!p_log->out_port) {
+		syslog(LOG_CRIT, "Cannot open file \'%s\' for %s: %s\n",
+		       p_log->log_file_name,
+		       p_log->accum_log_file ? "appending" : "writing",
+		       strerror(errno));
+		fprintf(stderr, "Cannot open file \'%s\': %s\n",
+			p_log->log_file_name, strerror(errno));
+		return -1;
+	}
+
+	if (fstat(fileno(p_log->out_port), &st) == 0)
+		p_log->count = st.st_size;
+
+	syslog(LOG_NOTICE, "%s log file opened\n", p_log->log_file_name);
+
+	if (p_log->daemon) {
+		dup2(fileno(p_log->out_port), 0);
+		dup2(fileno(p_log->out_port), 1);
+		dup2(fileno(p_log->out_port), 2);
+	}
+
+	return 0;
+}
+
+int osm_log_reopen_file(osm_log_t * p_log)
+{
+	int ret;
+
+	if (p_log->out_port == stdout || p_log->out_port == stderr)
+		return 0;
+	cl_spinlock_acquire(&p_log->lock);
+	fclose(p_log->out_port);
+	ret = open_out_port(p_log);
+	cl_spinlock_release(&p_log->lock);
+	return ret;
+}
+
+ib_api_status_t osm_log_init_v2(IN osm_log_t * 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)
+{
+	p_log->level = log_flags;
+	p_log->flush = flush;
+	p_log->count = 0;
+	p_log->max_size = max_size;
+	p_log->accum_log_file = accum_log_file;
+	p_log->log_file_name = (char *)log_file;
+
+	openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+	if (log_file == NULL || !strcmp(log_file, "-") ||
+	    !strcmp(log_file, "stdout"))
+		p_log->out_port = stdout;
+	else if (!strcmp(log_file, "stderr"))
+		p_log->out_port = stderr;
+	else if (open_out_port(p_log))
+		return IB_ERROR;
+
+	if (cl_spinlock_init(&p_log->lock) == CL_SUCCESS)
+		return IB_SUCCESS;
+	else
+		return IB_ERROR;
+}
+
+ib_api_status_t osm_log_init(IN osm_log_t * 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);
+}
diff --git a/opensm/osm_mad_pool.c b/opensm/osm_mad_pool.c
new file mode 100644
index 0000000..56a2a6d
--- /dev/null
+++ b/opensm/osm_mad_pool.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mad_pool_t.
+ * This object represents a pool of management datagram (MAD) objects.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_madw.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mad_pool_construct(IN osm_mad_pool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+
+	memset(p_pool, 0, sizeof(*p_pool));
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mad_pool_destroy(IN osm_mad_pool_t * const p_pool)
+{
+	CL_ASSERT(p_pool);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osm_mad_pool_init(IN osm_mad_pool_t * const p_pool)
+{
+	p_pool->mads_out = 0;
+
+	return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+
+	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
+	CL_ASSERT(total_size);
+
+	/*
+	   First, acquire a mad wrapper from the mad wrapper pool.
+	 */
+	p_madw = malloc(sizeof(*p_madw));
+	if (p_madw == NULL)
+		goto Exit;
+
+	osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);
+
+	/*
+	   Next, acquire a wire mad of the specified size.
+	 */
+	p_mad = osm_vendor_get(h_bind, total_size, &p_madw->vend_wrap);
+	if (p_mad == NULL) {
+		/* Don't leak wrappers! */
+		free(p_madw);
+		p_madw = NULL;
+		goto Exit;
+	}
+
+	cl_atomic_inc(&p_pool->mads_out);
+	/*
+	   Finally, attach the wire MAD to this wrapper.
+	 */
+	osm_madw_set_mad(p_madw, p_mad);
+
+Exit:
+	return p_madw;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t *osm_mad_pool_get_wrapper(IN osm_mad_pool_t * 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;
+
+	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
+	CL_ASSERT(total_size);
+	CL_ASSERT(p_mad);
+
+	/*
+	   First, acquire a mad wrapper from the mad wrapper pool.
+	 */
+	p_madw = malloc(sizeof(*p_madw));
+	if (p_madw == NULL)
+		goto Exit;
+
+	/*
+	   Finally, initialize the wrapper object.
+	 */
+	cl_atomic_inc(&p_pool->mads_out);
+	osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);
+	osm_madw_set_mad(p_madw, p_mad);
+
+Exit:
+	return (p_madw);
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t *osm_mad_pool_get_wrapper_raw(IN osm_mad_pool_t * const p_pool)
+{
+	osm_madw_t *p_madw;
+
+	p_madw = malloc(sizeof(*p_madw));
+	if (!p_madw)
+		return NULL;
+
+	osm_madw_init(p_madw, 0, 0, 0);
+	osm_madw_set_mad(p_madw, 0);
+	cl_atomic_inc(&p_pool->mads_out);
+
+	return (p_madw);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_put(IN osm_mad_pool_t * const p_pool, IN osm_madw_t * const p_madw)
+{
+	CL_ASSERT(p_madw);
+
+	/*
+	   First, return the wire mad to the pool
+	 */
+	if (p_madw->p_mad)
+		osm_vendor_put(p_madw->h_bind, &p_madw->vend_wrap);
+
+	/*
+	   Return the mad wrapper to the wrapper pool
+	 */
+	free(p_madw);
+	cl_atomic_dec(&p_pool->mads_out);
+}
diff --git a/opensm/osm_mcast_fwd_rcv.c b/opensm/osm_mcast_fwd_rcv.c
new file mode 100644
index 0000000..635c7da
--- /dev/null
+++ b/opensm/osm_mcast_fwd_rcv.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mft_rcv_t.
+ * This object represents the Multicast Forwarding Table Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mft_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_smp_t *p_smp;
+	uint32_t block_num;
+	uint8_t position;
+	osm_switch_t *p_sw;
+	osm_mft_context_t *p_mft_context;
+	uint16_t *p_block;
+	ib_net64_t node_guid;
+	ib_api_status_t status;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_block = (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;
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Setting MFT block %u, position %u, "
+		"Switch 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n",
+		block_num, position, cl_ntoh64(node_guid),
+		cl_ntoh64(p_smp->trans_id));
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+	p_sw = osm_get_switch_by_guid(sm->p_subn, node_guid);
+
+	if (!p_sw) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0801: "
+			"MFT received for nonexistent node "
+			"0x%016" PRIx64 "\n", cl_ntoh64(node_guid));
+	} else {
+		status = osm_switch_set_mft_block(p_sw, p_block,
+						  (uint16_t) block_num,
+						  position);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0802: "
+				"Setting MFT block failed (%s)"
+				"\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(sm->p_lock);
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_mcast_mgr.c b/opensm/osm_mcast_mgr.c
new file mode 100644
index 0000000..2f9cb5e
--- /dev/null
+++ b/opensm/osm_mcast_mgr.c
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcast_mgr_t.
+ * This file implements the Multicast Manager object.
+ */
+
+#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_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_sm.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>
+
+/**********************************************************************
+ **********************************************************************/
+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(osm_sm_t * sm, IN osm_mgrp_t * const p_mgrp)
+{
+	OSM_LOG_ENTER(sm->p_log);
+
+	if (p_mgrp->p_root)
+		__osm_mcast_mgr_purge_tree_node(p_mgrp->p_root);
+
+	p_mgrp->p_root = NULL;
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static float
+osm_mcast_mgr_compute_avg_hops(osm_sm_t * sm,
+			       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;
+	const osm_port_t *p_port;
+	const osm_mcm_port_t *p_mcm_port;
+	const cl_qmap_t *p_mcm_tbl;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_mcm_tbl = &p_mgrp->mcm_port_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_get_port_by_guid(sm->p_subn,
+					      ib_gid_get_guid(&p_mcm_port->
+							      port_gid));
+
+		if (!p_port) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A18: "
+				"No port object for port 0x%016" PRIx64 "\n",
+				cl_ntoh64(ib_gid_get_guid
+					  (&p_mcm_port->port_gid)));
+			continue;
+		}
+
+		hops += osm_switch_get_port_least_hops(p_sw, p_port);
+		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(sm->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_sm_t * sm,
+			       const osm_mgrp_t * const p_mgrp,
+			       const osm_switch_t * const p_sw)
+{
+	uint32_t max_hops = 0;
+	uint32_t hops = 0;
+	const osm_port_t *p_port;
+	const osm_mcm_port_t *p_mcm_port;
+	const cl_qmap_t *p_mcm_tbl;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_mcm_tbl = &p_mgrp->mcm_port_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_get_port_by_guid(sm->p_subn,
+					      ib_gid_get_guid(&p_mcm_port->
+							      port_gid));
+
+		if (!p_port) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A1A: "
+				"No port object for port 0x%016" PRIx64 "\n",
+				cl_ntoh64(ib_gid_get_guid
+					  (&p_mcm_port->port_gid)));
+			continue;
+		}
+
+		hops = osm_switch_get_port_least_hops(p_sw, p_port);
+		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(sm->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_sm_t * sm,
+							 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 */
+#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(sm->p_log);
+
+	p_sw_tbl = &sm->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(sm, p_mgrp, p_sw);
+		else
+			hops = osm_mcast_mgr_compute_max_hops(sm, p_mgrp, p_sw);
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Switch 0x%016" PRIx64 ", hops = %f\n",
+			cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), hops);
+
+		if (hops < best_hops) {
+			p_best_sw = p_sw;
+			best_hops = hops;
+		}
+	}
+
+	if (p_best_sw)
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Best switch is 0x%" PRIx64 ", hops = %f\n",
+			cl_ntoh64(osm_node_get_node_guid(p_best_sw->p_node)),
+			best_hops);
+	else
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"No multicast capable switches detected\n");
+
+	OSM_LOG_EXIT(sm->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_sm_t * sm,
+						      const osm_mgrp_t *
+						      const p_mgrp)
+{
+	const osm_switch_t *p_sw = NULL;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	   We always look for the best multicast tree root switch.
+	   Otherwise since we always start with a a single join
+	   the root will be always on the first switch attached to it.
+	   - Very bad ...
+	 */
+	p_sw = __osm_mcast_mgr_find_optimal_switch(sm, p_mgrp);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return ((osm_switch_t *) p_sw);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_mcast_mgr_set_tbl(osm_sm_t * sm, 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(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_sw);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(p_node);
+
+	p_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));
+
+	/*
+	   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)) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Writing MFT block 0x%X\n", block_id_ho);
+
+		block_id_ho = block_num + (position << 28);
+
+		status = osm_req_set(sm, 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(sm->p_log, OSM_LOG_ERROR, "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(sm->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_sm_t * sm,
+			  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;
+	boolean_t ignore_existing;
+	osm_mcast_work_obj_t *p_wobj;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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)) {
+		port_num =
+		    osm_switch_recommend_mcast_path(p_sw, p_wobj->p_port,
+						    mlid_ho, ignore_existing);
+
+		if (port_num == OSM_NO_PATH) {
+			/*
+			   This typically occurs if the switch does not support
+			   multicast and the multicast tree must branch at this
+			   switch.
+			 */
+			uint64_t node_guid_ho =
+			    cl_ntoh64(osm_node_get_node_guid(p_sw->p_node));
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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 %u\n", mlid_ho, node_guid_ho,
+				cl_ntoh16(osm_port_get_base_lid
+					  (p_wobj->p_port)));
+
+			__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(p_sw->p_node));
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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 %u\n", mlid_ho, node_guid_ho,
+				cl_ntoh16(osm_port_get_base_lid
+					  (p_wobj->p_port)));
+
+			__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(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_mcast_mgr_purge_list(osm_sm_t * sm, cl_qlist_t * const p_list)
+{
+	osm_mcast_work_obj_t *p_wobj;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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(sm->p_log, OSM_LOG_ERROR, "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(sm->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_sm_t * sm,
+						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(sm->p_log);
+
+	CL_ASSERT(p_sw);
+	CL_ASSERT(p_list);
+	CL_ASSERT(p_max_depth);
+
+	node_guid = osm_node_get_node_guid(p_sw->p_node);
+	node_guid_ho = cl_ntoh64(node_guid);
+	mlid_ho = cl_ntoh16(osm_mgrp_get_mlid(p_mgrp));
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Routing MLID 0x%X through switch 0x%" PRIx64
+		", %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 >= 64) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"Maximal hops number is reached for MLID 0x%x."
+			" Break processing.", mlid_ho);
+		__osm_mcast_mgr_purge_list(sm, p_list);
+		goto Exit;
+	}
+
+	if (depth > *p_max_depth) {
+		CL_ASSERT(depth == *p_max_depth + 1);
+		*p_max_depth = depth;
+	}
+
+	if (osm_switch_supports_mcast(p_sw) == FALSE) {
+		/*
+		   This switch doesn't do multicast.  Clean-up.
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A14: "
+			"Switch 0x%" PRIx64 " does not support multicast\n",
+			node_guid_ho);
+
+		/*
+		   Deallocate all the work objects on this branch of the tree.
+		 */
+		__osm_mcast_mgr_purge_list(sm, p_list);
+		goto Exit;
+	}
+
+	p_mtn = osm_mtree_node_new(p_sw);
+	if (p_mtn == NULL) {
+		/*
+		   We are unable to continue routing down this
+		   leg of the tree.  Clean-up.
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A15: "
+			"Insufficient memory to build multicast tree\n");
+
+		/*
+		   Deallocate all the work objects on this branch of the tree.
+		 */
+		__osm_mcast_mgr_purge_list(sm, p_list);
+		goto Exit;
+	}
+
+	max_children = osm_mtree_node_get_max_children(p_mtn);
+
+	CL_ASSERT(max_children > 1);
+
+	/*
+	   Prepare an empty list for each port in the switch.
+	   TO DO - this list array could probably be moved
+	   inside the switch element to save on malloc thrashing.
+	 */
+	list_array = malloc(sizeof(cl_qlist_t) * max_children);
+	if (list_array == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A16: "
+			"Unable to allocate list array\n");
+		__osm_mcast_mgr_purge_list(sm, 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(sm, 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) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Adding upstream port %u\n", upstream_port);
+
+		CL_ASSERT(upstream_port);
+		osm_mcast_tbl_set(p_tbl, mlid_ho, upstream_port);
+	}
+
+	/*
+	   For each port that was allocated some routes,
+	   recurse into this function to continue building the tree
+	   if the node on the other end of that port is another switch.
+	   Otherwise, the node is an endpoint, and we've found a leaf
+	   of the tree.  Mark leaves with our special pointer value.
+	 */
+
+	for (i = 0; i < max_children; i++) {
+		const osm_physp_t *p_physp;
+		const osm_physp_t *p_remote_physp;
+		osm_node_t *p_node;
+		const osm_node_t *p_remote_node;
+
+		p_port_list = &list_array[i];
+
+		count = cl_qlist_count(p_port_list);
+
+		/*
+		   There should be no children routed through the upstream port!
+		 */
+		CL_ASSERT((upstream_port == 0) || (i != upstream_port) ||
+			  ((i == upstream_port) && (count == 0)));
+
+		if (count == 0)
+			continue;	/* No routes down this port. */
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Routing %zu destinations via switch port %u\n",
+			count, i);
+
+		/*
+		   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 */
+			CL_ASSERT(count == 1);
+
+			p_wobj = (osm_mcast_work_obj_t *)
+			    cl_qlist_remove_head(p_port_list);
+			__osm_mcast_work_obj_delete(p_wobj);
+			continue;
+		}
+
+		p_node = p_sw->p_node;
+		p_remote_node = osm_node_get_remote_node(p_node, i, NULL);
+		if (!p_remote_node)
+			continue;
+
+		if (osm_node_get_type(p_remote_node) == IB_NODE_TYPE_SWITCH) {
+			/*
+			   Acquire a pointer to the remote switch then recurse.
+			 */
+			CL_ASSERT(p_remote_node->sw);
+
+			p_physp = osm_node_get_physp_ptr(p_node, i);
+			CL_ASSERT(p_physp);
+
+			p_remote_physp = osm_physp_get_remote(p_physp);
+			CL_ASSERT(p_remote_physp);
+
+			p_mtn->child_array[i] =
+			    __osm_mcast_mgr_branch(sm, 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));
+
+			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+				"Found leaf for port 0x%016" PRIx64
+				" on switch port %u\n",
+				cl_ntoh64(osm_port_get_guid(p_wobj->p_port)),
+				i);
+
+			__osm_mcast_work_obj_delete(p_wobj);
+		}
+	}
+
+	free(list_array);
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (p_mtn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mcast_mgr_build_spanning_tree(osm_sm_t * sm, osm_mgrp_t * const p_mgrp)
+{
+	const cl_qmap_t *p_mcm_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(sm->p_log);
+
+	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(sm, p_mgrp);
+
+	p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+	num_ports = cl_qmap_count(p_mcm_tbl);
+	if (num_ports == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"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(sm, p_mgrp);
+	if (p_sw == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A08: "
+			"Unable to locate a suitable switch for group 0x%X\n",
+			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_get_port_by_guid(sm->p_subn,
+					      ib_gid_get_guid(&p_mcm_port->
+							      port_gid));
+		if (!p_port) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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(sm->p_log, OSM_LOG_ERROR, "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(sm, p_mgrp, p_sw,
+						&port_list, 0, 0, &max_depth);
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Configured MLID 0x%X for %u ports, max tree depth = %u\n",
+		cl_ntoh16(osm_mgrp_get_mlid(p_mgrp)), count, max_depth);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+#if 0
+/* unused */
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_set_table(osm_sm_t * sm,
+			IN const osm_mgrp_t * 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(sm->p_log);
+
+	mlid_ho = cl_ntoh16(osm_mgrp_get_mlid(p_mgrp));
+	p_sw = osm_mtree_node_get_switch_ptr(p_mtn);
+
+	CL_ASSERT(p_sw);
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Configuring MLID 0x%X on switch 0x%" PRIx64 "\n",
+		mlid_ho, osm_node_get_node_guid(p_sw->p_node));
+
+	/*
+	   For every child of this tree node, set the corresponding
+	   bit in the switch's mcast table.
+	 */
+	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
+	max_children = osm_mtree_node_get_max_children(p_mtn);
+
+	CL_ASSERT(max_children <= osm_switch_get_num_ports(p_sw));
+
+	osm_mcast_tbl_clear_mlid(p_tbl, mlid_ho);
+
+	for (i = 0; i < max_children; i++) {
+		p_child_mtn = osm_mtree_node_get_child(p_mtn, i);
+		if (p_child_mtn == NULL)
+			continue;
+
+		osm_mcast_tbl_set(p_tbl, mlid_ho, i);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_mcast_mgr_clear(osm_sm_t * sm, 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(sm->p_log);
+
+	/*
+	   Walk the switches and clear the routing entries for
+	   this MLID.
+	 */
+	p_sw_tbl = &sm->p_subn->sw_guid_tbl;
+	p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
+	while (p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl)) {
+		p_mcast_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
+		osm_mcast_tbl_clear_mlid(p_mcast_tbl, cl_ntoh16(p_mgrp->mlid));
+		p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+#if 0
+/* TO DO - make this real -- at least update spanning tree */
+/**********************************************************************
+   Lock must be held on entry.
+**********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_process_single(osm_sm_t * sm,
+			     IN ib_net16_t const mlid,
+			     IN ib_net64_t const port_guid,
+			     IN uint8_t const join_state)
+{
+	uint8_t port_num;
+	uint16_t mlid_ho;
+	ib_net64_t sw_guid;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_remote_physp;
+	osm_node_t *p_remote_node;
+	osm_mcast_tbl_t *p_mcast_tbl;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(mlid);
+	CL_ASSERT(port_guid);
+
+	mlid_ho = cl_ntoh16(mlid);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Attempting to add port 0x%" PRIx64 " to MLID 0x%X, "
+		"\n\t\t\t\tjoin state = 0x%X\n",
+		cl_ntoh64(port_guid), mlid_ho, join_state);
+
+	/*
+	   Acquire the Port object.
+	 */
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A01: "
+			"Unable to acquire port object for 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	p_physp = p_port->p_physp;
+	if (p_physp == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A05: "
+			"Unable to acquire phsyical port object for 0x%" PRIx64
+			"\n", cl_ntoh64(port_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	p_remote_physp = osm_physp_get_remote(p_physp);
+	if (p_remote_physp == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A11: "
+			"Unable to acquire remote phsyical port object "
+			"for 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	p_remote_node = osm_physp_get_node_ptr(p_remote_physp);
+
+	CL_ASSERT(p_remote_node);
+
+	sw_guid = osm_node_get_node_guid(p_remote_node);
+
+	if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A22: "
+			"Remote node not a switch node 0x%" PRIx64 "\n",
+			cl_ntoh64(sw_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if (!p_remote_node->sw) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A12: "
+			"No switch object 0x%" PRIx64 "\n", cl_ntoh64(sw_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if (osm_switch_is_in_mcast_tree(p_remote_node->sw, mlid_ho)) {
+		/*
+		   We're in luck. The switch attached to this port
+		   is already in the multicast group, so we can just
+		   add the specified port as a new leaf of the tree.
+		 */
+		if (join_state & (IB_JOIN_STATE_FULL | IB_JOIN_STATE_NON)) {
+			/*
+			   This node wants to receive multicast frames.
+			   Get the switch port number to which the new member port
+			   is attached, then configure this single mcast table.
+			 */
+			port_num = osm_physp_get_port_num(p_remote_physp);
+			CL_ASSERT(port_num);
+
+			p_mcast_tbl =
+			    osm_switch_get_mcast_tbl_ptr(p_remote_node->sw);
+			osm_mcast_tbl_set(p_mcast_tbl, mlid_ho, port_num);
+		} else {
+			if (join_state & IB_JOIN_STATE_SEND_ONLY)
+				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+					"Success.  Nothing to do for send"
+					"only member\n");
+			else {
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A13: "
+					"Unknown join state 0x%X\n",
+					join_state);
+				status = IB_ERROR;
+				goto Exit;
+			}
+		}
+	} else
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Unable to add port\n");
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+#endif
+
+/**********************************************************************
+   lock must already be held on entry
+**********************************************************************/
+static ib_api_status_t
+osm_mcast_mgr_process_tree(osm_sm_t * sm,
+			   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;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	mlid = osm_mgrp_get_mlid(p_mgrp);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"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(&sm->p_subn->sw_guid_tbl) == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"No switches in subnet. Nothing to do\n");
+		goto Exit;
+	}
+
+	/*
+	   Clear the multicast tables to start clean, then build
+	   the spanning tree which sets the mcast table bits for each
+	   port in the group.
+	 */
+	__osm_mcast_mgr_clear(sm, p_mgrp);
+
+	if (!p_mgrp->full_members)
+		goto Exit;
+
+	status = __osm_mcast_mgr_build_spanning_tree(sm, p_mgrp);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A17: "
+			"Unable to create spanning tree (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ Process the entire group.
+ NOTE : The lock should be held externally!
+ **********************************************************************/
+static ib_api_status_t
+mcast_mgr_process_mgrp(osm_sm_t * sm,
+		       IN osm_mgrp_t * const p_mgrp,
+		       IN osm_mcast_req_type_t req_type,
+		       IN ib_net64_t port_guid)
+{
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	status = osm_mcast_mgr_process_tree(sm, p_mgrp, req_type, port_guid);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A19: "
+			"Unable to create spanning tree (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+	p_mgrp->last_tree_id = p_mgrp->last_change_id;
+
+	/* remove MCGRP if it is marked for deletion */
+	if (p_mgrp->to_be_deleted) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Destroying mgrp with lid:0x%x\n",
+			cl_ntoh16(p_mgrp->mlid));
+		sm->p_subn->mgroups[cl_ntoh16(p_mgrp->mlid) - IB_LID_MCAST_START_HO] = NULL;
+		osm_mgrp_delete(p_mgrp);
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t osm_mcast_mgr_process(osm_sm_t * sm)
+{
+	osm_signal_t signal;
+	osm_switch_t *p_sw;
+	cl_qmap_t *p_sw_tbl;
+	cl_qlist_t *p_list = &sm->mgrp_list;
+	osm_mgrp_t *p_mgrp;
+	boolean_t pending_transactions = FALSE;
+	int i;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_sw_tbl = &sm->p_subn->sw_guid_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(sm->p_lock);
+
+	for (i = 0; i <= sm->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
+	     i++) {
+		/*
+		   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.
+		 */
+		p_mgrp = sm->p_subn->mgroups[i];
+		if (p_mgrp)
+			mcast_mgr_process_mgrp(sm, p_mgrp,
+					       OSM_MCAST_REQ_TYPE_SUBNET_CHANGE,
+					       0);
+	}
+
+	/*
+	   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(sm, p_sw);
+		if (signal == OSM_SIGNAL_DONE_PENDING)
+			pending_transactions = TRUE;
+		p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+	}
+
+	while (!cl_is_qlist_empty(p_list)) {
+		cl_list_item_t *p = cl_qlist_remove_head(p_list);
+		free(p);
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+
+	if (pending_transactions == TRUE)
+		return (OSM_SIGNAL_DONE_PENDING);
+	else
+		return (OSM_SIGNAL_DONE);
+}
+
+/**********************************************************************
+  This is the function that is invoked during idle time to handle the
+  process request for mcast groups where join/leave/delete was required.
+ **********************************************************************/
+osm_signal_t osm_mcast_mgr_process_mgroups(osm_sm_t * sm)
+{
+	cl_qlist_t *p_list = &sm->mgrp_list;
+	osm_switch_t *p_sw;
+	cl_qmap_t *p_sw_tbl;
+	osm_mgrp_t *p_mgrp;
+	ib_net16_t mlid;
+	osm_signal_t ret, signal = OSM_SIGNAL_DONE;
+	osm_mcast_mgr_ctxt_t *ctx;
+	osm_mcast_req_type_t req_type;
+	ib_net64_t port_guid;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/* we need a lock to make sure the p_mgrp is not change other ways */
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+
+	while (!cl_is_qlist_empty(p_list)) {
+		ctx = (osm_mcast_mgr_ctxt_t *) cl_qlist_remove_head(p_list);
+		req_type = ctx->req_type;
+		port_guid = ctx->port_guid;
+
+		/* nice copy no warning on size diff */
+		memcpy(&mlid, &ctx->mlid, sizeof(mlid));
+
+		/* we can destroy the context now */
+		free(ctx);
+
+		/* since we delayed the execution we prefer to pass the
+		   mlid as the mgrp identifier and then find it or abort */
+		p_mgrp = osm_get_mgrp_by_mlid(sm->p_subn, mlid);
+		if (!p_mgrp)
+			continue;
+
+		/* 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(sm->p_log, OSM_LOG_DEBUG,
+				"Skip processing mgrp with lid:0x%X change id:%u\n",
+				cl_ntoh16(mlid), p_mgrp->last_change_id);
+			continue;
+		}
+
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Processing mgrp with lid:0x%X change id:%u\n",
+			cl_ntoh16(mlid), p_mgrp->last_change_id);
+		mcast_mgr_process_mgrp(sm, p_mgrp, req_type, port_guid);
+	}
+
+	/*
+	   Walk the switches and download the tables for each.
+	 */
+	p_sw_tbl = &sm->p_subn->sw_guid_tbl;
+	p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
+	while (p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl)) {
+		ret = __osm_mcast_mgr_set_tbl(sm, p_sw);
+		if (ret == OSM_SIGNAL_DONE_PENDING)
+			signal = ret;
+		p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+	}
+
+	osm_dump_mcast_routes(sm->p_subn->p_osm);
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+	OSM_LOG_EXIT(sm->p_log);
+	return signal;
+}
diff --git a/opensm/osm_mcast_tbl.c b/opensm/osm_mcast_tbl.c
new file mode 100644
index 0000000..17fb69c
--- /dev/null
+++ b/opensm/osm_mcast_tbl.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcast_tbl_t.
+ * This object represents an multicast forwarding table.
+ * This object is part of the opensm family of objects.
+ */
+
+#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 - 1);
+
+	/*
+	   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 - 1 > 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 - 1 > 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);
+}
diff --git a/opensm/osm_mcm_info.c b/opensm/osm_mcm_info.c
new file mode 100644
index 0000000..0325a34
--- /dev/null
+++ b/opensm/osm_mcm_info.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <opensm/osm_mcm_info.h>
+
+/**********************************************************************
+ **********************************************************************/
+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));
+		p_mcm->mlid = mlid;
+	}
+
+	return (p_mcm);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mcm_info_delete(IN osm_mcm_info_t * const p_mcm)
+{
+	free(p_mcm);
+}
diff --git a/opensm/osm_mcm_port.c b/opensm/osm_mcm_port.c
new file mode 100644
index 0000000..b6b6149
--- /dev/null
+++ b/opensm/osm_mcm_port.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcm_port_t.
+ * This object represents the membership of a port in a multicast group.
+ * This object is part of the OpenSM family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mcm_port.h>
+
+/**********************************************************************
+ **********************************************************************/
+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) {
+		memset(p_mcm, 0, sizeof(*p_mcm));
+		p_mcm->port_gid = *p_port_gid;
+		p_mcm->scope_state = scope_state;
+		p_mcm->proxy_join = proxy_join;
+	}
+
+	return (p_mcm);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mcm_port_delete(IN osm_mcm_port_t * const p_mcm)
+{
+	CL_ASSERT(p_mcm);
+	free(p_mcm);
+}
diff --git a/opensm/osm_mtree.c b/opensm/osm_mtree.c
new file mode 100644
index 0000000..3832e7d
--- /dev/null
+++ b/opensm/osm_mtree.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mtree_node_t.
+ * This file implements the Multicast Tree object.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mtree.h>
+
+/**********************************************************************
+ **********************************************************************/
+static 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);
+
+	memset(p_mtn, 0, sizeof(*p_mtn));
+
+	p_mtn->p_sw = (osm_switch_t *) p_sw;
+	p_mtn->max_children = p_sw->num_ports;
+
+	for (i = 0; i < p_mtn->max_children; i++)
+		p_mtn->child_array[i] = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 *) * (p_sw->num_ports - 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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+#if 0
+static 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]);
+		}
+	}
+}
+#endif
diff --git a/opensm/osm_multicast.c b/opensm/osm_multicast.c
new file mode 100644
index 0000000..350fd22
--- /dev/null
+++ b/opensm/osm_multicast.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of multicast functions.
+ */
+
+#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>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mgrp_delete(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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+		return NULL;
+
+	memset(p_mgrp, 0, sizeof(*p_mgrp));
+	cl_qmap_init(&p_mgrp->mcm_port_tbl);
+	p_mgrp->mlid = mlid;
+	p_mgrp->last_change_id = 0;
+	p_mgrp->last_tree_id = 0;
+	p_mgrp->to_be_deleted = FALSE;
+
+	return p_mgrp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void mgrp_send_notice(osm_subn_t *subn, osm_log_t *log,
+			     osm_mgrp_t *mgrp, unsigned num)
+{
+	ib_mad_notice_attr_t notice;
+	ib_api_status_t status;
+
+	notice.generic_type = 0x83;	/* generic SubnMgt type */
+	ib_notice_set_prod_type_ho(&notice, 4);	/* A Class Manager generator */
+	notice.g_or_v.generic.trap_num = CL_HTON16(num);
+	/* The sm_base_lid is saved in network order already. */
+	notice.issuer_lid = subn->sm_base_lid;
+	/* following o14-12.1.11 and table 120 p726 */
+	/* we need to provide the MGID */
+	memcpy(&notice.data_details.ntc_64_67.gid,
+	       &mgrp->mcmember_rec.mgid, sizeof(ib_gid_t));
+
+	/* According to page 653 - the issuer gid in this case of trap
+	   is the SM gid, since the SM is the initiator of this trap. */
+	notice.issuer_gid.unicast.prefix = subn->opt.subnet_prefix;
+	notice.issuer_gid.unicast.interface_id = subn->sm_port_guid;
+
+	if ((status = osm_report_notice(log, subn, &notice)))
+		OSM_LOG(log, OSM_LOG_ERROR, "ERR 7601: "
+			"Error sending trap reports (%s)\n",
+			ib_get_err_str(status));
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t *osm_mgrp_add_port(IN osm_subn_t *subn, osm_log_t *log,
+				  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 = 0;
+	uint8_t prev_scope;
+
+	p_mcm_port = osm_mcm_port_new(p_port_gid, join_state, proxy_join);
+	if (!p_mcm_port)
+		return NULL;
+
+	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++;
+	}
+
+	if ((join_state & IB_JOIN_STATE_FULL) &&
+	    !(prev_join_state & IB_JOIN_STATE_FULL) &&
+	    (++p_mgrp->full_members == 1)) {
+		mgrp_send_notice(subn, log, p_mgrp, 66);
+		p_mgrp->to_be_deleted = 0;
+	}
+
+	return (p_mcm_port);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_mgrp_remove_port(osm_subn_t *subn, osm_log_t *log, osm_mgrp_t *mgrp,
+			 osm_mcm_port_t *mcm, uint8_t join_state)
+{
+	int ret;
+	uint8_t port_join_state;
+	uint8_t new_join_state;
+
+	/*
+	 * according to the same o15-0.1.14 we get the stored
+	 * JoinState and the request JoinState and they must be
+	 * opposite to leave - otherwise just update it
+	 */
+	port_join_state = mcm->scope_state & 0x0F;
+	new_join_state = port_join_state & ~join_state;
+
+	if (new_join_state) {
+		mcm->scope_state = new_join_state | (mcm->scope_state & 0xf0);
+		OSM_LOG(log, OSM_LOG_DEBUG,
+			"updating port 0x%" PRIx64 " JoinState 0x%x -> 0x%x\n",
+			cl_ntoh64(mcm->port_gid.unicast.interface_id),
+			port_join_state, new_join_state);
+		ret = 0;
+	} else {
+		cl_qmap_remove_item(&mgrp->mcm_port_tbl, &mcm->map_item);
+		OSM_LOG(log, OSM_LOG_DEBUG, "removing port 0x%" PRIx64 "\n",
+			cl_ntoh64(mcm->port_gid.unicast.interface_id));
+		osm_mcm_port_delete(mcm);
+		/* track the fact we modified the group */
+		mgrp->last_change_id++;
+		ret = 1;
+	}
+
+	/* no more full members so the group will be deleted after re-route
+	   but only if it is not a well known group */
+	if ((port_join_state & IB_JOIN_STATE_FULL) &&
+	    !(new_join_state & IB_JOIN_STATE_FULL) &&
+	    (--mgrp->full_members == 0)) {
+		mgrp_send_notice(subn, log, mgrp, 67);
+		if (!mgrp->well_known)
+			mgrp->to_be_deleted = 1;
+	}
+
+	return ret;
+}
+
+void osm_mgrp_delete_port(osm_subn_t *subn, osm_log_t *log, osm_mgrp_t *mgrp,
+			  ib_net64_t port_guid)
+{
+	cl_map_item_t *item = cl_qmap_get(&mgrp->mcm_port_tbl, port_guid);
+
+	if (item != cl_qmap_end(&mgrp->mcm_port_tbl))
+		osm_mgrp_remove_port(subn, log, mgrp, (osm_mcm_port_t *)item, 0xf);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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);
+}
diff --git a/opensm/osm_node.c b/opensm/osm_node.c
new file mode 100644
index 0000000..07371a2
--- /dev/null
+++ b/opensm/osm_node.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_node_t.
+ * This object represents an Infiniband Node.
+ * This object is part of the opensm family of objects.
+ */
+
+#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)
+{
+	ib_net64_t port_guid;
+	ib_smp_t *p_smp;
+	ib_node_info_t *p_ni;
+	uint8_t port_num;
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	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);
+
+	osm_physp_init(&p_node->physp_table[port_num],
+		       port_guid, port_num, p_node,
+		       osm_madw_get_bind_handle(p_madw),
+		       p_smp->hop_count, p_smp->initial_path);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void node_init_physp0(IN osm_node_t * const p_node,
+			     IN const osm_madw_t * const p_madw)
+{
+	ib_smp_t *p_smp;
+	ib_node_info_t *p_ni;
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
+
+	osm_physp_init(&p_node->physp_table[0],
+		       p_ni->port_guid, 0, 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;
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	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)
+		return NULL;
+
+	memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
+	p_node->node_info = *p_ni;
+	p_node->physp_tbl_size = size + 1;
+
+	/*
+	   Construct Physical Port objects owned by this Node.
+	   Then, initialize the Physical Port through with we
+	   discovered this port.
+	   For switches, all ports have the same GUID.
+	   For CAs and routers, each port has a different GUID, so we only
+	   know the GUID for the port that responded to our
+	   Get(NodeInfo).
+	 */
+	for (i = 0; i < p_node->physp_tbl_size; i++)
+		osm_physp_construct(&p_node->physp_table[i]);
+
+	osm_node_init_physp(p_node, p_madw);
+	if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
+		node_init_physp0(p_node, p_madw);
+	p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
+
+	return (p_node);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void osm_node_destroy(IN osm_node_t * p_node)
+{
+	uint16_t i;
+
+	/*
+	   Cleanup all physports
+	 */
+	for (i = 0; i < p_node->physp_tbl_size; i++)
+		osm_physp_destroy(&p_node->physp_table[i]);
+
+	/* cleanup printable node_desc field */
+	if (p_node->print_desc) {
+		free(p_node->print_desc);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_node_delete(IN OUT osm_node_t ** const p_node)
+{
+	CL_ASSERT(p_node && *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 (p_physp && 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 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 (!p_physp || !osm_physp_has_any_link(p_physp))
+		return (NULL);
+
+	p_remote_physp = osm_physp_get_remote(p_physp);
+	if (p_remote_port_num)
+		*p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
+
+	return (osm_physp_get_node_ptr(p_remote_physp));
+}
+
+/**********************************************************************
+ The lock must be held before calling this function.
+**********************************************************************/
+ib_net16_t
+osm_node_get_remote_base_lid(IN osm_node_t * 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 (p_physp) {
+		p_remote_physp = osm_physp_get_remote(p_physp);
+		return (osm_physp_get_base_lid(p_remote_physp));
+	}
+
+	return (0);
+}
diff --git a/opensm/osm_node_desc_rcv.c b/opensm/osm_node_desc_rcv.c
new file mode 100644
index 0000000..f6178b9
--- /dev/null
+++ b/opensm/osm_node_desc_rcv.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_nd_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nd_rcv_process_nd(IN osm_sm_t * sm,
+			IN osm_node_t * const p_node,
+			IN const ib_node_desc_t * const p_nd)
+{
+	char *tmp_desc;
+	char print_desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	memcpy(&p_node->node_desc.description, p_nd, sizeof(*p_nd));
+
+	/* also set up a printable version */
+	memcpy(print_desc, p_nd, sizeof(*p_nd));
+	print_desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+	tmp_desc = remap_node_name(sm->p_subn->p_osm->node_name_map,
+			cl_ntoh64(osm_node_get_node_guid(p_node)),
+			print_desc);
+
+	/* make a copy for this node to "own" */
+	if (p_node->print_desc)
+		free(p_node->print_desc);
+	p_node->print_desc = tmp_desc;
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Node 0x%" PRIx64 "\n\t\t\t\tDescription = %s\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_nd_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_node_desc_t *p_nd;
+	ib_smp_t *p_smp;
+	osm_node_t *p_node;
+	ib_net64_t node_guid;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	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(sm->p_lock);
+	p_node = osm_get_node_by_guid(sm->p_subn, node_guid);
+	if (!p_node) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0B01: "
+			"NodeDescription received for nonexistent node "
+			"0x%" PRIx64 "\n", cl_ntoh64(node_guid));
+	} else {
+		__osm_nd_rcv_process_nd(sm, p_node, p_nd);
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_node_info_rcv.c b/opensm/osm_node_info_rcv.c
new file mode 100644
index 0000000..4d3724c
--- /dev/null
+++ b/opensm/osm_node_info_rcv.c
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_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>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_ucast_mgr.h>
+
+static void
+report_duplicated_guid(IN osm_sm_t * sm,
+		       osm_physp_t * p_physp,
+		       osm_node_t * p_neighbor_node, const uint8_t port_num)
+{
+	osm_physp_t *p_old, *p_new;
+	osm_dr_path_t path;
+
+	p_old = p_physp->p_remote_physp;
+	p_new = osm_node_get_physp_ptr(p_neighbor_node, port_num);
+
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D01: "
+		"Found duplicated node.\n"
+		"Node 0x%" PRIx64 " port %u is reachable from remote node "
+		"0x%" PRIx64 " port %u and remote node 0x%" PRIx64 " port %u.\n"
+		"Paths are:\n",
+		cl_ntoh64(p_physp->p_node->node_info.node_guid),
+		p_physp->port_num,
+		cl_ntoh64(p_old->p_node->node_info.node_guid), p_old->port_num,
+		cl_ntoh64(p_new->p_node->node_info.node_guid), p_new->port_num);
+
+	osm_dump_dr_path(sm->p_log, osm_physp_get_dr_path_ptr(p_physp),
+			 OSM_LOG_ERROR);
+
+	path = *osm_physp_get_dr_path_ptr(p_new);
+	osm_dr_path_extend(&path, port_num);
+	osm_dump_dr_path(sm->p_log, &path, OSM_LOG_ERROR);
+
+	osm_log(sm->p_log, OSM_LOG_SYS,
+		"FATAL: duplicated guids or 12x lane reversal\n");
+}
+
+static void requery_dup_node_info(IN osm_sm_t * sm,
+				  osm_physp_t * p_physp, unsigned count)
+{
+	osm_madw_context_t context;
+	osm_dr_path_t path;
+	cl_status_t status;
+
+	path = *osm_physp_get_dr_path_ptr(p_physp->p_remote_physp);
+	osm_dr_path_extend(&path, p_physp->p_remote_physp->port_num);
+
+	context.ni_context.node_guid =
+	    p_physp->p_remote_physp->p_node->node_info.port_guid;
+	context.ni_context.port_num = p_physp->p_remote_physp->port_num;
+	context.ni_context.dup_node_guid = p_physp->p_node->node_info.node_guid;
+	context.ni_context.dup_port_num = p_physp->port_num;
+	context.ni_context.dup_count = count;
+
+	status = osm_req_get(sm, &path, IB_MAD_ATTR_NODE_INFO,
+			     0, CL_DISP_MSGID_NONE, &context);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D02: "
+			"Failure initiating NodeInfo request (%s)\n",
+			ib_get_err_str(status));
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_set_links(IN osm_sm_t * sm,
+		       osm_node_t * p_node,
+		       const uint8_t port_num,
+		       const osm_ni_context_t * const p_ni_context)
+{
+	osm_node_t *p_neighbor_node;
+	osm_physp_t *p_physp;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	   A special case exists in which the node we're trying to
+	   link is our own node.  In this case, the guid value in
+	   the ni_context will be zero.
+	 */
+	if (p_ni_context->node_guid == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Nothing to link for our own node 0x%" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+		goto _exit;
+	}
+
+	p_neighbor_node = osm_get_node_by_guid(sm->p_subn,
+					       p_ni_context->node_guid);
+	if (!p_neighbor_node) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D10: "
+			"Unexpected removal of neighbor node "
+			"0x%" PRIx64 "\n", cl_ntoh64(p_ni_context->node_guid));
+		goto _exit;
+	}
+
+	/* When setting the link, ports on both
+	   sides of the link should be initialized */
+	if (!osm_node_link_has_valid_ports(p_node, port_num,
+					   p_neighbor_node,
+					   p_ni_context->port_num)) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Link at node 0x%" PRIx64 ", port %u - no valid ports\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)), port_num);
+		CL_ASSERT(0);
+		goto _exit;
+	}
+
+	if (osm_node_link_exists(p_node, port_num,
+				 p_neighbor_node, p_ni_context->port_num)) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Link already exists\n");
+		goto _exit;
+	}
+
+	if (osm_node_has_any_link(p_node, port_num) &&
+	    sm->p_subn->force_heavy_sweep == FALSE &&
+	    (!p_ni_context->dup_count ||
+	     (p_ni_context->dup_node_guid == osm_node_get_node_guid(p_node) &&
+	      p_ni_context->dup_port_num == port_num))) {
+		/*
+		   Uh oh...
+		   This could be reconnected ports, but also duplicated GUID
+		   (2 nodes have the same guid) or a 12x link with lane reversal
+		   that is not configured correctly.
+		   We will try to recover by querying NodeInfo again.
+		   In order to catch even fast port moving to new location(s) and
+		   back we will count up to 5.
+		   Some crazy reconnections (newly created switch loop right before
+		   targeted CA) will not be catched this way. So in worst case -
+		   report GUID duplication and request new discovery.
+		   When switch node is targeted NodeInfo querying will be done in
+		   opposite order, this is much stronger check, unfortunately it is
+		   impossible with CAs.
+		 */
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		if (p_ni_context->dup_count > 5) {
+			report_duplicated_guid(sm, p_physp,
+					       p_neighbor_node,
+					       p_ni_context->port_num);
+			sm->p_subn->force_heavy_sweep = TRUE;
+		} else if (p_node->sw)
+			requery_dup_node_info(sm, p_physp->p_remote_physp,
+					      p_ni_context->dup_count + 1);
+		else
+			requery_dup_node_info(sm, p_physp,
+					      p_ni_context->dup_count + 1);
+	}
+
+	/*
+	   When there are only two nodes with exact same guids (connected back
+	   to back) - the previous check for duplicated guid will not catch
+	   them. But the link will be from the port to itself...
+	   Enhanced Port 0 is an exception to this
+	 */
+	if ((osm_node_get_node_guid(p_node) == p_ni_context->node_guid) &&
+	    (port_num == p_ni_context->port_num) &&
+	    port_num != 0 && cl_qmap_count(&sm->p_subn->sw_guid_tbl) == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Duplicate GUID found by link from a port to itself:"
+			"node 0x%" PRIx64 ", port number %u\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)), port_num);
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		osm_dump_dr_path(sm->p_log,
+				 osm_physp_get_dr_path_ptr(p_physp),
+				 OSM_LOG_VERBOSE);
+
+		if (sm->p_subn->opt.exit_on_fatal == TRUE) {
+			osm_log(sm->p_log, OSM_LOG_SYS,
+				"Errors on subnet. Duplicate GUID found "
+				"by link from a port to itself. "
+				"See verbose opensm.log for more details\n");
+			exit(1);
+		}
+	}
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Creating new link between:\n\t\t\t\tnode 0x%" PRIx64
+		", port number %u and\n\t\t\t\tnode 0x%" PRIx64
+		", port number %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)), port_num,
+		cl_ntoh64(p_ni_context->node_guid), p_ni_context->port_num);
+
+	if (sm->ucast_mgr.cache_valid)
+		osm_ucast_cache_check_new_link(&sm->ucast_mgr,
+					       p_node, port_num,
+					       p_neighbor_node,
+					       p_ni_context->port_num);
+
+	osm_node_link(p_node, port_num, p_neighbor_node,
+		      p_ni_context->port_num);
+
+_exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_node(IN osm_sm_t * sm,
+			      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(sm->p_log);
+
+	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);
+
+	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.light_sweep = FALSE;
+	context.pi_context.active_transition = FALSE;
+
+	status = osm_req_get(sm, 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(sm->p_log, OSM_LOG_ERROR, "ERR 0D02: "
+			"Failure initiating PortInfo request (%s)\n",
+			ib_get_err_str(status));
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+osm_req_get_node_desc(IN osm_sm_t * sm,
+			osm_physp_t *p_physp)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osm_madw_context_t context;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	context.nd_context.node_guid =
+		osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp));
+
+	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
+			     IB_MAD_ATTR_NODE_DESC,
+			     0, CL_DISP_MSGID_NONE, &context);
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D03: "
+			"Failure initiating NodeDescription request (%s)\n",
+			ib_get_err_str(status));
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_get_node_desc(IN osm_sm_t * sm,
+			   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;
+	uint8_t port_num;
+	osm_physp_t *p_physp = NULL;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_ni = (ib_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);
+
+	osm_req_get_node_desc(sm, p_physp);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_ca_or_router(IN osm_sm_t * sm,
+				      IN osm_node_t * const p_node,
+				      IN const osm_madw_t * const p_madw)
+{
+	OSM_LOG_ENTER(sm->p_log);
+
+	__osm_ni_rcv_process_new_node(sm, p_node, p_madw);
+
+	/*
+	   A node guid of 0 is the corner case that indicates
+	   we discovered our own node.  Initialize the subnet
+	   object with the SM's own port guid.
+	 */
+	if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0)
+		sm->p_subn->sm_port_guid = p_node->node_info.port_guid;
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_ca_or_router(IN osm_sm_t * sm,
+					   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;
+	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;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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);
+	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_get_port_by_guid(sm->p_subn, p_ni->port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Creating new port object with GUID 0x%" PRIx64 "\n",
+			cl_ntoh64(p_ni->port_guid));
+
+		osm_node_init_physp(p_node, p_madw);
+
+		p_port = osm_port_new(p_ni, p_node);
+		if (p_port == NULL) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D04: "
+				"Unable to create new port object\n");
+			goto Exit;
+		}
+
+		/*
+		   Add the new port object to the database.
+		 */
+		p_port_check =
+		    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
+						  p_ni->port_guid,
+						  &p_port->map_item);
+		if (p_port_check != p_port) {
+			/*
+			   We should never be here!
+			   Somehow, this port GUID already exists in the table.
+			 */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D12: "
+				"Port 0x%" PRIx64 " already in the database!\n",
+				cl_ntoh64(p_ni->port_guid));
+
+			osm_port_delete(&p_port);
+			goto Exit;
+		}
+
+		/* If we are a master, then this means the port is new on the subnet.
+		   Mark it as new - need to send trap 64 on these ports.
+		   The condition that we are master is true, since if we are in discovering
+		   state (meaning we woke up from standby or we are just initializing),
+		   then these ports may be new to us, but are not new on the subnet.
+		   If we are master, then the subnet as we know it is the updated one,
+		   and any new ports we encounter should cause trap 64. C14-72.1.1 */
+		if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
+			p_port->is_new = 1;
+
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+	} else {
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		/*
+		   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.light_sweep = FALSE;
+
+	status = osm_req_get(sm, 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(sm->p_log, OSM_LOG_ERROR, "ERR 0D13: "
+			"Failure initiating PortInfo request (%s)\n",
+			ib_get_err_str(status));
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ni_rcv_process_switch(IN osm_sm_t * sm,
+			    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 *path;
+	ib_smp_t *p_smp;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/* update DR path of already initialized switch port 0 */
+	path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));
+	osm_dr_path_init(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(sm, path, IB_MAD_ATTR_SWITCH_INFO,
+			     0, CL_DISP_MSGID_NONE, &context);
+	if (status != IB_SUCCESS)
+		/* continue despite error */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D06: "
+			"Failure initiating SwitchInfo request (%s)\n",
+			ib_get_err_str(status));
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_switch(IN osm_sm_t * sm,
+				     IN osm_node_t * const p_node,
+				     IN const osm_madw_t * const p_madw)
+{
+
+	ib_smp_t *p_smp;
+	ib_node_info_t *p_ni;
+	uint8_t port_num;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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);
+
+	if (!osm_node_get_physp_ptr(p_node, port_num)) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Creating physp for node GUID:0x%"
+			PRIx64 ", port %u\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)),
+			port_num);
+		osm_node_init_physp(p_node, p_madw);
+	}
+
+	/*
+	   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 (p_node->discovery_count == 1)
+		__osm_ni_rcv_process_switch(sm, p_node, p_madw);
+	else if (!p_node->sw || p_node->sw->discovery_count == 0) {
+		/* we don't have the SwitchInfo - retry to get it */
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Retry to get SwitchInfo on node GUID:0x%"
+			PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node)));
+		__osm_ni_rcv_process_switch(sm, p_node, p_madw);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_switch(IN osm_sm_t * sm,
+				IN osm_node_t * const p_node,
+				IN const osm_madw_t * const p_madw)
+{
+	OSM_LOG_ENTER(sm->p_log);
+
+	__osm_ni_rcv_process_switch(sm, p_node, p_madw);
+
+	/*
+	   A node guid of 0 is the corner case that indicates
+	   we discovered our own node.  Initialize the subnet
+	   object with the SM's own port guid.
+	 */
+	if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0)
+		sm->p_subn->sm_port_guid = p_node->node_info.port_guid;
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must NOT be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new(IN osm_sm_t * sm,
+			 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_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;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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(sm->p_log, p_smp, OSM_LOG_VERBOSE);
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Discovered new %s node,"
+		"\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n",
+		ib_get_node_type_str(p_ni->node_type),
+		cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id));
+
+	p_node = osm_node_new(p_madw);
+	if (p_node == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D07: "
+			"Unable to create new node object\n");
+		goto Exit;
+	}
+
+	/*
+	   Create a new port object to represent this node's physical
+	   ports in the port table.
+	 */
+	p_port = osm_port_new(p_ni, p_node);
+	if (p_port == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D14: "
+			"Unable to create new port object\n");
+		osm_node_delete(&p_node);
+		goto Exit;
+	}
+
+	/*
+	   Add the new port object to the database.
+	 */
+	p_port_check =
+	    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
+					  p_ni->port_guid, &p_port->map_item);
+	if (p_port_check != p_port) {
+		/*
+		   We should never be here!
+		   Somehow, this port GUID already exists in the table.
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D15: "
+			"Duplicate Port GUID 0x%" PRIx64
+			"! Found by the two directed routes:\n",
+			cl_ntoh64(p_ni->port_guid));
+		osm_dump_dr_path(sm->p_log,
+				 osm_physp_get_dr_path_ptr(p_port->p_physp),
+				 OSM_LOG_ERROR);
+		osm_dump_dr_path(sm->p_log,
+				 osm_physp_get_dr_path_ptr(p_port_check->
+							   p_physp),
+				 OSM_LOG_ERROR);
+		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.
+	   Mark it as new - need to send trap 64 on these ports.
+	   The condition that we are master is true, since if we are in discovering
+	   state (meaning we woke up from standby or we are just initializing),
+	   then these ports may be new to us, but are not new on the subnet.
+	   If we are master, then the subnet as we know it is the updated one,
+	   and any new ports we encounter should cause trap 64. C14-72.1.1 */
+	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
+		p_port->is_new = 1;
+
+	/* If there were RouterInfo or other router attribute,
+	   this would be elsewhere */
+	if (p_ni->node_type == IB_NODE_TYPE_ROUTER) {
+		if ((p_rtr = osm_router_new(p_port)) == NULL)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1A: "
+				"Unable to create new router object\n");
+		else {
+			p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl;
+			p_rtr_check =
+			    (osm_router_t *) cl_qmap_insert(p_rtr_guid_tbl,
+							    p_ni->port_guid,
+							    &p_rtr->map_item);
+			if (p_rtr_check != p_rtr)
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1B: "
+					"Unable to add port GUID:0x%016" PRIx64
+					" to router table\n",
+					cl_ntoh64(p_ni->port_guid));
+		}
+	}
+
+	p_node_check =
+	    (osm_node_t *) cl_qmap_insert(&sm->p_subn->node_guid_tbl,
+					  p_ni->node_guid, &p_node->map_item);
+	if (p_node_check != p_node) {
+		/*
+		   This node must have been inserted by another thread.
+		   This is unexpected, but is not an error.
+		   We can simply clean-up, since the other thread will
+		   see this processing through to completion.
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Discovery race detected at node 0x%" PRIx64 "\n",
+			cl_ntoh64(p_ni->node_guid));
+		osm_node_delete(&p_node);
+		p_node = p_node_check;
+		__osm_ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
+		goto Exit;
+	} else
+		__osm_ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
+
+	p_node->discovery_count++;
+	__osm_ni_rcv_get_node_desc(sm, p_node, p_madw);
+
+	switch (p_ni->node_type) {
+	case IB_NODE_TYPE_CA:
+	case IB_NODE_TYPE_ROUTER:
+		__osm_ni_rcv_process_new_ca_or_router(sm, p_node, p_madw);
+		break;
+	case IB_NODE_TYPE_SWITCH:
+		__osm_ni_rcv_process_new_switch(sm, p_node, p_madw);
+		break;
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: "
+			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
+			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
+		break;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing(IN osm_sm_t * sm,
+			      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(sm->p_log);
+
+	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_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Rediscovered %s node 0x%" PRIx64 " TID 0x%" PRIx64
+		", discovered %u times already\n",
+		ib_get_node_type_str(p_ni->node_type),
+		cl_ntoh64(p_ni->node_guid),
+		cl_ntoh64(p_smp->trans_id), p_node->discovery_count);
+
+	/*
+	   If we haven't already encountered this existing node
+	   on this particular sweep, then process further.
+	 */
+	p_node->discovery_count++;
+
+	switch (p_ni->node_type) {
+	case IB_NODE_TYPE_CA:
+	case IB_NODE_TYPE_ROUTER:
+		__osm_ni_rcv_process_existing_ca_or_router(sm, p_node,
+							   p_madw);
+		break;
+
+	case IB_NODE_TYPE_SWITCH:
+		__osm_ni_rcv_process_existing_switch(sm, p_node, p_madw);
+		break;
+
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D09: "
+			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
+			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
+		break;
+	}
+
+	__osm_ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_ni_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_node_info_t *p_ni;
+	ib_smp_t *p_smp;
+	osm_node_t *p_node;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_ni = (ib_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(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: "
+			"Got Zero Node GUID! Found on the directed route:\n");
+		osm_dump_smp_dr_path(sm->p_log, p_smp, OSM_LOG_ERROR);
+		goto Exit;
+	}
+
+	if (p_ni->port_guid == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D17: "
+			"Got Zero Port GUID! Found on the directed route:\n");
+		osm_dump_smp_dr_path(sm->p_log, p_smp, OSM_LOG_ERROR);
+		goto Exit;
+	}
+
+	/*
+	   Determine if this node has already been discovered,
+	   and process accordingly.
+	   During processing of this node, hold the shared lock.
+	 */
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+	p_node = osm_get_node_by_guid(sm->p_subn, p_ni->node_guid);
+
+	osm_dump_node_info(sm->p_log, p_ni, OSM_LOG_DEBUG);
+
+	if (!p_node)
+		__osm_ni_rcv_process_new(sm, p_madw);
+	else
+		__osm_ni_rcv_process_existing(sm, p_node, p_madw);
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_opensm.c b/opensm/osm_opensm.c
new file mode 100644
index 0000000..7de2e5b
--- /dev/null
+++ b/opensm/osm_opensm.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_opensm_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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>
+#include <opensm/osm_event_plugin.h>
+
+struct routing_engine_module {
+	const char *name;
+	int (*setup) (struct osm_routing_engine *, osm_opensm_t *);
+};
+
+extern int osm_ucast_minhop_setup(struct osm_routing_engine *, osm_opensm_t *);
+extern int osm_ucast_updn_setup(struct osm_routing_engine *, osm_opensm_t *);
+extern int osm_ucast_file_setup(struct osm_routing_engine *, osm_opensm_t *);
+extern int osm_ucast_ftree_setup(struct osm_routing_engine *, osm_opensm_t *);
+extern int osm_ucast_lash_setup(struct osm_routing_engine *, osm_opensm_t *);
+extern int osm_ucast_dor_setup(struct osm_routing_engine *, osm_opensm_t *);
+
+const static struct routing_engine_module routing_modules[] = {
+	{"minhop", osm_ucast_minhop_setup},
+	{"updn", osm_ucast_updn_setup},
+	{"file", osm_ucast_file_setup},
+	{"ftree", osm_ucast_ftree_setup},
+	{"lash", osm_ucast_lash_setup},
+	{"dor", osm_ucast_dor_setup},
+	{NULL, NULL}
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type)
+{
+	switch (type) {
+	case OSM_ROUTING_ENGINE_TYPE_NONE:
+		return "none";
+	case OSM_ROUTING_ENGINE_TYPE_MINHOP:
+		return "minhop";
+	case OSM_ROUTING_ENGINE_TYPE_UPDN:
+		return "updn";
+	case OSM_ROUTING_ENGINE_TYPE_FILE:
+		return "file";
+	case OSM_ROUTING_ENGINE_TYPE_FTREE:
+		return "ftree";
+	case OSM_ROUTING_ENGINE_TYPE_LASH:
+		return "lash";
+	case OSM_ROUTING_ENGINE_TYPE_DOR:
+		return "dor";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_routing_engine_type_t osm_routing_engine_type(IN const char *str)
+{
+	/* For legacy reasons, consider a NULL pointer and the string
+	 * "null" as the minhop routing engine.
+	 */
+	if (!str || !strcasecmp(str, "null")
+	    || !strcasecmp(str, "minhop"))
+		return OSM_ROUTING_ENGINE_TYPE_MINHOP;
+	else if (!strcasecmp(str, "none"))
+		return OSM_ROUTING_ENGINE_TYPE_NONE;
+	else if (!strcasecmp(str, "updn"))
+		return OSM_ROUTING_ENGINE_TYPE_UPDN;
+	else if (!strcasecmp(str, "file"))
+		return OSM_ROUTING_ENGINE_TYPE_FILE;
+	else if (!strcasecmp(str, "ftree"))
+		return OSM_ROUTING_ENGINE_TYPE_FTREE;
+	else if (!strcasecmp(str, "lash"))
+		return OSM_ROUTING_ENGINE_TYPE_LASH;
+	else if (!strcasecmp(str, "dor"))
+		return OSM_ROUTING_ENGINE_TYPE_DOR;
+	else
+		return OSM_ROUTING_ENGINE_TYPE_UNKNOWN;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void append_routing_engine(osm_opensm_t *osm,
+				  struct osm_routing_engine *routing_engine)
+{
+	struct osm_routing_engine *r;
+
+	routing_engine->next = NULL;
+
+	if (!osm->routing_engine_list) {
+		osm->routing_engine_list = routing_engine;
+		return;
+	}
+
+	r = osm->routing_engine_list;
+	while (r->next)
+		r = r->next;
+
+	r->next = routing_engine;
+}
+
+static void setup_routing_engine(osm_opensm_t *osm, const char *name)
+{
+	struct osm_routing_engine *re;
+	const struct routing_engine_module *m;
+
+	for (m = routing_modules; m->name && *m->name; m++) {
+		if (!strcmp(m->name, name)) {
+			re = malloc(sizeof(struct osm_routing_engine));
+			if (!re) {
+				OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
+					"memory allocation failed\n");
+				return;
+			}
+			memset(re, 0, sizeof(struct osm_routing_engine));
+
+			re->name = m->name;
+			if (m->setup(re, osm)) {
+				OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
+					"setup of routing"
+					" engine \'%s\' failed\n", name);
+				return;
+			}
+			OSM_LOG(&osm->log, OSM_LOG_DEBUG,
+				"\'%s\' routing engine set up\n", re->name);
+			append_routing_engine(osm, re);
+			return;
+		}
+	}
+
+	OSM_LOG(&osm->log, OSM_LOG_ERROR,
+		"cannot find or setup routing engine \'%s\'", name);
+}
+
+static void setup_routing_engines(osm_opensm_t *osm, const char *engine_names)
+{
+	char *name, *str, *p;
+
+	if (!engine_names || !*engine_names) {
+		setup_routing_engine(osm, "minhop");
+		return;
+	}
+
+	str = strdup(engine_names);
+	name = strtok_r(str, ", \t\n", &p);
+	while (name && *name) {
+		setup_routing_engine(osm, name);
+		name = strtok_r(NULL, ", \t\n", &p);
+	}
+	free(str);
+
+	if (!osm->routing_engine_list)
+		setup_routing_engine(osm, "minhop");
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_opensm_construct(IN osm_opensm_t * const p_osm)
+{
+	memset(p_osm, 0, sizeof(*p_osm));
+	p_osm->osm_version = OSM_VERSION;
+	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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void destroy_routing_engines(osm_opensm_t *osm)
+{
+	struct osm_routing_engine *r, *next;
+
+	next = osm->routing_engine_list;
+	while (next) {
+		r = next;
+		next = r->next;
+		if (r->delete)
+			r->delete(r->context);
+		free(r);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void destroy_plugins(osm_opensm_t *osm)
+{
+	osm_epi_plugin_t *p;
+	/* remove from the list, and destroy it */
+	while (!cl_is_qlist_empty(&osm->plugin_list)){
+		p = (osm_epi_plugin_t *)cl_qlist_remove_head(&osm->plugin_list);
+		/* plugin is responsible for freeing its own resources */
+		osm_epi_destroy(p);
+	}
+}
+
+void osm_opensm_destroy(IN osm_opensm_t * 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);
+
+#ifdef ENABLE_OSM_PERF_MGR
+	/* Shutdown the PerfMgr */
+	osm_perfmgr_shutdown(&p_osm->perfmgr);
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+	/* 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 */
+	destroy_plugins(p_osm);
+	destroy_routing_engines(p_osm);
+	osm_sa_destroy(&p_osm->sa);
+	osm_sm_destroy(&p_osm->sm);
+#ifdef ENABLE_OSM_PERF_MGR
+	osm_perfmgr_destroy(&p_osm->perfmgr);
+#endif				/* ENABLE_OSM_PERF_MGR */
+	osm_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);
+#ifdef HAVE_LIBPTHREAD
+	pthread_cond_destroy(&p_osm->stats.cond);
+	pthread_mutex_destroy(&p_osm->stats.mutex);
+#else
+	cl_event_destroy(&p_osm->stats.event);
+#endif
+	close_node_name_map(p_osm->node_name_map);
+
+	cl_plock_destroy(&p_osm->lock);
+
+	osm_log_destroy(&p_osm->log);
+}
+
+static void load_plugins(osm_opensm_t *osm, const char *plugin_names)
+{
+	osm_epi_plugin_t *epi;
+	char *p_names, *name, *p;
+
+	p_names = strdup(plugin_names);
+	name = strtok_r(p_names, " \t\n", &p);
+	while (name && *name) {
+		epi = osm_epi_construct(osm, name);
+		if (!epi)
+			osm_log(&osm->log, OSM_LOG_ERROR,
+				"cannot load plugin \'%s\'\n", name);
+		else
+			cl_qlist_insert_tail(&osm->plugin_list, &epi->list);
+		name = strtok_r(NULL, " \t\n", &p);
+	}
+	free(p_names);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_init(IN osm_opensm_t * 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);
+
+	if (p_opt->daemon)
+		p_osm->log.daemon = 1;
+
+	status = osm_log_init_v2(&p_osm->log, p_opt->force_log_flush,
+				 p_opt->log_flags, p_opt->log_file,
+				 p_opt->log_max_size, p_opt->accum_log_file);
+	if (status != IB_SUCCESS)
+		return (status);
+
+	/* 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",
+		p_osm->osm_version);
+	/* Write the OSM_VERSION to the SYS_LOG */
+	osm_log(&p_osm->log, OSM_LOG_SYS, "%s\n", p_osm->osm_version);	/* Format Waived */
+
+	OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "[\n");	/* Format Waived */
+
+	status = cl_plock_init(&p_osm->lock);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_init(&p_osm->stats.mutex, NULL);
+	pthread_cond_init(&p_osm->stats.cond, NULL);
+#else
+	status = cl_event_init(&p_osm->stats.event, FALSE);
+	if (status != IB_SUCCESS)
+		goto Exit;
+#endif
+
+	if (p_opt->single_thread) {
+		OSM_LOG(&p_osm->log, OSM_LOG_INFO,
+			"Forcing single threaded dispatcher\n");
+		status = cl_disp_init(&p_osm->disp, 1, "opensm");
+	} else {
+		/*
+		 * Normal behavior is to initialize the dispatcher with
+		 * one thread per CPU, as specified by a thread count of '0'.
+		 */
+		status = cl_disp_init(&p_osm->disp, 0, "opensm");
+	}
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	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);
+	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);
+	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;
+
+	cl_qlist_init(&p_osm->plugin_list);
+
+	if (p_opt->event_plugin_name)
+		load_plugins(p_osm, p_opt->event_plugin_name);
+
+#ifdef ENABLE_OSM_PERF_MGR
+	status = osm_perfmgr_init(&p_osm->perfmgr, p_osm, p_opt);
+	if (status != IB_SUCCESS)
+		goto Exit;
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+	setup_routing_engines(p_osm, p_opt->routing_engine_names);
+
+	p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_NONE;
+
+	p_osm->node_name_map = open_node_name_map(p_opt->node_name_map_name);
+
+Exit:
+	OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n");	/* Format Waived */
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_bind(IN osm_opensm_t * const p_osm, IN const ib_net64_t guid)
+{
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(&p_osm->log);
+
+	status = osm_sm_bind(&p_osm->sm, guid);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	status = osm_sa_bind(&p_osm->sa, guid);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+#ifdef ENABLE_OSM_PERF_MGR
+	status = osm_perfmgr_bind(&p_osm->perfmgr, guid);
+	if (status != IB_SUCCESS)
+		goto Exit;
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+Exit:
+	OSM_LOG_EXIT(&p_osm->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id,
+			     void *event_data)
+{
+	cl_list_item_t *item;
+
+	for (item = cl_qlist_head(&osm->plugin_list);
+	     item != cl_qlist_end(&osm->plugin_list);
+	     item = cl_qlist_next(item)) {
+		osm_epi_plugin_t *p = (osm_epi_plugin_t *)item;
+		if (p->impl->report)
+			p->impl->report(p->plugin_data, event_id, event_data);
+	}
+}
diff --git a/opensm/osm_perfmgr.c b/opensm/osm_perfmgr.c
new file mode 100644
index 0000000..f7da2dc
--- /dev/null
+++ b/opensm/osm_perfmgr.c
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2007 The Regents of the University of California.
+ * Copyright (c) 2007-2008 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_perfmgr_t.
+ * This object implements an IBA performance manager.
+ *
+ * Author:
+ *    Ira Weiny, LLNL
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#ifdef ENABLE_OSM_PERF_MGR
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <poll.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <float.h>
+#include <arpa/inet.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_thread.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_opensm.h>
+
+#define OSM_PERFMGR_INITIAL_TID_VALUE 0xcafe
+
+#if ENABLE_OSM_PERF_MGR_PROFILE
+struct {
+	double fastest_us;
+	double slowest_us;
+	double avg_us;
+	uint64_t num;
+} perfmgr_mad_stats = {
+	fastest_us: DBL_MAX,
+	slowest_us: DBL_MIN,
+	avg_us: 0,
+	num: 0
+};
+
+/* diff must be something which can fit in a susecond_t */
+static inline void update_mad_stats(struct timeval *diff)
+{
+	double new = (diff->tv_sec * 1000000) + diff->tv_usec;
+	if (new < perfmgr_mad_stats.fastest_us)
+		perfmgr_mad_stats.fastest_us = new;
+	if (new > perfmgr_mad_stats.slowest_us)
+		perfmgr_mad_stats.slowest_us = new;
+
+	perfmgr_mad_stats.avg_us =
+	    ((perfmgr_mad_stats.avg_us * perfmgr_mad_stats.num) + new)
+	    / (perfmgr_mad_stats.num + 1);
+	perfmgr_mad_stats.num++;
+}
+
+static inline void perfmgr_clear_mad_stats(void)
+{
+	perfmgr_mad_stats.fastest_us = DBL_MAX;
+	perfmgr_mad_stats.slowest_us = DBL_MIN;
+	perfmgr_mad_stats.avg_us = 0;
+	perfmgr_mad_stats.num = 0;
+}
+
+/* after and diff can be the same struct */
+static inline void diff_time(struct timeval *before,
+			     struct timeval *after, struct timeval *diff)
+{
+	struct timeval tmp = *after;
+	if (tmp.tv_usec < before->tv_usec) {
+		tmp.tv_sec--;
+		tmp.tv_usec += 1000000;
+	}
+	diff->tv_sec = tmp.tv_sec - before->tv_sec;
+	diff->tv_usec = tmp.tv_usec - before->tv_usec;
+}
+
+#endif
+
+extern int wait_for_pending_transactions(osm_stats_t * stats);
+
+/**********************************************************************
+ * Internal helper functions.
+ **********************************************************************/
+static inline void __init_monitored_nodes(osm_perfmgr_t * pm)
+{
+	cl_qmap_init(&pm->monitored_map);
+	pm->remove_list = NULL;
+	cl_event_construct(&pm->sig_query);
+	cl_event_init(&pm->sig_query, FALSE);
+}
+
+static inline void
+__mark_for_removal(osm_perfmgr_t * pm, __monitored_node_t * node)
+{
+	if (pm->remove_list) {
+		node->next = pm->remove_list;
+		pm->remove_list = node;
+	} else {
+		node->next = NULL;
+		pm->remove_list = node;
+	}
+}
+
+static inline void __remove_marked_nodes(osm_perfmgr_t * pm)
+{
+	while (pm->remove_list) {
+		__monitored_node_t *next = pm->remove_list->next;
+
+		cl_qmap_remove_item(&(pm->monitored_map),
+				    (cl_map_item_t *) (pm->remove_list));
+
+		if (pm->remove_list->name)
+			free(pm->remove_list->name);
+		free(pm->remove_list);
+		pm->remove_list = next;
+	}
+}
+
+static inline void __decrement_outstanding_queries(osm_perfmgr_t * pm)
+{
+	cl_atomic_dec(&(pm->outstanding_queries));
+	cl_event_signal(&(pm->sig_query));
+}
+
+/**********************************************************************
+ * Receive the MAD from the vendor layer and post it for processing by
+ * the dispatcher.
+ **********************************************************************/
+static void
+osm_perfmgr_mad_recv_callback(osm_madw_t * p_madw, void *bind_context,
+			      osm_madw_t * p_req_madw)
+{
+	osm_perfmgr_t *pm = (osm_perfmgr_t *) bind_context;
+
+	OSM_LOG_ENTER(pm->log);
+
+	osm_madw_copy_context(p_madw, p_req_madw);
+	osm_mad_pool_put(pm->mad_pool, p_req_madw);
+
+	__decrement_outstanding_queries(pm);
+
+	/* post this message for later processing. */
+	if (cl_disp_post(pm->pc_disp_h, OSM_MSG_MAD_PORT_COUNTERS,
+			 (void *)p_madw, NULL, NULL) != CL_SUCCESS) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C01: "
+			"PerfMgr Dispatcher post failed\n");
+		osm_mad_pool_put(pm->mad_pool, p_madw);
+	}
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Process MAD send errors.
+ **********************************************************************/
+static void
+osm_perfmgr_mad_send_err_callback(void *bind_context, osm_madw_t * p_madw)
+{
+	osm_perfmgr_t *pm = (osm_perfmgr_t *) bind_context;
+	osm_madw_context_t *context = &(p_madw->context);
+	uint64_t node_guid = context->perfmgr_context.node_guid;
+	uint8_t port = context->perfmgr_context.port;
+	cl_map_item_t *p_node;
+	__monitored_node_t *p_mon_node;
+
+	OSM_LOG_ENTER(pm->log);
+
+	/* go ahead and get the monitored node struct to have the printable
+	 * name if needed in messages
+	 */
+	if ((p_node = cl_qmap_get(&(pm->monitored_map), node_guid)) ==
+	    cl_qmap_end(&(pm->monitored_map))) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C15: GUID 0x%016"
+			PRIx64 " not found in monitored map\n",
+			node_guid);
+		goto Exit;
+	}
+	p_mon_node = (__monitored_node_t *) p_node;
+
+	OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C02: %s (0x%" PRIx64
+		") port %u\n", p_mon_node->name, p_mon_node->guid, port);
+
+	if (pm->subn->opt.perfmgr_redir && p_madw->status == IB_TIMEOUT) {
+		/* First, find the node in the monitored map */
+		cl_plock_acquire(pm->lock);
+		/* Now, validate port number */
+		if (port > p_mon_node->redir_tbl_size) {
+			cl_plock_release(pm->lock);
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C16: "
+				"Invalid port num %u for %s (GUID 0x%016"
+				PRIx64 ") num ports %u\n", port, p_mon_node->name,
+				p_mon_node->guid, p_mon_node->redir_tbl_size);
+			goto Exit;
+		}
+		/* Clear redirection info */
+		p_mon_node->redir_port[port].redir_lid = 0;
+		p_mon_node->redir_port[port].redir_qp = 0;
+		cl_plock_release(pm->lock);
+	}
+
+Exit:
+	osm_mad_pool_put(pm->mad_pool, p_madw);
+
+	__decrement_outstanding_queries(pm);
+
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Bind the PerfMgr to the vendor layer for MAD sends/receives
+ **********************************************************************/
+ib_api_status_t
+osm_perfmgr_bind(osm_perfmgr_t * const pm, const ib_net64_t port_guid)
+{
+	osm_bind_info_t bind_info;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(pm->log);
+
+	if (pm->bind_handle != OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR,
+			"ERR 4C03: Multiple binds not allowed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	bind_info.port_guid = port_guid;
+	bind_info.mad_class = IB_MCLASS_PERF;
+	bind_info.class_version = 1;
+	bind_info.is_responder = FALSE;
+	bind_info.is_report_processor = FALSE;
+	bind_info.is_trap_processor = FALSE;
+	bind_info.recv_q_size = OSM_PM_DEFAULT_QP1_RCV_SIZE;
+	bind_info.send_q_size = OSM_PM_DEFAULT_QP1_SEND_SIZE;
+
+	OSM_LOG(pm->log, OSM_LOG_VERBOSE,
+		"Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	pm->bind_handle = osm_vendor_bind(pm->vendor,
+					  &bind_info,
+					  pm->mad_pool,
+					  osm_perfmgr_mad_recv_callback,
+					  osm_perfmgr_mad_send_err_callback,
+					  pm);
+
+	if (pm->bind_handle == OSM_BIND_INVALID_HANDLE) {
+		status = IB_ERROR;
+		OSM_LOG(pm->log, OSM_LOG_ERROR,
+			"ERR 4C04: Vendor specific bind failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(pm->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Unbind the PerfMgr from the vendor layer for MAD sends/receives
+ **********************************************************************/
+static void osm_perfmgr_mad_unbind(osm_perfmgr_t * const pm)
+{
+	OSM_LOG_ENTER(pm->log);
+	if (pm->bind_handle == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C05: No previous bind\n");
+		goto Exit;
+	}
+	osm_vendor_unbind(pm->bind_handle);
+Exit:
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Given a monitored node and a port, return the qp
+ **********************************************************************/
+static ib_net32_t get_qp(__monitored_node_t * mon_node, uint8_t port)
+{
+	ib_net32_t qp = cl_ntoh32(1);
+
+	if (mon_node && mon_node->redir_tbl_size &&
+	    port < mon_node->redir_tbl_size &&
+	    mon_node->redir_port[port].redir_lid &&
+	    mon_node->redir_port[port].redir_qp)
+		qp = mon_node->redir_port[port].redir_qp;
+
+	return qp;
+}
+
+/**********************************************************************
+ * Given a node, a port, and an optional monitored node,
+ * return the appropriate lid to query that port
+ **********************************************************************/
+static ib_net16_t
+get_lid(osm_node_t * p_node, uint8_t port, __monitored_node_t * mon_node)
+{
+	if (mon_node && mon_node->redir_tbl_size &&
+	    port < mon_node->redir_tbl_size &&
+	    mon_node->redir_port[port].redir_lid)
+		return mon_node->redir_port[port].redir_lid;
+
+	switch (p_node->node_info.node_type) {
+	case IB_NODE_TYPE_CA:
+	case IB_NODE_TYPE_ROUTER:
+		return osm_node_get_base_lid(p_node, port);
+	case IB_NODE_TYPE_SWITCH:
+		return osm_node_get_base_lid(p_node, 0);
+	default:
+		return 0;
+	}
+}
+
+/**********************************************************************
+ * Form and send the Port Counters MAD for a single port.
+ **********************************************************************/
+static ib_api_status_t
+osm_perfmgr_send_pc_mad(osm_perfmgr_t * perfmgr, ib_net16_t dest_lid,
+			ib_net32_t dest_qp, uint8_t port, uint8_t mad_method,
+			osm_madw_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	ib_port_counters_t *port_counter = NULL;
+	ib_perfmgt_mad_t *pm_mad = NULL;
+	osm_madw_t *p_madw = NULL;
+
+	OSM_LOG_ENTER(perfmgr->log);
+
+	p_madw =
+	    osm_mad_pool_get(perfmgr->mad_pool, perfmgr->bind_handle,
+			     MAD_BLOCK_SIZE, NULL);
+	if (p_madw == NULL)
+		return (IB_INSUFFICIENT_MEMORY);
+
+	pm_mad = osm_madw_get_perfmgt_mad_ptr(p_madw);
+
+	/* build the mad */
+	pm_mad->header.base_ver = 1;
+	pm_mad->header.mgmt_class = IB_MCLASS_PERF;
+	pm_mad->header.class_ver = 1;
+	pm_mad->header.method = mad_method;
+	pm_mad->header.status = 0;
+	pm_mad->header.class_spec = 0;
+	pm_mad->header.trans_id =
+	    cl_hton64((uint64_t) cl_atomic_inc(&(perfmgr->trans_id)));
+	pm_mad->header.attr_id = IB_MAD_ATTR_PORT_CNTRS;
+	pm_mad->header.resv = 0;
+	pm_mad->header.attr_mod = 0;
+
+	port_counter = (ib_port_counters_t *) & (pm_mad->data);
+	memset(port_counter, 0, sizeof(*port_counter));
+	port_counter->port_select = port;
+	port_counter->counter_select = 0xFFFF;
+
+	p_madw->mad_addr.dest_lid = dest_lid;
+	p_madw->mad_addr.addr_type.gsi.remote_qp = dest_qp;
+	p_madw->mad_addr.addr_type.gsi.remote_qkey =
+	    cl_hton32(IB_QP1_WELL_KNOWN_Q_KEY);
+	/* FIXME what about other partitions */
+	p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
+	p_madw->mad_addr.addr_type.gsi.service_level = 0;
+	p_madw->mad_addr.addr_type.gsi.global_route = FALSE;
+	p_madw->resp_expected = TRUE;
+
+	if (p_context)
+		p_madw->context = *p_context;
+
+	status = osm_vendor_send(perfmgr->bind_handle, p_madw, TRUE);
+
+	if (status == IB_SUCCESS) {
+		/* pause this thread if we have too many outstanding requests */
+		cl_atomic_inc(&(perfmgr->outstanding_queries));
+		if (perfmgr->outstanding_queries >
+		    perfmgr->max_outstanding_queries) {
+			perfmgr->sweep_state = PERFMGR_SWEEP_SUSPENDED;
+			cl_event_wait_on(&perfmgr->sig_query, EVENT_NO_TIMEOUT,
+					 TRUE);
+			perfmgr->sweep_state = PERFMGR_SWEEP_ACTIVE;
+		}
+	}
+
+	OSM_LOG_EXIT(perfmgr->log);
+	return (status);
+}
+
+/**********************************************************************
+ * sweep the node_guid_tbl and collect the node guids to be tracked
+ **********************************************************************/
+static void __collect_guids(cl_map_item_t * const p_map_item, void *context)
+{
+	osm_node_t *node = (osm_node_t *) p_map_item;
+	uint64_t node_guid = cl_ntoh64(node->node_info.node_guid);
+	osm_perfmgr_t *pm = (osm_perfmgr_t *) context;
+	__monitored_node_t *mon_node = NULL;
+	uint32_t size;
+
+	OSM_LOG_ENTER(pm->log);
+
+	if (cl_qmap_get(&(pm->monitored_map), node_guid)
+	    == cl_qmap_end(&(pm->monitored_map))) {
+		/* if not already in our map add it */
+		size = node->node_info.num_ports;
+		mon_node = malloc(sizeof(*mon_node) + sizeof(redir_t) * size);
+		if (!mon_node) {
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 4C06: "
+				"malloc failed: not handling node %s"
+				"(GUID 0x%" PRIx64 ")\n", node->print_desc, node_guid);
+			goto Exit;
+		}
+		memset(mon_node, 0, sizeof(*mon_node) + sizeof(redir_t) * size);
+		mon_node->guid = node_guid;
+		mon_node->name = strdup(node->print_desc);
+		mon_node->redir_tbl_size = size + 1;
+		cl_qmap_insert(&(pm->monitored_map), node_guid,
+			       (cl_map_item_t *) mon_node);
+	}
+
+Exit:
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * query the Port Counters of all the nodes in the subnet.
+ **********************************************************************/
+static void
+__osm_perfmgr_query_counters(cl_map_item_t * const p_map_item, void *context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint8_t port = 0, startport = 1;
+	osm_perfmgr_t *pm = (osm_perfmgr_t *) context;
+	osm_node_t *node = NULL;
+	__monitored_node_t *mon_node = (__monitored_node_t *) p_map_item;
+	osm_madw_context_t mad_context;
+	uint8_t num_ports = 0;
+	uint64_t node_guid = 0;
+	ib_net32_t remote_qp;
+
+	OSM_LOG_ENTER(pm->log);
+
+	cl_plock_acquire(pm->lock);
+	node = osm_get_node_by_guid(pm->subn, cl_hton64(mon_node->guid));
+	if (!node) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR,
+			"ERR 4C07: Node \"%s\" (guid 0x%" PRIx64
+			") no longer exists so removing from PerfMgr monitoring\n",
+			mon_node->name, mon_node->guid);
+		__mark_for_removal(pm, mon_node);
+		goto Exit;
+	}
+
+	num_ports = osm_node_get_num_physp(node);
+	node_guid = cl_ntoh64(node->node_info.node_guid);
+
+	/* make sure we have a database object ready to store this information */
+	if (perfmgr_db_create_entry(pm->db, node_guid, num_ports,
+				    node->print_desc) !=
+	    PERFMGR_EVENT_DB_SUCCESS) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR,
+			"ERR 4C08: DB create entry failed for 0x%"
+			PRIx64 " (%s) : %s\n", node_guid, node->print_desc,
+			strerror(errno));
+		goto Exit;
+	}
+
+	/* if switch, check for enhanced port 0 */
+	if (osm_node_get_type(node) == IB_NODE_TYPE_SWITCH &&
+	    node->sw &&
+	    ib_switch_info_is_enhanced_port0(&node->sw->switch_info))
+		startport = 0;
+
+	/* issue the query for each port */
+	for (port = startport; port < num_ports; port++) {
+		ib_net16_t lid;
+
+		if (!osm_node_get_physp_ptr(node, port))
+			continue;
+
+		lid = get_lid(node, port, mon_node);
+		if (lid == 0) {
+			OSM_LOG(pm->log, OSM_LOG_DEBUG, "WARN: node 0x%" PRIx64
+				" port %d (%s): port out of range, skipping\n",
+				cl_ntoh64(node->node_info.node_guid), port,
+				node->print_desc);
+			continue;
+		}
+
+		remote_qp = get_qp(mon_node, port);
+
+		mad_context.perfmgr_context.node_guid = node_guid;
+		mad_context.perfmgr_context.port = port;
+		mad_context.perfmgr_context.mad_method = IB_MAD_METHOD_GET;
+#if ENABLE_OSM_PERF_MGR_PROFILE
+		gettimeofday(&(mad_context.perfmgr_context.query_start), NULL);
+#endif
+		OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Getting stats for node 0x%"
+			PRIx64 " port %d (lid %u) (%s)\n", node_guid, port,
+			cl_ntoh16(lid), node->print_desc);
+		status =
+		    osm_perfmgr_send_pc_mad(pm, lid, remote_qp, port,
+					    IB_MAD_METHOD_GET, &mad_context);
+		if (status != IB_SUCCESS)
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C09: "
+				"Failed to issue port counter query for node 0x%"
+				PRIx64 " port %d (%s)\n",
+				node->node_info.node_guid, port,
+				node->print_desc);
+	}
+Exit:
+	cl_plock_release(pm->lock);
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Discovery stuff.
+ * Basically this code should not be here, but merged with main OpenSM
+ **********************************************************************/
+extern void osm_drop_mgr_process(IN osm_sm_t *sm);
+
+static int sweep_hop_1(osm_sm_t * sm)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osm_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;
+	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+	uint8_t num_ports;
+	osm_physp_t *p_ext_physp;
+
+	port_guid = sm->p_subn->sm_port_guid;
+
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 4C81: No SM port object\n");
+		return -1;
+	}
+
+	p_node = p_port->p_node;
+	port_num = ib_node_info_get_local_port_num(&p_node->node_info);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Probing hop 1 on local port %u\n", port_num);
+
+	p_physp = osm_node_get_physp_ptr(p_node, port_num);
+
+	CL_ASSERT(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:
+		memset(&context, 0, sizeof(context));
+		context.ni_context.node_guid = osm_node_get_node_guid(p_node);
+		context.ni_context.port_num = port_num;
+
+		path_array[1] = port_num;
+
+		osm_dr_path_init(&hop_1_path, h_bind, 1, path_array);
+		status = osm_req_get(sm, &hop_1_path,
+				     IB_MAD_ATTR_NODE_INFO, 0,
+				     CL_DISP_MSGID_NONE, &context);
+
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4C82: "
+				"Request for NodeInfo failed\n");
+		break;
+
+	case IB_NODE_TYPE_SWITCH:
+		/* Need to go over all the ports of the switch, and send a node_info
+		 * from them. This doesn't include the port 0 of the switch, which
+		 * hosts the SM.
+		 * Note: We'll send another switchInfo on port 0, since if no ports
+		 * are connected, we still want to get some response, and have the
+		 * subnet come up.
+		 */
+		num_ports = osm_node_get_num_physp(p_node);
+		for (port_num = 0; port_num < num_ports; port_num++) {
+			/* go through the port only if the port is not DOWN */
+			p_ext_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (!p_ext_physp || ib_port_info_get_port_state
+			    (&p_ext_physp->port_info) <= IB_LINK_DOWN)
+				continue;
+
+			memset(&context, 0, sizeof(context));
+			context.ni_context.node_guid =
+			    osm_node_get_node_guid(p_node);
+			context.ni_context.port_num = port_num;
+
+			path_array[1] = port_num;
+
+			osm_dr_path_init(&hop_1_path, h_bind, 1, path_array);
+			status = osm_req_get(sm, &hop_1_path,
+					     IB_MAD_ATTR_NODE_INFO, 0,
+					     CL_DISP_MSGID_NONE, &context);
+
+			if (status != IB_SUCCESS)
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4C82: "
+					"Request for NodeInfo failed\n");
+		}
+		break;
+
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 4C83: Unknown node type %d\n",
+			osm_node_get_type(p_node));
+	}
+
+	return (status);
+}
+
+static unsigned is_sm_port_down(osm_sm_t * const sm)
+{
+	ib_net64_t port_guid;
+	osm_port_t *p_port;
+
+	port_guid = sm->p_subn->sm_port_guid;
+	if (port_guid == 0)
+		return 1;
+
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		CL_PLOCK_RELEASE(sm->p_lock);
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4C85: "
+			"SM port with GUID:%016" PRIx64 " is unknown\n",
+			cl_ntoh64(port_guid));
+		return 1;
+	}
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	return osm_physp_get_port_state(p_port->p_physp) == IB_LINK_DOWN;
+}
+
+static int sweep_hop_0(osm_sm_t * const sm)
+{
+	ib_api_status_t status;
+	osm_dr_path_t dr_path;
+	osm_bind_handle_t h_bind;
+	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+	memset(path_array, 0, sizeof(path_array));
+
+	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
+	if (h_bind == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No bound ports.\n");
+		return -1;
+	}
+
+	osm_dr_path_init(&dr_path, h_bind, 0, path_array);
+	status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_NODE_INFO, 0,
+			     CL_DISP_MSGID_NONE, NULL);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 4C86: Request for NodeInfo failed\n");
+
+	return (status);
+}
+
+static void reset_node_count(cl_map_item_t * const p_map_item, void *cxt)
+{
+	osm_node_t *p_node = (osm_node_t *) p_map_item;
+	p_node->discovery_count = 0;
+}
+
+static void reset_port_count(cl_map_item_t * const p_map_item, void *cxt)
+{
+	osm_port_t *p_port = (osm_port_t *) p_map_item;
+	p_port->discovery_count = 0;
+}
+
+static void reset_switch_count(cl_map_item_t * const p_map_item, void *cxt)
+{
+	osm_switch_t *p_sw = (osm_switch_t *) p_map_item;
+	p_sw->discovery_count = 0;
+	p_sw->need_update = 0;
+}
+
+static int perfmgr_discovery(osm_opensm_t * osm)
+{
+	int ret;
+
+	CL_PLOCK_ACQUIRE(&osm->lock);
+	cl_qmap_apply_func(&osm->subn.node_guid_tbl, reset_node_count, NULL);
+	cl_qmap_apply_func(&osm->subn.port_guid_tbl, reset_port_count, NULL);
+	cl_qmap_apply_func(&osm->subn.sw_guid_tbl, reset_switch_count, NULL);
+	CL_PLOCK_RELEASE(&osm->lock);
+
+	osm->subn.in_sweep_hop_0 = TRUE;
+
+	ret = sweep_hop_0(&osm->sm);
+	if (ret)
+		goto _exit;
+
+	if (wait_for_pending_transactions(&osm->stats))
+		goto _exit;
+
+	if (is_sm_port_down(&osm->sm)) {
+		OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "SM port is down\n");
+		goto _drop;
+	}
+
+	osm->subn.in_sweep_hop_0 = FALSE;
+
+	ret = sweep_hop_1(&osm->sm);
+	if (ret)
+		goto _exit;
+
+	if (wait_for_pending_transactions(&osm->stats))
+		goto _exit;
+
+_drop:
+	osm_drop_mgr_process(&osm->sm);
+
+_exit:
+	return ret;
+}
+
+/**********************************************************************
+ * Main PerfMgr processor - query the performance counters.
+ **********************************************************************/
+void osm_perfmgr_process(osm_perfmgr_t * pm)
+{
+#if ENABLE_OSM_PERF_MGR_PROFILE
+	struct timeval before, after;
+#endif
+
+	if (pm->state != PERFMGR_STATE_ENABLED)
+		return;
+
+	if (pm->subn->sm_state == IB_SMINFO_STATE_STANDBY ||
+	    pm->subn->sm_state == IB_SMINFO_STATE_NOTACTIVE)
+		perfmgr_discovery(pm->subn->p_osm);
+
+#if ENABLE_OSM_PERF_MGR_PROFILE
+	gettimeofday(&before, NULL);
+#endif
+	pm->sweep_state = PERFMGR_SWEEP_ACTIVE;
+	/* With the global lock held collect the node guids */
+	/* FIXME we should be able to track SA notices
+	 * and not have to sweep the node_guid_tbl each pass
+	 */
+	OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Gathering PerfMgr stats\n");
+	cl_plock_acquire(pm->lock);
+	cl_qmap_apply_func(&(pm->subn->node_guid_tbl),
+			   __collect_guids, (void *)pm);
+	cl_plock_release(pm->lock);
+
+	/* then for each node query their counters */
+	cl_qmap_apply_func(&(pm->monitored_map),
+			   __osm_perfmgr_query_counters, (void *)pm);
+
+	/* Clean out any nodes found to be removed during the
+	 * sweep
+	 */
+	__remove_marked_nodes(pm);
+
+#if ENABLE_OSM_PERF_MGR_PROFILE
+	/* spin on outstanding queries */
+	while (pm->outstanding_queries > 0)
+		cl_event_wait_on(&pm->sig_sweep, 1000, TRUE);
+
+	gettimeofday(&after, NULL);
+	diff_time(&before, &after, &after);
+	osm_log(pm->log, OSM_LOG_INFO,
+		"PerfMgr total sweep time : %ld.%06ld s\n"
+		"        fastest mad      : %g us\n"
+		"        slowest mad      : %g us\n"
+		"        average mad      : %g us\n",
+		after.tv_sec, after.tv_usec,
+		perfmgr_mad_stats.fastest_us,
+		perfmgr_mad_stats.slowest_us, perfmgr_mad_stats.avg_us);
+	perfmgr_clear_mad_stats();
+#endif
+
+	pm->sweep_state = PERFMGR_SWEEP_SLEEP;
+}
+
+/**********************************************************************
+ * PerfMgr timer - loop continuously and signal SM to run PerfMgr
+ * processor.
+ **********************************************************************/
+static void perfmgr_sweep(void *arg)
+{
+	osm_perfmgr_t *pm = arg;
+
+	if (pm->state == PERFMGR_STATE_ENABLED)
+		osm_sm_signal(pm->sm, OSM_SIGNAL_PERFMGR_SWEEP);
+	cl_timer_start(&pm->sweep_timer, pm->sweep_time_s * 1000);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_perfmgr_shutdown(osm_perfmgr_t * const pm)
+{
+	OSM_LOG_ENTER(pm->log);
+	cl_timer_stop(&pm->sweep_timer);
+	osm_perfmgr_mad_unbind(pm);
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_perfmgr_destroy(osm_perfmgr_t * const pm)
+{
+	OSM_LOG_ENTER(pm->log);
+	perfmgr_db_destroy(pm->db);
+	cl_timer_destroy(&pm->sweep_timer);
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Detect if someone else on the network could have cleared the counters
+ * without us knowing.  This is easy to detect because the counters never wrap
+ * but are "sticky"
+ *
+ * The one time this will not work is if the port is getting errors fast enough
+ * to have the reading overtake the previous reading.  In this case counters
+ * will be missed.
+ **********************************************************************/
+static void
+osm_perfmgr_check_oob_clear(osm_perfmgr_t * pm, __monitored_node_t *mon_node,
+			    uint8_t port, perfmgr_db_err_reading_t * cr,
+			    perfmgr_db_data_cnt_reading_t * dc)
+{
+	perfmgr_db_err_reading_t prev_err;
+	perfmgr_db_data_cnt_reading_t prev_dc;
+
+	if (perfmgr_db_get_prev_err(pm->db, mon_node->guid, port, &prev_err)
+	    != PERFMGR_EVENT_DB_SUCCESS) {
+		OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Failed to find previous "
+			"error reading for %s (guid 0x%" PRIx64 ") port %u\n",
+			mon_node->name, mon_node->guid, port);
+		return;
+	}
+
+	if (cr->symbol_err_cnt < prev_err.symbol_err_cnt ||
+	    cr->link_err_recover < prev_err.link_err_recover ||
+	    cr->link_downed < prev_err.link_downed ||
+	    cr->rcv_err < prev_err.rcv_err ||
+	    cr->rcv_rem_phys_err < prev_err.rcv_rem_phys_err ||
+	    cr->rcv_switch_relay_err < prev_err.rcv_switch_relay_err ||
+	    cr->xmit_discards < prev_err.xmit_discards ||
+	    cr->xmit_constraint_err < prev_err.xmit_constraint_err ||
+	    cr->rcv_constraint_err < prev_err.rcv_constraint_err ||
+	    cr->link_integrity < prev_err.link_integrity ||
+	    cr->buffer_overrun < prev_err.buffer_overrun ||
+	    cr->vl15_dropped < prev_err.vl15_dropped) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 4C0A: "
+			"Detected an out of band error clear "
+			"on %s (0x%" PRIx64 ") port %u\n",
+			mon_node->name, mon_node->guid, port);
+		perfmgr_db_clear_prev_err(pm->db, mon_node->guid, port);
+	}
+
+	/* FIXME handle extended counters */
+	if (perfmgr_db_get_prev_dc(pm->db, mon_node->guid, port, &prev_dc)
+	    != PERFMGR_EVENT_DB_SUCCESS) {
+		OSM_LOG(pm->log, OSM_LOG_VERBOSE,
+			"Failed to find previous data count "
+			"reading for %s (0x%" PRIx64 ") port %u\n",
+			mon_node->name, mon_node->guid, port);
+		return;
+	}
+
+	if (dc->xmit_data < prev_dc.xmit_data ||
+	    dc->rcv_data < prev_dc.rcv_data ||
+	    dc->xmit_pkts < prev_dc.xmit_pkts ||
+	    dc->rcv_pkts < prev_dc.rcv_pkts) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR,
+			"PerfMgr: ERR 4C0B: Detected an out of band data counter "
+			"clear on node %s (0x%" PRIx64 ") port %u\n",
+			mon_node->name, mon_node->guid, port);
+		perfmgr_db_clear_prev_dc(pm->db, mon_node->guid, port);
+	}
+}
+
+/**********************************************************************
+ * Return 1 if the value is "close" to overflowing
+ **********************************************************************/
+static int counter_overflow_4(uint8_t val)
+{
+	return (val >= 10);
+}
+
+static int counter_overflow_8(uint8_t val)
+{
+	return (val >= (UINT8_MAX - (UINT8_MAX / 4)));
+}
+
+static int counter_overflow_16(ib_net16_t val)
+{
+	return (cl_ntoh16(val) >= (UINT16_MAX - (UINT16_MAX / 4)));
+}
+
+static int counter_overflow_32(ib_net32_t val)
+{
+	return (cl_ntoh32(val) >= (UINT32_MAX - (UINT32_MAX / 4)));
+}
+
+/**********************************************************************
+ * Check if the port counters have overflowed and if so issue a clear
+ * MAD to the port.
+ **********************************************************************/
+static void
+osm_perfmgr_check_overflow(osm_perfmgr_t * pm, __monitored_node_t *mon_node,
+			   uint8_t port, ib_port_counters_t * pc)
+{
+	osm_madw_context_t mad_context;
+	ib_api_status_t status;
+	ib_net32_t remote_qp;
+
+	OSM_LOG_ENTER(pm->log);
+
+	if (counter_overflow_16(pc->symbol_err_cnt) ||
+	    counter_overflow_8(pc->link_err_recover) ||
+	    counter_overflow_8(pc->link_downed) ||
+	    counter_overflow_16(pc->rcv_err) ||
+	    counter_overflow_16(pc->rcv_rem_phys_err) ||
+	    counter_overflow_16(pc->rcv_switch_relay_err) ||
+	    counter_overflow_16(pc->xmit_discards) ||
+	    counter_overflow_8(pc->xmit_constraint_err) ||
+	    counter_overflow_8(pc->rcv_constraint_err) ||
+	    counter_overflow_4(PC_LINK_INT(pc->link_int_buffer_overrun)) ||
+	    counter_overflow_4(PC_BUF_OVERRUN(pc->link_int_buffer_overrun)) ||
+	    counter_overflow_16(pc->vl15_dropped) ||
+	    counter_overflow_32(pc->xmit_data) ||
+	    counter_overflow_32(pc->rcv_data) ||
+	    counter_overflow_32(pc->xmit_pkts) ||
+	    counter_overflow_32(pc->rcv_pkts)) {
+		osm_node_t *p_node = NULL;
+		ib_net16_t lid = 0;
+
+		osm_log(pm->log, OSM_LOG_VERBOSE,
+			"PerfMgr: Counter overflow: %s (0x%" PRIx64
+			") port %d; clearing counters\n",
+			mon_node->name, mon_node->guid, port);
+
+		cl_plock_acquire(pm->lock);
+		p_node = osm_get_node_by_guid(pm->subn, cl_hton64(mon_node->guid));
+		lid = get_lid(p_node, port, mon_node);
+		cl_plock_release(pm->lock);
+		if (lid == 0) {
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 4C0C: "
+				"Failed to clear counters for %s (0x%"
+				PRIx64 ") port %d; failed to get lid\n",
+				mon_node->name, mon_node->guid, port);
+			goto Exit;
+		}
+
+		remote_qp = get_qp(NULL, port);
+
+		mad_context.perfmgr_context.node_guid = mon_node->guid;
+		mad_context.perfmgr_context.port = port;
+		mad_context.perfmgr_context.mad_method = IB_MAD_METHOD_SET;
+		/* clear port counters */
+		status =
+		    osm_perfmgr_send_pc_mad(pm, lid, remote_qp, port,
+					    IB_MAD_METHOD_SET, &mad_context);
+		if (status != IB_SUCCESS)
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 4C11: "
+				"Failed to send clear counters MAD for %s (0x%"
+				PRIx64 ") port %d\n",
+				mon_node->name, mon_node->guid, port);
+
+		perfmgr_db_clear_prev_dc(pm->db, mon_node->guid, port);
+	}
+
+Exit:
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Check values for logging of errors
+ **********************************************************************/
+static void
+osm_perfmgr_log_events(osm_perfmgr_t * pm, __monitored_node_t *mon_node, uint8_t port,
+		       perfmgr_db_err_reading_t * reading)
+{
+	perfmgr_db_err_reading_t prev_read;
+	time_t time_diff = 0;
+	perfmgr_db_err_t err =
+	    perfmgr_db_get_prev_err(pm->db, mon_node->guid, port, &prev_read);
+
+	if (err != PERFMGR_EVENT_DB_SUCCESS) {
+		OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Failed to find previous "
+			"reading for %s (0x%" PRIx64 ") port %u\n",
+			mon_node->name, mon_node->guid, port);
+		return;
+	}
+	time_diff = (reading->time - prev_read.time);
+
+	/* FIXME these events should be defineable by the user in a config
+	 * file somewhere. */
+	if (reading->symbol_err_cnt > prev_read.symbol_err_cnt)
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C0D: "
+			"Found %" PRIu64 " Symbol errors in %lu sec on %s (0x%"
+			PRIx64 ") port %u\n",
+			(reading->symbol_err_cnt - prev_read.symbol_err_cnt),
+			time_diff, mon_node->name, mon_node->guid, port);
+
+	if (reading->rcv_err > prev_read.rcv_err)
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C0E: "
+			"Found %" PRIu64
+			" Receive errors in %lu sec on %s (0x%" PRIx64
+			") port %u\n", (reading->rcv_err - prev_read.rcv_err),
+			time_diff, mon_node->name, mon_node->guid, port);
+
+	if (reading->xmit_discards > prev_read.xmit_discards)
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C0F: "
+			"Found %" PRIu64 " Xmit Discards in %lu sec on %s (0x%"
+			PRIx64 ") port %u\n",
+			(reading->xmit_discards - prev_read.xmit_discards),
+			time_diff, mon_node->name, mon_node->guid, port);
+}
+
+/**********************************************************************
+ * The dispatcher uses a thread pool which will call this function when
+ * we have a thread available to process our mad received from the wire.
+ **********************************************************************/
+static void osm_pc_rcv_process(void *context, void *data)
+{
+	osm_perfmgr_t *const pm = (osm_perfmgr_t *) context;
+	osm_madw_t *p_madw = (osm_madw_t *) data;
+	osm_madw_context_t *mad_context = &(p_madw->context);
+	ib_port_counters_t *wire_read =
+	    (ib_port_counters_t *) & (osm_madw_get_perfmgt_mad_ptr(p_madw)->
+				      data);
+	ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw);
+	uint64_t node_guid = mad_context->perfmgr_context.node_guid;
+	uint8_t port = mad_context->perfmgr_context.port;
+	perfmgr_db_err_reading_t err_reading;
+	perfmgr_db_data_cnt_reading_t data_reading;
+	cl_map_item_t *p_node;
+	__monitored_node_t *p_mon_node;
+
+	OSM_LOG_ENTER(pm->log);
+
+	/* go ahead and get the monitored node struct to have the printable
+	 * name if needed in messages
+	 */
+	if ((p_node = cl_qmap_get(&(pm->monitored_map), node_guid)) ==
+	    cl_qmap_end(&(pm->monitored_map))) {
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C12: GUID 0x%016"
+			PRIx64 " not found in monitored map\n",
+			node_guid);
+		goto Exit;
+	}
+	p_mon_node = (__monitored_node_t *) p_node;
+
+	OSM_LOG(pm->log, OSM_LOG_VERBOSE,
+		"Processing received MAD status 0x%x context 0x%"
+		PRIx64 " port %u\n", p_mad->status, node_guid, port);
+
+	/* Response could also be redirection (IBM eHCA PMA does this) */
+	if (p_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO) {
+		char gid_str[INET6_ADDRSTRLEN];
+		ib_class_port_info_t *cpi =
+		    (ib_class_port_info_t *) &
+		    (osm_madw_get_perfmgt_mad_ptr(p_madw)->data);
+		ib_api_status_t status;
+
+		OSM_LOG(pm->log, OSM_LOG_VERBOSE,
+			"Redirection to LID %u GID %s QP 0x%x received\n",
+			cl_ntoh16(cpi->redir_lid),
+			inet_ntop(AF_INET6, cpi->redir_gid.raw, gid_str,
+				  sizeof gid_str),
+			cl_ntoh32(cpi->redir_qp));
+
+		/* LID or GID redirection ? */
+		/* For GID redirection, need to get PathRecord from SA */
+		if (cpi->redir_lid == 0) {
+			OSM_LOG(pm->log, OSM_LOG_VERBOSE,
+				"GID redirection not currently implemented!\n");
+			goto Exit;
+		}
+
+		if (!pm->subn->opt.perfmgr_redir) {
+				OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C16: "
+				       "redirection requested but disabled\n");
+			goto Exit;
+		}
+
+		/* LID redirection support (easier than GID redirection) */
+		cl_plock_acquire(pm->lock);
+		/* Now, validate port number */
+		if (port > p_mon_node->redir_tbl_size) {
+			cl_plock_release(pm->lock);
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C13: "
+				"Invalid port num %d for GUID 0x%016"
+				PRIx64 " num ports %d\n", port, node_guid,
+				p_mon_node->redir_tbl_size);
+			goto Exit;
+		}
+		p_mon_node->redir_port[port].redir_lid = cpi->redir_lid;
+		p_mon_node->redir_port[port].redir_qp = cpi->redir_qp;
+		cl_plock_release(pm->lock);
+
+		/* Finally, reissue the query to the redirected location */
+		status =
+		    osm_perfmgr_send_pc_mad(pm, cpi->redir_lid, cpi->redir_qp,
+					    port,
+					    mad_context->perfmgr_context.
+					    mad_method, mad_context);
+		if (status != IB_SUCCESS)
+			OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 4C14: "
+				"Failed to send redirected MAD with method 0x%x for node 0x%"
+				PRIx64 " port %d\n",
+				mad_context->perfmgr_context.mad_method,
+				node_guid, port);
+		goto Exit;
+	}
+
+	CL_ASSERT(p_mad->attr_id == IB_MAD_ATTR_PORT_CNTRS);
+
+	perfmgr_db_fill_err_read(wire_read, &err_reading);
+	/* FIXME separate query for extended counters if they are supported
+	 * on the port.
+	 */
+	perfmgr_db_fill_data_cnt_read_pc(wire_read, &data_reading);
+
+	/* detect an out of band clear on the port */
+	if (mad_context->perfmgr_context.mad_method != IB_MAD_METHOD_SET)
+		osm_perfmgr_check_oob_clear(pm, p_mon_node, port,
+					    &err_reading, &data_reading);
+
+	/* log any critical events from this reading */
+	osm_perfmgr_log_events(pm, p_mon_node, port, &err_reading);
+
+	if (mad_context->perfmgr_context.mad_method == IB_MAD_METHOD_GET) {
+		perfmgr_db_add_err_reading(pm->db, node_guid, port,
+					   &err_reading);
+		perfmgr_db_add_dc_reading(pm->db, node_guid, port,
+					  &data_reading);
+	} else {
+		perfmgr_db_clear_prev_err(pm->db, node_guid, port);
+		perfmgr_db_clear_prev_dc(pm->db, node_guid, port);
+	}
+
+	osm_perfmgr_check_overflow(pm, p_mon_node, port, wire_read);
+
+#if ENABLE_OSM_PERF_MGR_PROFILE
+	do {
+		struct timeval proc_time;
+		gettimeofday(&proc_time, NULL);
+		diff_time(&(p_madw->context.perfmgr_context.query_start),
+			  &proc_time, &proc_time);
+		update_mad_stats(&proc_time);
+	} while (0);
+#endif
+
+Exit:
+	osm_mad_pool_put(pm->mad_pool, p_madw);
+
+	OSM_LOG_EXIT(pm->log);
+}
+
+/**********************************************************************
+ * Initialize the PerfMgr object
+ **********************************************************************/
+ib_api_status_t
+osm_perfmgr_init(osm_perfmgr_t * const pm, osm_opensm_t *osm,
+		 const osm_subn_opt_t * const p_opt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&osm->log);
+
+	OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "Initializing PerfMgr\n");
+
+	memset(pm, 0, sizeof(*pm));
+
+	cl_event_construct(&pm->sig_sweep);
+	cl_event_init(&pm->sig_sweep, FALSE);
+	pm->subn = &osm->subn;
+	pm->sm = &osm->sm;
+	pm->log = &osm->log;
+	pm->mad_pool = &osm->mad_pool;
+	pm->vendor = osm->p_vendor;
+	pm->trans_id = OSM_PERFMGR_INITIAL_TID_VALUE;
+	pm->lock = &osm->lock;
+	pm->state =
+	    p_opt->perfmgr ? PERFMGR_STATE_ENABLED : PERFMGR_STATE_DISABLE;
+	pm->sweep_time_s = p_opt->perfmgr_sweep_time_s;
+	pm->max_outstanding_queries = p_opt->perfmgr_max_outstanding_queries;
+	pm->osm = osm;
+
+	status = cl_timer_init(&pm->sweep_timer, perfmgr_sweep, pm);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	pm->db = perfmgr_db_construct(pm);
+	if (!pm->db) {
+		pm->state = PERFMGR_STATE_NO_DB;
+		goto Exit;
+	}
+
+	pm->pc_disp_h = cl_disp_register(&osm->disp, OSM_MSG_MAD_PORT_COUNTERS,
+					 osm_pc_rcv_process, pm);
+	if (pm->pc_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	__init_monitored_nodes(pm);
+
+	cl_timer_start(&pm->sweep_timer, pm->sweep_time_s * 1000);
+
+Exit:
+	OSM_LOG_EXIT(pm->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Clear the counters from the db
+ **********************************************************************/
+void osm_perfmgr_clear_counters(osm_perfmgr_t * pm)
+{
+	/**
+	 * FIXME todo issue clear on the fabric?
+	 */
+	perfmgr_db_clear_counters(pm->db);
+	osm_log(pm->log, OSM_LOG_INFO, "PerfMgr counters cleared\n");
+}
+
+/*******************************************************************
+ * Have the DB dump its information to the file specified
+ *******************************************************************/
+void osm_perfmgr_dump_counters(osm_perfmgr_t * pm, perfmgr_db_dump_t dump_type)
+{
+	char path[256];
+	char *file_name;
+	if (pm->subn->opt.event_db_dump_file)
+		file_name = pm->subn->opt.event_db_dump_file;
+	else {
+		snprintf(path, sizeof(path), "%s/%s",
+			 pm->subn->opt.dump_files_dir,
+			 OSM_PERFMGR_DEFAULT_DUMP_FILE);
+		file_name = path;
+	}
+	if (perfmgr_db_dump(pm->db, file_name, dump_type) != 0)
+		OSM_LOG(pm->log, OSM_LOG_ERROR, "Failed to dump file %s : %s",
+			file_name, strerror(errno));
+}
+
+/*******************************************************************
+ * Have the DB print its information to the fp specified
+ *******************************************************************/
+void
+osm_perfmgr_print_counters(osm_perfmgr_t *pm, char *nodename, FILE *fp)
+{
+	uint64_t guid = strtoull(nodename, NULL, 0);
+	if (guid == 0 && errno == EINVAL) {
+		perfmgr_db_print_by_name(pm->db, nodename, fp);
+	} else {
+		perfmgr_db_print_by_guid(pm->db, guid, fp);
+	}
+}
+
+#endif				/* ENABLE_OSM_PERF_MGR */
diff --git a/opensm/osm_perfmgr_db.c b/opensm/osm_perfmgr_db.c
new file mode 100644
index 0000000..934be77
--- /dev/null
+++ b/opensm/osm_perfmgr_db.c
@@ -0,0 +1,807 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 The Regents of the University of California.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#ifdef ENABLE_OSM_PERF_MGR
+
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#include <opensm/osm_perfmgr_db.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_opensm.h>
+
+/** =========================================================================
+ */
+perfmgr_db_t *perfmgr_db_construct(osm_perfmgr_t *perfmgr)
+{
+	perfmgr_db_t *db = malloc(sizeof(*db));
+	if (!db)
+		return (NULL);
+
+	cl_qmap_init(&(db->pc_data));
+	cl_plock_construct(&(db->lock));
+	cl_plock_init(&(db->lock));
+	db->perfmgr = perfmgr;
+	return ((void *)db);
+}
+
+/** =========================================================================
+ */
+void perfmgr_db_destroy(perfmgr_db_t * db)
+{
+	if (db) {
+		cl_plock_destroy(&(db->lock));
+		free(db);
+	}
+}
+
+/**********************************************************************
+ * Internal call db->lock should be held when calling
+ **********************************************************************/
+static inline _db_node_t *_get(perfmgr_db_t * db, uint64_t guid)
+{
+	cl_map_item_t *rc = cl_qmap_get(&(db->pc_data), guid);
+	const cl_map_item_t *end = cl_qmap_end(&(db->pc_data));
+
+	if (rc == end)
+		return (NULL);
+	return ((_db_node_t *) rc);
+}
+
+static inline perfmgr_db_err_t bad_node_port(_db_node_t * node, uint8_t port)
+{
+	if (!node)
+		return (PERFMGR_EVENT_DB_GUIDNOTFOUND);
+	if (port == 0 || port >= node->num_ports)
+		return (PERFMGR_EVENT_DB_PORTNOTFOUND);
+	return (PERFMGR_EVENT_DB_SUCCESS);
+}
+
+/** =========================================================================
+ */
+static _db_node_t *__malloc_node(uint64_t guid, uint8_t num_ports, char *name)
+{
+	int i = 0;
+	time_t cur_time = 0;
+	_db_node_t *rc = malloc(sizeof(*rc));
+	if (!rc)
+		return (NULL);
+
+	rc->ports = calloc(num_ports, sizeof(_db_port_t));
+	if (!rc->ports)
+		goto free_rc;
+	rc->num_ports = num_ports;
+	rc->node_guid = guid;
+
+	cur_time = time(NULL);
+	for (i = 0; i < num_ports; i++) {
+		rc->ports[i].last_reset = cur_time;
+		rc->ports[i].err_previous.time = cur_time;
+		rc->ports[i].dc_previous.time = cur_time;
+	}
+	snprintf(rc->node_name, NODE_NAME_SIZE, "%s", name);
+
+	return (rc);
+
+free_rc:
+	free(rc);
+	return (NULL);
+}
+
+/** =========================================================================
+ */
+static void __free_node(_db_node_t * node)
+{
+	if (!node)
+		return;
+	if (node->ports)
+		free(node->ports);
+	free(node);
+}
+
+/* insert nodes to the database */
+static perfmgr_db_err_t __insert(perfmgr_db_t * db, _db_node_t * node)
+{
+	cl_map_item_t *rc = cl_qmap_insert(&(db->pc_data), node->node_guid,
+					   (cl_map_item_t *) node);
+
+	if ((void *)rc != (void *)node)
+		return (PERFMGR_EVENT_DB_FAIL);
+	return (PERFMGR_EVENT_DB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+perfmgr_db_err_t
+perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid,
+			uint8_t num_ports, char *name)
+{
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+
+	cl_plock_excl_acquire(&(db->lock));
+	if (!_get(db, guid)) {
+		_db_node_t *pc_node = __malloc_node(guid, num_ports, name);
+		if (!pc_node) {
+			rc = PERFMGR_EVENT_DB_NOMEM;
+			goto Exit;
+		}
+		if (__insert(db, pc_node)) {
+			__free_node(pc_node);
+			rc = PERFMGR_EVENT_DB_FAIL;
+			goto Exit;
+		}
+	}
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+/**********************************************************************
+ * Dump a reading vs the previous reading to stdout
+ **********************************************************************/
+static inline void
+debug_dump_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num,
+		       _db_port_t * port, perfmgr_db_err_reading_t * cur)
+{
+	osm_log_t *log = db->perfmgr->log;
+
+	if (!osm_log_is_active(log, OSM_LOG_DEBUG))
+		return;		/* optimize this a bit */
+
+	osm_log(log, OSM_LOG_DEBUG,
+		"GUID 0x%" PRIx64 " Port %u:\n", guid, port_num);
+	osm_log(log, OSM_LOG_DEBUG,
+		"sym %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->symbol_err_cnt, port->err_previous.symbol_err_cnt,
+		port->err_total.symbol_err_cnt);
+	osm_log(log, OSM_LOG_DEBUG,
+		"ler %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->link_err_recover, port->err_previous.link_err_recover,
+		port->err_total.link_err_recover);
+	osm_log(log, OSM_LOG_DEBUG,
+		"ld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->link_downed, port->err_previous.link_downed,
+		port->err_total.link_downed);
+	osm_log(log, OSM_LOG_DEBUG,
+		"re %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_err,
+		port->err_previous.rcv_err, port->err_total.rcv_err);
+	osm_log(log, OSM_LOG_DEBUG,
+		"rrp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->rcv_rem_phys_err, port->err_previous.rcv_rem_phys_err,
+		port->err_total.rcv_rem_phys_err);
+	osm_log(log, OSM_LOG_DEBUG,
+		"rsr %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->rcv_switch_relay_err,
+		port->err_previous.rcv_switch_relay_err,
+		port->err_total.rcv_switch_relay_err);
+	osm_log(log, OSM_LOG_DEBUG,
+		"xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->xmit_discards, port->err_previous.xmit_discards,
+		port->err_total.xmit_discards);
+	osm_log(log, OSM_LOG_DEBUG,
+		"xce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->xmit_constraint_err,
+		port->err_previous.xmit_constraint_err,
+		port->err_total.xmit_constraint_err);
+	osm_log(log, OSM_LOG_DEBUG,
+		"rce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->rcv_constraint_err, port->err_previous.rcv_constraint_err,
+		port->err_total.rcv_constraint_err);
+	osm_log(log, OSM_LOG_DEBUG,
+		"li %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->link_integrity, port->err_previous.link_integrity,
+		port->err_total.link_integrity);
+	osm_log(log, OSM_LOG_DEBUG,
+		"bo %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->buffer_overrun, port->err_previous.buffer_overrun,
+		port->err_total.buffer_overrun);
+	osm_log(log, OSM_LOG_DEBUG,
+		"vld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->vl15_dropped, port->err_previous.vl15_dropped,
+		port->err_total.vl15_dropped);
+}
+
+/**********************************************************************
+ * perfmgr_db_err_reading_t functions
+ **********************************************************************/
+perfmgr_db_err_t
+perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid,
+			   uint8_t port, perfmgr_db_err_reading_t * reading)
+{
+	_db_port_t *p_port = NULL;
+	_db_node_t *node = NULL;
+	perfmgr_db_err_reading_t *previous = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+	osm_epi_pe_event_t epi_pe_data;
+
+	cl_plock_excl_acquire(&(db->lock));
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	p_port = &(node->ports[port]);
+	previous = &(node->ports[port].err_previous);
+
+	debug_dump_err_reading(db, guid, port, p_port, reading);
+
+	epi_pe_data.time_diff_s = (reading->time - previous->time);
+	osm_epi_create_port_id(&(epi_pe_data.port_id), guid, port,
+			       node->node_name);
+
+	/* calculate changes from previous reading */
+	epi_pe_data.symbol_err_cnt =
+	    (reading->symbol_err_cnt - previous->symbol_err_cnt);
+	p_port->err_total.symbol_err_cnt += epi_pe_data.symbol_err_cnt;
+	epi_pe_data.link_err_recover =
+	    (reading->link_err_recover - previous->link_err_recover);
+	p_port->err_total.link_err_recover += epi_pe_data.link_err_recover;
+	epi_pe_data.link_downed =
+	    (reading->link_downed - previous->link_downed);
+	p_port->err_total.link_downed += epi_pe_data.link_downed;
+	epi_pe_data.rcv_err = (reading->rcv_err - previous->rcv_err);
+	p_port->err_total.rcv_err += epi_pe_data.rcv_err;
+	epi_pe_data.rcv_rem_phys_err =
+	    (reading->rcv_rem_phys_err - previous->rcv_rem_phys_err);
+	p_port->err_total.rcv_rem_phys_err += epi_pe_data.rcv_rem_phys_err;
+	epi_pe_data.rcv_switch_relay_err =
+	    (reading->rcv_switch_relay_err - previous->rcv_switch_relay_err);
+	p_port->err_total.rcv_switch_relay_err +=
+	    epi_pe_data.rcv_switch_relay_err;
+	epi_pe_data.xmit_discards =
+	    (reading->xmit_discards - previous->xmit_discards);
+	p_port->err_total.xmit_discards += epi_pe_data.xmit_discards;
+	epi_pe_data.xmit_constraint_err =
+	    (reading->xmit_constraint_err - previous->xmit_constraint_err);
+	p_port->err_total.xmit_constraint_err +=
+	    epi_pe_data.xmit_constraint_err;
+	epi_pe_data.rcv_constraint_err =
+	    (reading->rcv_constraint_err - previous->rcv_constraint_err);
+	p_port->err_total.rcv_constraint_err += epi_pe_data.rcv_constraint_err;
+	epi_pe_data.link_integrity =
+	    (reading->link_integrity - previous->link_integrity);
+	p_port->err_total.link_integrity += epi_pe_data.link_integrity;
+	epi_pe_data.buffer_overrun =
+	    (reading->buffer_overrun - previous->buffer_overrun);
+	p_port->err_total.buffer_overrun += epi_pe_data.buffer_overrun;
+	epi_pe_data.vl15_dropped =
+	    (reading->vl15_dropped - previous->vl15_dropped);
+	p_port->err_total.vl15_dropped += epi_pe_data.vl15_dropped;
+
+	p_port->err_previous = *reading;
+
+	osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_ERRORS,
+				&epi_pe_data);
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+perfmgr_db_err_t perfmgr_db_get_prev_err(perfmgr_db_t * db, uint64_t guid,
+					 uint8_t port,
+					 perfmgr_db_err_reading_t * reading)
+{
+	_db_node_t *node = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+
+	cl_plock_acquire(&(db->lock));
+
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	*reading = node->ports[port].err_previous;
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+perfmgr_db_err_t
+perfmgr_db_clear_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port)
+{
+	_db_node_t *node = NULL;
+	perfmgr_db_err_reading_t *previous = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+
+	cl_plock_excl_acquire(&(db->lock));
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	previous = &(node->ports[port].err_previous);
+
+	memset(previous, 0, sizeof(*previous));
+	node->ports[port].err_previous.time = time(NULL);
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+static inline void
+debug_dump_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num,
+		      _db_port_t * port, perfmgr_db_data_cnt_reading_t * cur)
+{
+	osm_log_t *log = db->perfmgr->log;
+	if (!osm_log_is_active(log, OSM_LOG_DEBUG))
+		return;		/* optimize this a big */
+
+	osm_log(log, OSM_LOG_DEBUG,
+		"xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->xmit_data, port->dc_previous.xmit_data,
+		port->dc_total.xmit_data);
+	osm_log(log, OSM_LOG_DEBUG,
+		"rd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_data,
+		port->dc_previous.rcv_data, port->dc_total.rcv_data);
+	osm_log(log, OSM_LOG_DEBUG,
+		"xp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
+		cur->xmit_pkts, port->dc_previous.xmit_pkts,
+		port->dc_total.xmit_pkts);
+	osm_log(log, OSM_LOG_DEBUG,
+		"rp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_pkts,
+		port->dc_previous.rcv_pkts, port->dc_total.rcv_pkts);
+}
+
+/**********************************************************************
+ * perfmgr_db_data_cnt_reading_t functions
+ **********************************************************************/
+perfmgr_db_err_t
+perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid,
+			  uint8_t port, perfmgr_db_data_cnt_reading_t * reading)
+{
+	_db_port_t *p_port = NULL;
+	_db_node_t *node = NULL;
+	perfmgr_db_data_cnt_reading_t *previous = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+	osm_epi_dc_event_t epi_dc_data;
+
+	cl_plock_excl_acquire(&(db->lock));
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	p_port = &(node->ports[port]);
+	previous = &(node->ports[port].dc_previous);
+
+	debug_dump_dc_reading(db, guid, port, p_port, reading);
+
+	epi_dc_data.time_diff_s = (reading->time - previous->time);
+	osm_epi_create_port_id(&(epi_dc_data.port_id), guid, port,
+			       node->node_name);
+
+	/* calculate changes from previous reading */
+	epi_dc_data.xmit_data = (reading->xmit_data - previous->xmit_data);
+	p_port->dc_total.xmit_data += epi_dc_data.xmit_data;
+	epi_dc_data.rcv_data = (reading->rcv_data - previous->rcv_data);
+	p_port->dc_total.rcv_data += epi_dc_data.rcv_data;
+	epi_dc_data.xmit_pkts = (reading->xmit_pkts - previous->xmit_pkts);
+	p_port->dc_total.xmit_pkts += epi_dc_data.xmit_pkts;
+	epi_dc_data.rcv_pkts = (reading->rcv_pkts - previous->rcv_pkts);
+	p_port->dc_total.rcv_pkts += epi_dc_data.rcv_pkts;
+	epi_dc_data.unicast_xmit_pkts =
+	    (reading->unicast_xmit_pkts - previous->unicast_xmit_pkts);
+	p_port->dc_total.unicast_xmit_pkts += epi_dc_data.unicast_xmit_pkts;
+	epi_dc_data.unicast_rcv_pkts =
+	    (reading->unicast_rcv_pkts - previous->unicast_rcv_pkts);
+	p_port->dc_total.unicast_rcv_pkts += epi_dc_data.unicast_rcv_pkts;
+	epi_dc_data.multicast_xmit_pkts =
+	    (reading->multicast_xmit_pkts - previous->multicast_xmit_pkts);
+	p_port->dc_total.multicast_xmit_pkts += epi_dc_data.multicast_xmit_pkts;
+	epi_dc_data.multicast_rcv_pkts =
+	    (reading->multicast_rcv_pkts - previous->multicast_rcv_pkts);
+	p_port->dc_total.multicast_rcv_pkts += epi_dc_data.multicast_rcv_pkts;
+
+	p_port->dc_previous = *reading;
+
+	osm_opensm_report_event(db->perfmgr->osm,
+				OSM_EVENT_ID_PORT_DATA_COUNTERS, &epi_dc_data);
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+perfmgr_db_err_t perfmgr_db_get_prev_dc(perfmgr_db_t * db, uint64_t guid,
+					uint8_t port,
+					perfmgr_db_data_cnt_reading_t * reading)
+{
+	_db_node_t *node = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+
+	cl_plock_acquire(&(db->lock));
+
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	*reading = node->ports[port].dc_previous;
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+perfmgr_db_err_t
+perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port)
+{
+	_db_node_t *node = NULL;
+	perfmgr_db_data_cnt_reading_t *previous = NULL;
+	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
+
+	cl_plock_excl_acquire(&(db->lock));
+	node = _get(db, guid);
+	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
+		goto Exit;
+
+	previous = &(node->ports[port].dc_previous);
+
+	memset(previous, 0, sizeof(*previous));
+	node->ports[port].dc_previous.time = time(NULL);
+
+Exit:
+	cl_plock_release(&(db->lock));
+	return (rc);
+}
+
+static void __clear_counters(cl_map_item_t * const p_map_item, void *context)
+{
+	_db_node_t *node = (_db_node_t *) p_map_item;
+	int i = 0;
+	time_t ts = time(NULL);
+
+	for (i = 0; i < node->num_ports; i++) {
+		node->ports[i].err_total.symbol_err_cnt = 0;
+		node->ports[i].err_total.link_err_recover = 0;
+		node->ports[i].err_total.link_downed = 0;
+		node->ports[i].err_total.rcv_err = 0;
+		node->ports[i].err_total.rcv_rem_phys_err = 0;
+		node->ports[i].err_total.rcv_switch_relay_err = 0;
+		node->ports[i].err_total.xmit_discards = 0;
+		node->ports[i].err_total.xmit_constraint_err = 0;
+		node->ports[i].err_total.rcv_constraint_err = 0;
+		node->ports[i].err_total.link_integrity = 0;
+		node->ports[i].err_total.buffer_overrun = 0;
+		node->ports[i].err_total.vl15_dropped = 0;
+		node->ports[i].err_total.time = ts;
+
+		node->ports[i].dc_total.xmit_data = 0;
+		node->ports[i].dc_total.rcv_data = 0;
+		node->ports[i].dc_total.xmit_pkts = 0;
+		node->ports[i].dc_total.rcv_pkts = 0;
+		node->ports[i].dc_total.unicast_xmit_pkts = 0;
+		node->ports[i].dc_total.unicast_rcv_pkts = 0;
+		node->ports[i].dc_total.multicast_xmit_pkts = 0;
+		node->ports[i].dc_total.multicast_rcv_pkts = 0;
+		node->ports[i].dc_total.time = ts;
+
+		node->ports[i].last_reset = ts;
+	}
+}
+
+/**********************************************************************
+ * Clear all the counters from the db
+ **********************************************************************/
+void perfmgr_db_clear_counters(perfmgr_db_t * db)
+{
+	cl_plock_excl_acquire(&(db->lock));
+	cl_qmap_apply_func(&(db->pc_data), __clear_counters, (void *)db);
+	cl_plock_release(&(db->lock));
+#if 0
+	if (db->db_impl->clear_counters)
+		db->db_impl->clear_counters(db->db_data);
+#endif
+}
+
+/**********************************************************************
+ * Output a tab delimited output of the port counters
+ **********************************************************************/
+static void __dump_node_mr(_db_node_t * node, FILE * fp)
+{
+	int i = 0;
+
+	fprintf(fp, "\nName\tGUID\tPort\tLast Reset\t"
+		"%s\t%s\t"
+		"%s\t%s\t%s\t%s\t%s\t%s\t%s\t"
+		"%s\t%s\t%s\t%s\t%s\t%s\t%s\t"
+		"%s\t%s\t%s\t%s\n",
+		"symbol_err_cnt",
+		"link_err_recover",
+		"link_downed",
+		"rcv_err",
+		"rcv_rem_phys_err",
+		"rcv_switch_relay_err",
+		"xmit_discards",
+		"xmit_constraint_err",
+		"rcv_constraint_err",
+		"link_int_err",
+		"buf_overrun_err",
+		"vl15_dropped",
+		"xmit_data",
+		"rcv_data",
+		"xmit_pkts",
+		"rcv_pkts",
+		"unicast_xmit_pkts",
+		"unicast_rcv_pkts",
+		"multicast_xmit_pkts", "multicast_rcv_pkts");
+	for (i = 1; i < node->num_ports; i++) {
+		char *since = ctime(&(node->ports[i].last_reset));
+		since[strlen(since) - 1] = '\0';	/* remove \n */
+
+		fprintf(fp,
+			"%s\t0x%" PRIx64 "\t%d\t%s\t%" PRIu64 "\t%" PRIu64 "\t"
+			"%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t"
+			"%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64
+			"\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64
+			"\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64
+			"\t%" PRIu64 "\t%" PRIu64 "\n", node->node_name,
+			node->node_guid, i, since,
+			node->ports[i].err_total.symbol_err_cnt,
+			node->ports[i].err_total.link_err_recover,
+			node->ports[i].err_total.link_downed,
+			node->ports[i].err_total.rcv_err,
+			node->ports[i].err_total.rcv_rem_phys_err,
+			node->ports[i].err_total.rcv_switch_relay_err,
+			node->ports[i].err_total.xmit_discards,
+			node->ports[i].err_total.xmit_constraint_err,
+			node->ports[i].err_total.rcv_constraint_err,
+			node->ports[i].err_total.link_integrity,
+			node->ports[i].err_total.buffer_overrun,
+			node->ports[i].err_total.vl15_dropped,
+			node->ports[i].dc_total.xmit_data,
+			node->ports[i].dc_total.rcv_data,
+			node->ports[i].dc_total.xmit_pkts,
+			node->ports[i].dc_total.rcv_pkts,
+			node->ports[i].dc_total.unicast_xmit_pkts,
+			node->ports[i].dc_total.unicast_rcv_pkts,
+			node->ports[i].dc_total.multicast_xmit_pkts,
+			node->ports[i].dc_total.multicast_rcv_pkts);
+	}
+}
+
+/**********************************************************************
+ * Output a human readable output of the port counters
+ **********************************************************************/
+static void __dump_node_hr(_db_node_t * node, FILE * fp)
+{
+	int i = 0;
+
+	fprintf(fp, "\n");
+	for (i = 1; i < node->num_ports; i++) {
+		char *since = ctime(&(node->ports[i].last_reset));
+		since[strlen(since) - 1] = '\0';	/* remove \n */
+
+		fprintf(fp, "\"%s\" 0x%" PRIx64 " port %d (Since %s)\n"
+			"     symbol_err_cnt       : %" PRIu64 "\n"
+			"     link_err_recover     : %" PRIu64 "\n"
+			"     link_downed          : %" PRIu64 "\n"
+			"     rcv_err              : %" PRIu64 "\n"
+			"     rcv_rem_phys_err     : %" PRIu64 "\n"
+			"     rcv_switch_relay_err : %" PRIu64 "\n"
+			"     xmit_discards        : %" PRIu64 "\n"
+			"     xmit_constraint_err  : %" PRIu64 "\n"
+			"     rcv_constraint_err   : %" PRIu64 "\n"
+			"     link_integrity_err   : %" PRIu64 "\n"
+			"     buf_overrun_err      : %" PRIu64 "\n"
+			"     vl15_dropped         : %" PRIu64 "\n"
+			"     xmit_data            : %" PRIu64 "\n"
+			"     rcv_data             : %" PRIu64 "\n"
+			"     xmit_pkts            : %" PRIu64 "\n"
+			"     rcv_pkts             : %" PRIu64 "\n"
+			"     unicast_xmit_pkts    : %" PRIu64 "\n"
+			"     unicast_rcv_pkts     : %" PRIu64 "\n"
+			"     multicast_xmit_pkts  : %" PRIu64 "\n"
+			"     multicast_rcv_pkts   : %" PRIu64 "\n",
+			node->node_name,
+			node->node_guid,
+			i,
+			since,
+			node->ports[i].err_total.symbol_err_cnt,
+			node->ports[i].err_total.link_err_recover,
+			node->ports[i].err_total.link_downed,
+			node->ports[i].err_total.rcv_err,
+			node->ports[i].err_total.rcv_rem_phys_err,
+			node->ports[i].err_total.rcv_switch_relay_err,
+			node->ports[i].err_total.xmit_discards,
+			node->ports[i].err_total.xmit_constraint_err,
+			node->ports[i].err_total.rcv_constraint_err,
+			node->ports[i].err_total.link_integrity,
+			node->ports[i].err_total.buffer_overrun,
+			node->ports[i].err_total.vl15_dropped,
+			node->ports[i].dc_total.xmit_data,
+			node->ports[i].dc_total.rcv_data,
+			node->ports[i].dc_total.xmit_pkts,
+			node->ports[i].dc_total.rcv_pkts,
+			node->ports[i].dc_total.unicast_xmit_pkts,
+			node->ports[i].dc_total.unicast_rcv_pkts,
+			node->ports[i].dc_total.multicast_xmit_pkts,
+			node->ports[i].dc_total.multicast_rcv_pkts);
+	}
+}
+
+/* Define a context for the __db_dump callback */
+typedef struct {
+	FILE *fp;
+	perfmgr_db_dump_t dump_type;
+} dump_context_t;
+
+/**********************************************************************
+ **********************************************************************/
+static void __db_dump(cl_map_item_t * const p_map_item, void *context)
+{
+	_db_node_t *node = (_db_node_t *) p_map_item;
+	dump_context_t *c = (dump_context_t *) context;
+	FILE *fp = c->fp;
+
+	switch (c->dump_type) {
+	case PERFMGR_EVENT_DB_DUMP_MR:
+		__dump_node_mr(node, fp);
+		break;
+	case PERFMGR_EVENT_DB_DUMP_HR:
+	default:
+		__dump_node_hr(node, fp);
+		break;
+	}
+}
+
+/**********************************************************************
+ * print node data to fp
+ **********************************************************************/
+void
+perfmgr_db_print_by_name(perfmgr_db_t * db, char *nodename, FILE *fp)
+{
+	cl_map_item_t *item = NULL;
+	_db_node_t *node = NULL;
+
+	cl_plock_acquire(&(db->lock));
+
+	/* find the node */
+	item = cl_qmap_head(&(db->pc_data));
+	while (item != cl_qmap_end(&(db->pc_data))) {
+		node = (_db_node_t *)item;
+		if (strcmp(node->node_name, nodename) == 0) {
+			__dump_node_hr(node, fp);
+			goto done;
+		}
+		item = cl_qmap_next(item);
+	}
+
+	fprintf(fp, "Node %s not found...\n", nodename);
+done:
+	cl_plock_release(&(db->lock));
+}
+
+/**********************************************************************
+ * print node data to fp
+ **********************************************************************/
+void
+perfmgr_db_print_by_guid(perfmgr_db_t * db, uint64_t nodeguid, FILE *fp)
+{
+	cl_map_item_t *node = NULL;
+
+	cl_plock_acquire(&(db->lock));
+
+	node = cl_qmap_get(&(db->pc_data), nodeguid);
+	if (node != cl_qmap_end(&(db->pc_data)))
+		__dump_node_hr((_db_node_t *)node, fp);
+	else
+		fprintf(fp, "Node %"PRIx64" not found...\n", nodeguid);
+
+	cl_plock_release(&(db->lock));
+}
+
+/**********************************************************************
+ * dump the data to the file "file"
+ **********************************************************************/
+perfmgr_db_err_t
+perfmgr_db_dump(perfmgr_db_t * db, char *file, perfmgr_db_dump_t dump_type)
+{
+	dump_context_t context;
+
+	context.fp = fopen(file, "w+");
+	if (!context.fp)
+		return (PERFMGR_EVENT_DB_FAIL);
+	context.dump_type = dump_type;
+
+	cl_plock_acquire(&(db->lock));
+	cl_qmap_apply_func(&(db->pc_data), __db_dump, (void *)&context);
+	cl_plock_release(&(db->lock));
+	fclose(context.fp);
+	return (PERFMGR_EVENT_DB_SUCCESS);
+}
+
+/**********************************************************************
+ * Fill in the various DB objects from their wire counter parts
+ **********************************************************************/
+void
+perfmgr_db_fill_err_read(ib_port_counters_t * wire_read,
+			 perfmgr_db_err_reading_t * reading)
+{
+	reading->symbol_err_cnt = cl_ntoh16(wire_read->symbol_err_cnt);
+	reading->link_err_recover = cl_ntoh16(wire_read->link_err_recover);
+	reading->link_downed = wire_read->link_downed;
+	reading->rcv_err = wire_read->rcv_err;
+	reading->rcv_rem_phys_err = cl_ntoh16(wire_read->rcv_rem_phys_err);
+	reading->rcv_switch_relay_err =
+	    cl_ntoh16(wire_read->rcv_switch_relay_err);
+	reading->xmit_discards = cl_ntoh16(wire_read->xmit_discards);
+	reading->xmit_constraint_err =
+	    cl_ntoh16(wire_read->xmit_constraint_err);
+	reading->rcv_constraint_err = wire_read->rcv_constraint_err;
+	reading->link_integrity =
+	    PC_LINK_INT(wire_read->link_int_buffer_overrun);
+	reading->buffer_overrun =
+	    PC_BUF_OVERRUN(wire_read->link_int_buffer_overrun);
+	reading->vl15_dropped = cl_ntoh16(wire_read->vl15_dropped);
+	reading->time = time(NULL);
+}
+
+void
+perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read,
+				 perfmgr_db_data_cnt_reading_t * reading)
+{
+	reading->xmit_data = cl_ntoh32(wire_read->xmit_data);
+	reading->rcv_data = cl_ntoh32(wire_read->rcv_data);
+	reading->xmit_pkts = cl_ntoh32(wire_read->xmit_pkts);
+	reading->rcv_pkts = cl_ntoh32(wire_read->rcv_pkts);
+	reading->unicast_xmit_pkts = 0;
+	reading->unicast_rcv_pkts = 0;
+	reading->multicast_xmit_pkts = 0;
+	reading->multicast_rcv_pkts = 0;
+	reading->time = time(NULL);
+}
+
+void
+perfmgr_db_fill_data_cnt_read_epc(ib_port_counters_ext_t * wire_read,
+				  perfmgr_db_data_cnt_reading_t * reading)
+{
+	reading->xmit_data = cl_ntoh64(wire_read->xmit_data);
+	reading->rcv_data = cl_ntoh64(wire_read->rcv_data);
+	reading->xmit_pkts = cl_ntoh64(wire_read->xmit_pkts);
+	reading->rcv_pkts = cl_ntoh64(wire_read->rcv_pkts);
+	reading->unicast_xmit_pkts = cl_ntoh64(wire_read->unicast_xmit_pkts);
+	reading->unicast_rcv_pkts = cl_ntoh64(wire_read->unicast_rcv_pkts);
+	reading->multicast_xmit_pkts =
+	    cl_ntoh64(wire_read->multicast_xmit_pkts);
+	reading->multicast_rcv_pkts = cl_ntoh64(wire_read->multicast_rcv_pkts);
+	reading->time = time(NULL);
+}
+#endif				/* ENABLE_OSM_PERF_MGR */
diff --git a/opensm/osm_pkey.c b/opensm/osm_pkey.c
new file mode 100644
index 0000000..e09faa8
--- /dev/null
+++ b/opensm/osm_pkey.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of opensm pkey manipulation functions.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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)
+			return (IB_ERROR);
+		memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
+		cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block);
+	}
+
+	/* sets the block values */
+	memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t));
+
+	/*
+	   NOTE: as the spec does not require uniqueness of PKeys in
+	   tables there is no other way but to refresh the entire keys map.
+
+	   Moreover, if the same key exists but with full membership it should
+	   have precedence 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);
+
+	if (!p_port_1 || !p_port_2) {
+		ret = FALSE;
+		goto Exit;
+	}
+
+	p_physp1 = p_port_1->p_physp;
+	p_physp2 = p_port_2->p_physp;
+
+	if (!p_physp1 || !p_physp2) {
+		ret = FALSE;
+		goto Exit;
+	}
+
+	ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2);
+
+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);
+
+	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 = p_port1->p_physp;
+	}
+
+	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 = p_port2->p_physp;
+	}
+
+	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_LOG(p_log, OSM_LOG_DEBUG,
+		"Search for PKey: 0x%04x\n", cl_ntoh16(pkey));
+
+	/* if the pkey given is an invalid pkey - return TRUE. */
+	if (ib_pkey_is_invalid(pkey)) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Given invalid PKey - we treat it loosely and allow it\n");
+		res = TRUE;
+		goto Exit;
+	}
+
+	pkey_base = ib_pkey_get_base(pkey);
+
+	pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
+
+	p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base);
+	if (p_pkey) {
+		res = TRUE;
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"PKey 0x%04x was found\n", cl_ntoh16(pkey));
+	} else {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"PKey 0x%04x was not found\n", cl_ntoh16(pkey));
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return res;
+}
diff --git a/opensm/osm_pkey_mgr.c b/opensm/osm_pkey_mgr.c
new file mode 100644
index 0000000..9df8c85
--- /dev/null
+++ b/opensm/osm_pkey_mgr.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * Implementation of the P_Key Manager (Partititon Manager).
+ * This is part of the OpenSM.
+ */
+
+#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 osm_sm_t * sm,
+			       IN const ib_net16_t pkey,
+			       IN osm_physp_t * p_physp)
+{
+	osm_node_t *p_node = osm_physp_get_node_ptr(p_physp);
+	osm_pkey_tbl_t *p_pkey_tbl;
+	ib_net16_t *p_orig_pkey;
+	char *stat = NULL;
+	osm_pending_pkey_t *p_pending;
+
+	p_pkey_tbl = &p_physp->pkeys;
+	p_pending = (osm_pending_pkey_t *) malloc(sizeof(osm_pending_pkey_t));
+	if (!p_pending) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0502: "
+			"Failed to allocate new pending pkey entry for node "
+			"0x%016" PRIx64 " port %u\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)),
+			osm_physp_get_port_num(p_physp));
+		return;
+	}
+	p_pending->pkey = pkey;
+	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, "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 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, osm_sm_t * sm,
+				 const osm_prtn_t * p_prtn,
+				 const boolean_t full)
+{
+	const cl_map_t *p_tbl =
+	    full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl;
+	cl_map_iterator_t i, i_next;
+	ib_net16_t pkey = p_prtn->pkey;
+	osm_physp_t *p_physp;
+
+	if (full)
+		pkey |= cl_hton16(0x8000);
+
+	i_next = cl_map_head(p_tbl);
+	while (i_next != cl_map_end(p_tbl)) {
+		i = i_next;
+		i_next = cl_map_next(i);
+		p_physp = cl_map_obj(i);
+		if (p_physp)
+			pkey_mgr_process_physical_port(p_log, sm, pkey,
+						       p_physp);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+pkey_mgr_update_pkey_entry(IN osm_sm_t * sm,
+			   IN const osm_physp_t * p_physp,
+			   IN const ib_pkey_table_t * block,
+			   IN const uint16_t block_index)
+{
+	osm_madw_context_t context;
+	osm_node_t *p_node = osm_physp_get_node_ptr(p_physp);
+	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(sm, 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, osm_sm_t * sm,
+			   IN 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;
+
+	p_pi = &p_physp->port_info;
+
+	if ((p_pi->vl_enforce & 0xc) == (0xc) * (enforce == TRUE)) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"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.light_sweep = FALSE;
+	context.pi_context.active_transition = FALSE;
+
+	status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
+			     payload, sizeof(payload),
+			     IB_MAD_ATTR_PORT_INFO,
+			     cl_hton32(osm_physp_get_port_num(p_physp)),
+			     CL_DISP_MSGID_NONE, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0511: "
+			"Failed to set PortInfo for "
+			"node 0x%016" PRIx64 " port %u\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,
+			"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_sm_t * sm,
+				      const osm_port_t * const p_port)
+{
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	ib_pkey_table_t *block, *new_block;
+	osm_pkey_tbl_t *p_pkey_tbl;
+	uint16_t block_index;
+	uint8_t pkey_index;
+	uint16_t last_free_block_index = 0;
+	uint8_t last_free_pkey_index = 0;
+	uint16_t num_of_blocks;
+	uint16_t max_num_of_blocks;
+	ib_api_status_t status;
+	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 = p_port->p_physp;
+	if (!p_physp)
+		return FALSE;
+
+	p_node = osm_physp_get_node_ptr(p_physp);
+	p_pkey_tbl = &p_physp->pkeys;
+	num_of_blocks = osm_pkey_tbl_get_num_blocks(p_pkey_tbl);
+	max_num_of_blocks =
+	    pkey_mgr_get_physp_max_blocks(sm->p_subn, p_physp);
+	if (p_pkey_tbl->max_blocks > max_num_of_blocks) {
+		OSM_LOG(p_log, OSM_LOG_INFO,
+			"Max number of blocks reduced from %u to %u "
+			"for node 0x%016" PRIx64 " port %u\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, "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, "ERR 0505: "
+					"Failed to set PKey 0x%04x in block %u idx %u "
+					"for node 0x%016" PRIx64 " port %u\n",
+					cl_ntoh16(p_pending->pkey), block_index,
+					pkey_index,
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_node)),
+					osm_physp_get_port_num(p_physp));
+			}
+		}
+
+		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(sm, p_physp, new_block,
+					       block_index);
+		if (status == IB_SUCCESS) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG,
+				"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, "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, osm_sm_t * sm,
+			  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 = p_port->p_physp;
+	if (!p_physp)
+		return FALSE;
+	peer = osm_physp_get_remote(p_physp);
+	if (!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 = &peer->pkeys;
+	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, "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, sm, 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(sm, peer, block,
+						       block_index);
+			if (status == IB_SUCCESS)
+				ret_val = TRUE;
+			else
+				OSM_LOG(p_log, OSM_LOG_ERROR, "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)
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"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;
+
+	CL_ASSERT(p_osm);
+
+	OSM_LOG_ENTER(&p_osm->log);
+
+	CL_PLOCK_EXCL_ACQUIRE(&p_osm->lock);
+
+	if (osm_prtn_make_partitions(&p_osm->log, &p_osm->subn) != IB_SUCCESS) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 0510: "
+			"osm_prtn_make_partitions() failed\n");
+		goto _err;
+	}
+
+	/* populate the pending pkey entries by scanning all partitions */
+	p_tbl = &p_osm->subn.prtn_pkey_tbl;
+	p_next = cl_qmap_head(p_tbl);
+	while (p_next != cl_qmap_end(p_tbl)) {
+		p_prtn = (osm_prtn_t *) p_next;
+		p_next = cl_qmap_next(p_next);
+		pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm,
+						 p_prtn, FALSE);
+		pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm,
+						 p_prtn, TRUE);
+	}
+
+	/* calculate and set new pkey tables */
+	p_tbl = &p_osm->subn.port_guid_tbl;
+	p_next = cl_qmap_head(p_tbl);
+	while (p_next != cl_qmap_end(p_tbl)) {
+		p_port = (osm_port_t *) p_next;
+		p_next = cl_qmap_next(p_next);
+		if (pkey_mgr_update_port(&p_osm->log, &p_osm->sm, p_port))
+			signal = OSM_SIGNAL_DONE_PENDING;
+		if ((osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH)
+		    && pkey_mgr_update_peer_port(&p_osm->log, &p_osm->sm,
+						 &p_osm->subn, p_port,
+						 !p_osm->subn.opt.
+						 no_partition_enforcement))
+			signal = OSM_SIGNAL_DONE_PENDING;
+	}
+
+_err:
+	CL_PLOCK_RELEASE(&p_osm->lock);
+	OSM_LOG_EXIT(&p_osm->log);
+	return (signal);
+}
diff --git a/opensm/osm_pkey_rcv.c b/opensm/osm_pkey_rcv.c
new file mode 100644
index 0000000..7061941
--- /dev/null
+++ b/opensm/osm_pkey_rcv.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void osm_pkey_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_pkey_table_t *p_pkey_tbl;
+	ib_smp_t *p_smp;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	osm_pkey_context_t *p_context;
+	ib_net64_t port_guid;
+	ib_net64_t node_guid;
+	uint8_t port_num;
+	uint16_t block_num;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	p_context = osm_madw_get_pkey_context_ptr(p_madw);
+	p_pkey_tbl = (ib_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);
+
+	cl_plock_excl_acquire(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4806: "
+			"No port object for port with GUID 0x%" PRIx64
+			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+			", TID 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid),
+			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+		goto Exit;
+	}
+
+	p_node = p_port->p_node;
+	CL_ASSERT(p_node);
+
+	block_num = (uint16_t) ((cl_ntoh32(p_smp->attr_mod)) & 0x0000FFFF);
+	/* in case of a non switch node the attr modifier should be ignored */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {
+		port_num =
+		    (uint8_t) (((cl_ntoh32(p_smp->attr_mod)) & 0x00FF0000) >>
+			       16);
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+	} else {
+		p_physp = p_port->p_physp;
+		port_num = p_physp->port_num;
+	}
+
+	/*
+	   We do not mind if this is a result of a set or get - all we want is to
+	   update the subnet.
+	 */
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Got GetResp(PKey) block:%u port_num %u with GUID 0x%"
+		PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%"
+		PRIx64 "\n", block_num, port_num, cl_ntoh64(port_guid),
+		cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+
+	/*
+	   Determine if we encountered a new Physical Port.
+	   If so, ignore it.
+	 */
+	if (!p_physp) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4807: "
+			"Got invalid port number %u\n", port_num);
+		goto Exit;
+	}
+
+	osm_dump_pkey_block(sm->p_log,
+			    port_guid, block_num,
+			    port_num, p_pkey_tbl, OSM_LOG_DEBUG);
+
+	osm_physp_set_pkey_tbl(sm->p_log, sm->p_subn,
+			       p_physp, p_pkey_tbl, block_num);
+
+Exit:
+	cl_plock_release(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_port.c b/opensm/osm_port.c
new file mode 100644
index 0000000..4b4d4b8
--- /dev/null
+++ b/opensm/osm_port.c
@@ -0,0 +1,780 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_physp_t.
+ * This object represents an Infiniband Port.
+ * This object is part of the opensm family of objects.
+ */
+
+#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 uninitialized */
+	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->need_update = 2;
+	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)
+			break;
+		memset(p_slvl, 0, sizeof(ib_slvl_table_t));
+		cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl);
+	}
+
+	/* initialize the pkey table */
+	osm_pkey_tbl_init(&p_physp->pkeys);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_port_delete(IN OUT osm_port_t ** const pp_port)
+{
+	/* cleanup all mcm recs attached */
+	osm_port_remove_all_mgrp(*pp_port);
+	free(*pp_port);
+	*pp_port = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_port_init(IN osm_port_t * const p_port,
+	      IN const ib_node_info_t * p_ni,
+	      IN osm_node_t * const p_parent_node)
+{
+	ib_net64_t port_guid;
+	osm_physp_t *p_physp;
+	uint8_t port_num;
+
+	CL_ASSERT(p_port);
+	CL_ASSERT(p_ni);
+	CL_ASSERT(p_parent_node);
+
+	memset(p_port, 0, sizeof(*p_port));
+	cl_qlist_init(&p_port->mcm_list);
+	p_port->p_node = (struct osm_node *)p_parent_node;
+	port_guid = p_ni->port_guid;
+	p_port->guid = port_guid;
+	port_num = p_ni->node_type == IB_NODE_TYPE_SWITCH ?
+		0 : ib_node_info_get_local_port_num(p_ni);
+
+	/*
+	   Get the pointers to the physical node objects "owned" by this
+	   logical port GUID.
+	   For switches, port '0' is owned; for HCA's and routers,
+	   only the singular part that has this GUID is owned.
+	 */
+	p_physp = osm_node_get_physp_ptr(p_parent_node, port_num);
+	CL_ASSERT(port_guid == osm_physp_get_port_guid(p_physp));
+	p_port->p_physp = p_physp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni,
+			 IN osm_node_t * const p_parent_node)
+{
+	osm_port_t *p_port;
+
+	p_port = malloc(sizeof(*p_port));
+	if (p_port != NULL) {
+		memset(p_port, 0, sizeof(*p_port));
+		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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 osm_physp_t *p_remote_physp;
+	uint8_t mtu;
+	uint8_t remote_mtu;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_remote_physp = osm_physp_get_remote(p_physp);
+	if (p_remote_physp) {
+		/* use the available MTU */
+		mtu = ib_port_info_get_mtu_cap(&p_physp->port_info);
+
+		remote_mtu =
+		    ib_port_info_get_mtu_cap(&p_remote_physp->port_info);
+
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Remote port 0x%016" PRIx64 " port = %u : "
+			"MTU = %u. This Port MTU: %u\n",
+			cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
+			osm_physp_get_port_num(p_remote_physp),
+			remote_mtu, mtu);
+
+		if (mtu != remote_mtu) {
+			if (mtu > remote_mtu)
+				mtu = remote_mtu;
+
+			OSM_LOG(p_log, OSM_LOG_VERBOSE,
+				"MTU mismatch between ports."
+				"\n\t\t\t\tPort 0x%016" PRIx64 ", port %u"
+				" and port 0x%016" PRIx64 ", port %u."
+				"\n\t\t\t\tUsing lower MTU of %u\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+				osm_physp_get_port_num(p_physp),
+				cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
+				osm_physp_get_port_num(p_remote_physp),mtu);
+		}
+	} else
+		mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info);
+
+	if (mtu == 0) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG, "ERR 4101: "
+			"Invalid MTU = 0. Forcing correction to 256\n");
+		mtu = 1;
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return (mtu);
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_op_vls(IN osm_log_t * p_log,
+			   IN const osm_subn_t * p_subn,
+			   IN const osm_physp_t * p_physp)
+{
+	const osm_physp_t *p_remote_physp;
+	uint8_t op_vls;
+	uint8_t remote_op_vls;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_remote_physp = osm_physp_get_remote(p_physp);
+	if (p_remote_physp) {
+		/* use the available VLCap */
+		op_vls = ib_port_info_get_vl_cap(&p_physp->port_info);
+
+		remote_op_vls =
+		    ib_port_info_get_vl_cap(&p_remote_physp->port_info);
+
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Remote port 0x%016" PRIx64 " port = 0x%X : "
+			"VL_CAP = %u. This port VL_CAP = %u\n",
+			cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
+			osm_physp_get_port_num(p_remote_physp),
+			remote_op_vls, op_vls);
+
+		if (op_vls != remote_op_vls) {
+			if (op_vls > remote_op_vls)
+				op_vls = remote_op_vls;
+
+			OSM_LOG(p_log, OSM_LOG_VERBOSE,
+				"OP_VLS mismatch between ports."
+				"\n\t\t\t\tPort 0x%016" PRIx64 ", port 0x%X"
+				" and port 0x%016" PRIx64 ", port 0x%X."
+				"\n\t\t\t\tUsing lower OP_VLS of %u\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+				osm_physp_get_port_num(p_physp),
+				cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
+				osm_physp_get_port_num(p_remote_physp), op_vls);
+		}
+	} else
+		op_vls = ib_port_info_get_op_vls(&p_physp->port_info);
+
+	/* 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, "ERR 4102: "
+			"Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n");
+		op_vls = 1;
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return (op_vls);
+}
+
+static inline uint64_t __osm_ptr_to_key(void const *p)
+{
+	uint64_t k = 0;
+
+	memcpy(&k, p, sizeof(void *));
+	return k;
+}
+
+static 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).
+ **********************************************************************/
+static 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);
+
+	/* find the OSM node */
+	p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid);
+	if (!p_port) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4103: "
+			"Failed to find the SM own port by guid\n");
+		status = CL_ERROR;
+		goto Exit;
+	}
+
+	/* get the node of the SM */
+	p_node = p_port->p_node;
+
+	/*
+	   traverse the path adding the nodes to the table
+	   start after the first dummy hop and stop just before the
+	   last one
+	 */
+	for (hop = 1; hop < p_path->hop_count - 1; hop++) {
+		/* go out using the phys port of the path */
+		p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
+
+		/* make sure we got a valid port and it has a remote port */
+		if (!p_physp) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4104: "
+				"DR Traversal stopped on invalid port at hop:%u\n",
+				hop);
+			status = CL_ERROR;
+			goto Exit;
+		}
+
+		/* we track the ports we go out along the path */
+		if (hop > 1)
+			cl_map_insert(p_physp_map, __osm_ptr_to_key(p_physp),
+				      NULL);
+
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Traversed through node: 0x%016" PRIx64
+			" port:%u\n",
+			cl_ntoh64(p_node->node_info.node_guid),
+			p_path->path[hop]);
+
+		if (!(p_physp = osm_physp_get_remote(p_physp))) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4106: "
+				"DR Traversal stopped on missing remote physp at hop:%u\n",
+				hop);
+			status = CL_ERROR;
+			goto Exit;
+		}
+
+		p_node = osm_physp_get_node_ptr(p_physp);
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__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;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp, *p_remote_physp;
+	ib_net64_t port_guid;
+	boolean_t next_list_is_full = TRUE, reached_dest = FALSE;
+	uint8_t num_ports, port_num;
+
+	p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
+	if (!p_nextPortsList)
+		return;
+
+	/*
+	   initialize the map of all port participating in current dr path
+	   not including first and last switches
+	 */
+	cl_map_construct(&physp_map);
+	cl_map_init(&physp_map, 4);
+	cl_map_construct(&visited_map);
+	cl_map_init(&visited_map, 4);
+	p_dr_path = osm_physp_get_dr_path_ptr(p_dest_physp);
+	__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
+	 */
+	cl_list_construct(p_nextPortsList);
+	cl_list_init(p_nextPortsList, 10);
+
+	port_guid = p_subn->sm_port_guid;
+
+	CL_ASSERT(port_guid);
+
+	p_port = osm_get_port_by_guid(p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4105: No SM port object\n");
+		goto Exit;
+	}
+
+	/*
+	   HACK: We are assuming SM is running on HCA, so when getting the default
+	   port we'll get the port connected to the rest of the subnet. If SM is
+	   running on SWITCH - we should try to get a dr path from all switch ports.
+	 */
+	p_physp = p_port->p_physp;
+
+	CL_ASSERT(p_physp);
+
+	cl_list_insert_tail(p_nextPortsList, p_physp);
+
+	while (next_list_is_full == TRUE) {
+		next_list_is_full = FALSE;
+		p_currPortsList = p_nextPortsList;
+		p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
+		if (!p_nextPortsList) {
+			p_nextPortsList = p_currPortsList;
+			goto Exit;
+		}
+		cl_list_construct(p_nextPortsList);
+		cl_list_init(p_nextPortsList, 10);
+		p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList);
+		while (p_physp != NULL) {
+			/* If we are in a switch - need to go out through all
+			   the other physical ports of the switch */
+			num_ports = osm_node_get_num_physp(p_physp->p_node);
+
+			for (port_num = 1; port_num < num_ports; port_num++) {
+				if (osm_node_get_type(p_physp->p_node) ==
+				    IB_NODE_TYPE_SWITCH)
+					p_remote_physp =
+					    osm_node_get_physp_ptr(p_physp->
+								   p_node,
+								   port_num);
+				else
+					/* this is HCA or router - the remote port is just the port connected
+					   on the other side */
+					p_remote_physp =
+					    p_physp->p_remote_physp;
+
+				/*
+				   make sure that all of the following occurred:
+				   1. The port isn't NULL
+				   2. This is not the port we came from
+				   3. The port is not in the physp_map
+				   4. This port haven't been visited before
+				 */
+				if (p_remote_physp &&
+				    p_remote_physp != p_physp &&
+				    cl_map_get(&physp_map,
+					       __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)
+		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);
+	/*
+	   (14.2.5.7) - the block number valid values are 0-2047, and are
+	   further limited by the size of the P_Key table specified by
+	   the PartitionCap on the node.
+	 */
+	if (!p_physp->p_node->sw || p_physp->port_num == 0)
+		/*
+		   The maximum blocks is defined in the node info: partition cap
+		   for CA, router, and switch management ports.
+		 */
+		max_blocks =
+		    (cl_ntoh16(p_physp->p_node->node_info.partition_cap) +
+		     IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
+		    / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+	else
+		/*
+		   This is a switch, and not a management port. The maximum
+		   blocks is defined in the switch info: partition enforcement
+		   cap.
+		 */
+		max_blocks =
+		    (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) +
+		     IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
+		     1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+
+	if (block_num >= max_blocks) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4108: "
+			"Got illegal set for block number:%u "
+			"For GUID: %" PRIx64 " port number:%u\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);
+}
diff --git a/opensm/osm_port_info_rcv.c b/opensm/osm_port_info_rcv.c
new file mode 100644
index 0000000..02ad586
--- /dev/null
+++ b/opensm/osm_port_info_rcv.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.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 <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_ucast_mgr.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_set_sm(IN osm_sm_t * sm,
+		    IN osm_physp_t * const p_physp)
+{
+	osm_bind_handle_t h_bind;
+	osm_dr_path_t *p_dr_path;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"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(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void pi_rcv_check_and_fix_lid(osm_log_t *log, ib_port_info_t * const pi,
+				     osm_physp_t * p)
+{
+	if (cl_ntoh16(pi->base_lid) > IB_LID_UCAST_END_HO) {
+		OSM_LOG(log, OSM_LOG_ERROR, "ERR 0F04: "
+			"Got invalid base LID %u from the network. "
+			"Corrected to %u.\n", cl_ntoh16(pi->base_lid),
+			cl_ntoh16(p->port_info.base_lid));
+		pi->base_lid = p->port_info.base_lid;
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_endport(IN osm_sm_t * sm,
+			     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(sm->p_log);
+
+	port_guid = osm_physp_get_port_guid(p_physp);
+
+	/* HACK extended port 0 should be handled too! */
+	if (osm_physp_get_port_num(p_physp) != 0) {
+		/* track the minimal endport MTU and rate */
+		mtu = ib_port_info_get_mtu_cap(p_pi);
+		if (mtu < sm->p_subn->min_ca_mtu) {
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"Setting endport minimal MTU to:%u defined by port:0x%"
+				PRIx64 "\n", mtu, cl_ntoh64(port_guid));
+			sm->p_subn->min_ca_mtu = mtu;
+		}
+
+		rate = ib_port_info_compute_rate(p_pi);
+		if (rate < sm->p_subn->min_ca_rate) {
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"Setting endport minimal rate to:%u defined by port:0x%"
+				PRIx64 "\n", rate, cl_ntoh64(port_guid));
+			sm->p_subn->min_ca_rate = rate;
+		}
+	}
+
+	if (port_guid == sm->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(sm, p_physp);
+	} else {
+		p_sm_tbl = &sm->p_subn->sm_guid_tbl;
+		if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) {
+			/*
+			 * Before querying the SM - we want to make sure we
+			 * clean its state, so if the querying fails we
+			 * recognize that this SM is not active.
+			 */
+			p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid);
+			if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
+				/* clean it up */
+				p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state;
+			if (sm->p_subn->opt.ignore_other_sm)
+				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+					"Ignoring SM on port 0x%" PRIx64 "\n",
+					cl_ntoh64(port_guid));
+			else {
+				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+					"Detected another SM. Requesting SMInfo"
+					"\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;
+				context.smi_context.port_guid = port_guid;
+				status = osm_req_get(sm,
+						     osm_physp_get_dr_path_ptr
+						     (p_physp),
+						     IB_MAD_ATTR_SM_INFO, 0,
+						     CL_DISP_MSGID_NONE,
+						     &context);
+
+				if (status != IB_SUCCESS)
+					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+						"ERR 0F05: "
+						"Failure requesting SMInfo (%s)\n",
+						ib_get_err_str(status));
+			}
+		} else {
+			p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_tbl, port_guid);
+			if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
+				free(p_sm);
+		}
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_pi_rcv_process_switch_port(IN osm_sm_t * sm,
+				 IN osm_node_t * const p_node,
+				 IN osm_physp_t * const p_physp,
+				 IN 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;
+	uint8_t port_num;
+	uint8_t remote_port_num;
+	osm_dr_path_t path;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	   Check the state of the physical port.
+	   If there appears to be something on the other end of the wire,
+	   then ask for NodeInfo.  Ignore the switch management port.
+	 */
+	port_num = osm_physp_get_port_num(p_physp);
+	/* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch,
+	   and we got switchInfo of our local switch. Do not continue
+	   probing through the switch. */
+	if (port_num != 0 && sm->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) {
+				p_remote_node =
+				    osm_physp_get_node_ptr(p_remote_physp);
+				remote_port_num =
+				    osm_physp_get_port_num(p_remote_physp);
+
+				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+					"Unlinking local node 0x%" PRIx64
+					", port %u"
+					"\n\t\t\t\tand remote node 0x%" PRIx64
+					", port %u\n",
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_node)), port_num,
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_remote_node)),
+					remote_port_num);
+
+				if (sm->ucast_mgr.cache_valid)
+					osm_ucast_cache_add_link(&sm->ucast_mgr,
+								 p_physp,
+								 p_remote_physp);
+
+				osm_node_unlink(p_node, (uint8_t) port_num,
+						p_remote_node,
+						(uint8_t) remote_port_num);
+
+			}
+			break;
+
+		case IB_LINK_INIT:
+		case IB_LINK_ARMED:
+		case IB_LINK_ACTIVE:
+			/*
+			   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));
+
+				memset(&context, 0, sizeof(context));
+				context.ni_context.node_guid =
+				    osm_node_get_node_guid(p_node);
+				context.ni_context.port_num =
+				    osm_physp_get_port_num(p_physp);
+
+				status = osm_req_get(sm,
+						     &path,
+						     IB_MAD_ATTR_NODE_INFO,
+						     0,
+						     CL_DISP_MSGID_NONE,
+						     &context);
+
+				if (status != IB_SUCCESS)
+					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+						"ERR 0F02: "
+						"Failure initiating NodeInfo request (%s)\n",
+						ib_get_err_str(status));
+			} else
+				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+					"Skipping SMP responder port %u\n",
+					p_pi->local_port_num);
+			break;
+
+		default:
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: "
+				"Unknown link state = %u, port = %u\n",
+				ib_port_info_get_port_state(p_pi),
+				p_pi->local_port_num);
+			break;
+		}
+	}
+
+	if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw &&
+	    p_node->sw->need_update == 1 && port_num != 0)
+		p_node->sw->need_update = 0;
+
+	if (p_physp->need_update)
+		sm->p_subn->ignore_existing_lfts = TRUE;
+
+	if (port_num == 0)
+		pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
+
+	/*
+	   Update the PortInfo attribute.
+	 */
+	osm_physp_set_port_info(p_physp, p_pi);
+
+	if (port_num == 0) {
+		/* 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(sm, p_physp, p_pi);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm,
+				       IN osm_node_t * const p_node,
+				       IN osm_physp_t * const p_physp,
+				       IN ib_port_info_t * const p_pi)
+{
+	OSM_LOG_ENTER(sm->p_log);
+
+	UNUSED_PARAM(p_node);
+
+	pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
+
+	osm_physp_set_port_info(p_physp, p_pi);
+
+	__osm_pi_rcv_process_endport(sm, p_physp, p_pi);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+#define IBM_VENDOR_ID  (0x5076)
+/**********************************************************************
+ **********************************************************************/
+static void get_pkey_table(IN osm_log_t * p_log,
+			   IN osm_sm_t * sm,
+			   IN osm_node_t * 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);
+
+	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(sm, &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, "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 osm_sm_t * sm,
+				      IN osm_node_t * const p_node,
+				      IN osm_physp_t * const p_physp)
+{
+	OSM_LOG_ENTER(sm->p_log);
+
+	get_pkey_table(sm->p_log, sm, p_node, p_physp);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_pi_rcv_process_set(IN osm_sm_t * sm, IN osm_node_t * const p_node,
+		       IN const uint8_t port_num, IN osm_madw_t * const p_madw)
+{
+	osm_physp_t *p_physp;
+	ib_net64_t port_guid;
+	ib_smp_t *p_smp;
+	ib_port_info_t *p_pi;
+	osm_pi_context_t *p_context;
+	osm_log_level_t level;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_context = osm_madw_get_pi_context_ptr(p_madw);
+
+	CL_ASSERT(p_node);
+
+	p_physp = osm_node_get_physp_ptr(p_node, port_num);
+	CL_ASSERT(p_physp);
+
+	port_guid = osm_physp_get_port_guid(p_physp);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_pi = (ib_port_info_t *) ib_smp_get_payload_ptr(p_smp);
+
+	/* check for error */
+	if (cl_ntoh16(p_smp->status) & 0x7fff) {
+		/* If port already ACTIVE, don't treat status 7 as error */
+		if (p_context->active_transition &&
+		    (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) {
+			level = OSM_LOG_INFO;
+			OSM_LOG(sm->p_log, OSM_LOG_INFO,
+				"Received error status 0x%x for SetResp() during ACTIVE transition\n",
+				cl_ntoh16(p_smp->status) & 0x7fff);
+			/* Should there be a subsequent Get to validate that port is ACTIVE ? */
+		} else {
+			level = OSM_LOG_ERROR;
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F10: "
+				"Received error status for SetResp()\n");
+		}
+		osm_dump_port_info(sm->p_log,
+				   osm_node_get_node_guid(p_node),
+				   port_guid, port_num, p_pi, level);
+	}
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Received logical SetResp() for GUID 0x%" PRIx64
+		", port num %u"
+		"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+		" TID 0x%" PRIx64 "\n",
+		cl_ntoh64(port_guid), port_num,
+		cl_ntoh64(osm_node_get_node_guid(p_node)),
+		cl_ntoh64(p_smp->trans_id));
+
+	osm_physp_set_port_info(p_physp, p_pi);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pi_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_port_info_t *p_pi;
+	ib_smp_t *p_smp;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_dr_path_t *p_dr_path;
+	osm_node_t *p_node;
+	osm_pi_context_t *p_context;
+	ib_net64_t port_guid;
+	ib_net64_t node_guid;
+	uint8_t port_num;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(sm);
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_context = osm_madw_get_pi_context_ptr(p_madw);
+	p_pi = (ib_port_info_t *) ib_smp_get_payload_ptr(p_smp);
+
+	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);
+
+	port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);
+
+	port_guid = p_context->port_guid;
+	node_guid = p_context->node_guid;
+
+	osm_dump_port_info(sm->p_log,
+			   node_guid, port_guid, port_num, p_pi, OSM_LOG_DEBUG);
+
+	/* 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(sm->p_log, OSM_LOG_DEBUG,
+			"Client reregister received on response\n");
+		ib_port_info_set_client_rereg(p_pi, 0);
+	}
+
+	/*
+	   we might get a response during a light sweep looking for a change in
+	   the status of a remote port that did not respond in earlier sweeps.
+	   So if the context of the Get was light_sweep - we do not need to
+	   do anything with the response - just flag that we need a heavy sweep
+	 */
+	if (p_context->light_sweep == TRUE) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Got light sweep response from remote port of parent node "
+			"GUID 0x%" PRIx64 " port 0x%016" PRIx64
+			", Commencing heavy sweep\n",
+			cl_ntoh64(node_guid), cl_ntoh64(port_guid));
+		sm->p_subn->force_heavy_sweep = TRUE;
+		sm->p_subn->ignore_existing_lfts = TRUE;
+		goto Exit;
+	}
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		CL_PLOCK_RELEASE(sm->p_lock);
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
+			"No port object for port with GUID 0x%" PRIx64
+			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+			", TID 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid),
+			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+		goto Exit;
+	}
+
+	p_node = p_port->p_node;
+	CL_ASSERT(p_node);
+
+	/*
+	   If 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(sm, p_node, port_num, p_madw);
+	else {
+		p_port->discovery_count++;
+
+		/*
+		   This PortInfo arrived because we did a Get() method,
+		   most likely due to a subnet sweep in progress.
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Discovered port num %u with GUID 0x%" PRIx64
+			" for parent node GUID 0x%" PRIx64
+			", TID 0x%" PRIx64 "\n",
+			port_num, cl_ntoh64(port_guid),
+			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+
+		/*
+		   Determine if we encountered a new Physical Port.
+		   If so, initialize the new Physical Port then
+		   continue processing as normal.
+		 */
+		if (!p_physp) {
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"Initializing port number %u\n", port_num);
+			p_physp = &p_node->physp_table[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);
+		} 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);
+		}
+
+		/* if port just inited or reached INIT state (external reset)
+		   request update for port related tables */
+		p_physp->need_update =
+		    (ib_port_info_get_port_state(p_pi) == IB_LINK_INIT ||
+		     p_physp->need_update > 1) ? 1 : 0;
+
+		switch (osm_node_get_type(p_node)) {
+		case IB_NODE_TYPE_CA:
+		case IB_NODE_TYPE_ROUTER:
+			__osm_pi_rcv_process_ca_or_router_port(sm,
+							       p_node, p_physp,
+							       p_pi);
+			break;
+		case IB_NODE_TYPE_SWITCH:
+			__osm_pi_rcv_process_switch_port(sm,
+							 p_node, p_physp, p_pi);
+			break;
+		default:
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
+				"Unknown node type %u with GUID 0x%" PRIx64
+				"\n", osm_node_get_type(p_node),
+				cl_ntoh64(node_guid));
+			break;
+		}
+
+		/*
+		   Get the tables on the physp.
+		 */
+		if (p_physp->need_update || sm->p_subn->need_update)
+			__osm_pi_rcv_get_pkey_slvl_vla_tables(sm, p_node,
+							      p_physp);
+
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+Exit:
+	/*
+	   Release the lock before jumping here!!
+	 */
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_prtn.c b/opensm/osm_prtn.c
new file mode 100644
index 0000000..be51410
--- /dev/null
+++ b/opensm/osm_prtn.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_prtn_t.
+ * This object represents an IBA partition.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	cl_map_t *p_tbl;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+
+	p_port = osm_get_port_by_guid(p_subn, guid);
+	if (!p_port) {
+		OSM_LOG(p_log, OSM_LOG_VERBOSE,
+			"port 0x%" PRIx64 " not found\n", cl_ntoh64(guid));
+		return status;
+	}
+
+	p_physp = p_port->p_physp;
+	if (!p_physp) {
+		OSM_LOG(p_log, OSM_LOG_VERBOSE,
+			"no physical for port 0x%" PRIx64 "\n",
+			cl_ntoh64(guid));
+		return status;
+	}
+
+	if (cl_map_remove(&p->part_guid_tbl, guid) ||
+	    cl_map_remove(&p->full_guid_tbl, guid)) {
+		OSM_LOG(p_log, OSM_LOG_VERBOSE,
+			"port 0x%" PRIx64 " already in "
+			"partition \'%s\' (0x%04x). Will overwrite\n",
+			cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey));
+	}
+
+	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,
+				     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 hop_limit;
+
+	pkey = p->pkey | cl_hton16(0x8000);
+	if (!scope)
+		scope = OSM_DEFAULT_MGRP_SCOPE;
+	hop_limit = (scope == IB_MC_SCOPE_LINK_LOCAL) ? 0 : IB_HOPLIMIT_MAX;
+
+	memset(&mc_rec, 0, sizeof(mc_rec));
+
+	mc_rec.mgid = 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 = p_subn->opt.subnet_timeout;
+	mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p->sl, 0, hop_limit);
+	/* Scope in MCMemberRecord (if present) needs to be consistent with MGID */
+	mc_rec.scope_state = ib_member_set_scope_state(scope, IB_MC_REC_STATE_FULL_MEMBER);
+	ib_mgid_set_scope(&mc_rec.mgid, scope);
+
+	/* don't update rate, mtu */
+	comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL |
+	    IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
+	status = osm_mcmr_rcv_find_or_create_new_mgrp(p_sa, comp_mask, &mc_rec,
+						      &p_mgrp);
+	if (!p_mgrp || status != IB_SUCCESS)
+		OSM_LOG(p_log, OSM_LOG_ERROR,
+			"Failed to create MC group with pkey 0x%04x\n",
+			cl_ntoh16(pkey));
+	if (p_mgrp) {
+		p_mgrp->well_known = TRUE;
+		p->mlid = p_mgrp->mlid;
+	}
+
+	/* 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 (if present) needs to be consistent with MGID */
+	mc_rec.scope_state = ib_member_set_scope_state(scope, IB_MC_REC_STATE_FULL_MEMBER);
+	ib_mgid_set_scope(&mc_rec.mgid, scope);
+
+	status = osm_mcmr_rcv_find_or_create_new_mgrp(p_sa, comp_mask, &mc_rec,
+						      &p_mgrp);
+	if (p_mgrp) {
+		p_mgrp->well_known = TRUE;
+		if (!p->mlid)
+			p->mlid = p_mgrp->mlid;
+	}
+
+	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;
+}
+
+osm_prtn_t *osm_prtn_find_by_name(osm_subn_t * p_subn, const char *name)
+{
+	cl_map_item_t *p_next;
+	osm_prtn_t *p;
+
+	p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
+	while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
+		p = (osm_prtn_t *) p_next;
+		p_next = cl_qmap_next(&p->map_item);
+		if (!strncmp(p->name, name, sizeof(p->name)))
+			return p;
+	}
+
+	return NULL;
+}
+
+osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn,
+			      const char *name, uint16_t pkey)
+{
+	osm_prtn_t *p = NULL, *p_check;
+
+	pkey &= cl_hton16((uint16_t) ~ 0x8000);
+
+	if (!pkey) {
+		if (name && (p = osm_prtn_find_by_name(p_subn, name)))
+			return p;
+		if (!(pkey = __generate_pkey(p_subn)))
+			return NULL;
+	}
+
+	p = osm_prtn_new(name, pkey);
+	if (!p) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "Unable to create"
+			" partition \'%s\' (0x%04x)\n", name, cl_ntoh16(pkey));
+		return NULL;
+	}
+
+	p_check = (osm_prtn_t *) cl_qmap_insert(&p_subn->prtn_pkey_tbl,
+						p->pkey, &p->map_item);
+	if (p != p_check) {
+		OSM_LOG(p_log, OSM_LOG_VERBOSE, "Duplicated partition"
+			" definition: \'%s\' (0x%04x) prev name \'%s\'"
+			".  Will use it\n",
+			name, cl_ntoh16(pkey), p_check->name);
+		osm_prtn_delete(&p);
+		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, 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 : OSM_DEFAULT_PARTITION_CONFIG_FILE;
+	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, "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;
+}
diff --git a/opensm/osm_prtn_config.c b/opensm/osm_prtn_config.c
new file mode 100644
index 0000000..9511608
--- /dev/null
+++ b/opensm/osm_prtn_config.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2006-2007 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of opensm partition management configuration
+ */
+
+#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>
+
+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_mask;
+	boolean_t full;
+};
+
+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,
+					    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;
+	unsigned int scope;
+
+	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.qos && conf->sl != OSM_DEFAULT_SL) {
+		OSM_LOG(conf->p_log, OSM_LOG_DEBUG, "Overriding SL %d"
+			" to default SL %d on partition %s"
+			" as QoS is not enabled.\n",
+			conf->sl, OSM_DEFAULT_SL, name);
+		conf->sl = OSM_DEFAULT_SL;
+	}
+	conf->p_prtn->sl = (uint8_t) conf->sl;
+
+	if (!conf->is_ipoib)
+		return 0;
+
+	if (!conf->scope_mask) {
+		osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
+				     (uint8_t) conf->rate,
+				     (uint8_t) conf->mtu,
+				     0);
+		return 0;
+	}
+
+	for (scope = 0; scope < 16; scope++) {
+		if (((1<<scope) & conf->scope_mask) == 0)
+			continue;
+
+		osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
+				     (uint8_t) conf->rate,
+				     (uint8_t) conf->mtu,
+				     (uint8_t) 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)) {
+		unsigned int scope;
+		if (!val || (scope = strtoul(val, NULL, 0)) == 0 || scope > 0xF)
+			OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
+				"PARSE WARN: line %d: "
+				"flag \'scope\' requires valid value"
+				" - skipped\n", lineno);
+		else
+			conf->scope_mask |= (1<<scope);
+	} 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 if (!strncmp(flag, "defmember", len)) {
+		if (!val || (strncmp(val, "limited", strlen(val))
+			     && strncmp(val, "full", strlen(val))))
+			OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
+				"PARSE WARN: line %d: "
+				"flag \'defmember\' requires valid value (limited or full)"
+				" - skipped\n", lineno);
+		else
+			conf->full = strncmp(val, "full", strlen(val)) == 0;
+	} 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 = conf->full;
+
+	if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
+		return 0;
+
+	if (flag) {
+		/* reset default membership to limited */
+		full = FALSE;
+		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 = strtoull(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;
+	conf->full = FALSE;
+	return conf;
+}
+
+static int flush_part_conf(struct part_conf *conf)
+{
+	memset(conf, 0, sizeof(*conf));
+	return 0;
+}
+
+static int parse_part_conf(struct part_conf *conf, char *str, int lineno)
+{
+	int ret, len = 0;
+	char *name, *id, *flag, *flval;
+	char *q, *p;
+
+	p = str;
+	if (*p == '\t' || *p == '\0' || *p == '\n')
+		p++;
+
+	len += (int)(p - str);
+	str = p;
+
+	if (conf->p_prtn)
+		goto skip_header;
+
+	q = strchr(p, ':');
+	if (!q) {
+		OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: "
+			"no partition definition found\n", lineno);
+		fprintf(stderr, "\nPARSE ERROR: line %d: "
+			"no partition definition found\n", lineno);
+		return -1;
+	}
+
+	*q++ = '\0';
+	str = q;
+
+	name = id = flag = flval = NULL;
+
+	q = strchr(p, ',');
+	if (q)
+		*q = '\0';
+
+	ret = parse_name_token(p, &name, &id);
+	p += ret;
+	len += ret;
+
+	while (q) {
+		flag = flval = NULL;
+		q = strchr(p, ',');
+		if (q)
+			*q++ = '\0';
+		ret = parse_name_token(p, &flag, &flval);
+		if (!flag) {
+			OSM_LOG(conf->p_log, OSM_LOG_ERROR,
+				"PARSE ERROR: line %d: "
+				"bad partition flags\n", lineno);
+			fprintf(stderr, "\nPARSE ERROR: line %d: "
+				"bad partition flags\n", lineno);
+			return -1;
+		}
+		p += ret;
+		len += ret;
+		partition_add_flag(lineno, conf, flag, flval);
+	}
+
+	if (p != str || (partition_create(lineno, conf,
+					  name, id, flag, flval) < 0)) {
+		OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: "
+			"bad partition definition\n", lineno);
+		fprintf(stderr, "\nPARSE ERROR: line %d: "
+			"bad partition definition\n", lineno);
+		return -1;
+	}
+
+skip_header:
+	do {
+		name = flag = NULL;
+		q = strchr(p, ',');
+		if (q)
+			*q++ = '\0';
+		ret = parse_name_token(p, &name, &flag);
+		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,
+			"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;
+}
diff --git a/opensm/osm_qos.c b/opensm/osm_qos.c
new file mode 100644
index 0000000..b451c25
--- /dev/null
+++ b/opensm/osm_qos.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM QoS infrastructure primitives
+ */
+
+#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>
+#include <opensm/osm_qos_policy.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_sm_t * sm,
+						osm_physp_t * p,
+						uint8_t port_num,
+						unsigned force_update,
+						const ib_vl_arb_table_t *
+						table_block,
+						unsigned block_length,
+						unsigned block_num)
+{
+	ib_vl_arb_table_t block;
+	osm_madw_context_t context;
+	uint32_t attr_mod;
+	unsigned vl_mask, i;
+
+	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;
+
+	memset(&block, 0, sizeof(block));
+	memcpy(&block, table_block, block_length * sizeof(block.vl_entry[0]));
+	for (i = 0; i < block_length; i++)
+		block.vl_entry[i].vl &= vl_mask;
+
+	if (!force_update &&
+	    !memcmp(&p->vl_arb[block_num], &block,
+		    block_length * sizeof(block.vl_entry[0])))
+		return IB_SUCCESS;
+
+	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(sm, 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_sm_t * sm,
+				    osm_physp_t * p, uint8_t port_num,
+				    unsigned force_update,
+				    const struct qos_config *qcfg)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	ib_port_info_t *p_pi = &p->port_info;
+	unsigned len;
+
+	if (p_pi->vl_arb_low_cap > 0) {
+		len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
+		    p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+		if ((status = vlarb_update_table_block(sm, p, port_num,
+						       force_update,
+						       &qcfg->vlarb_low[0],
+						       len, 0)) != IB_SUCCESS)
+			return status;
+	}
+	if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
+		len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+		if ((status = vlarb_update_table_block(sm, p, port_num,
+						       force_update,
+						       &qcfg->vlarb_low[1],
+						       len, 1)) != IB_SUCCESS)
+			return status;
+	}
+	if (p_pi->vl_arb_high_cap > 0) {
+		len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
+		    p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+		if ((status = vlarb_update_table_block(sm, p, port_num,
+						       force_update,
+						       &qcfg->vlarb_high[0],
+						       len, 2)) != IB_SUCCESS)
+			return status;
+	}
+	if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
+		len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+		if ((status = vlarb_update_table_block(sm, p, port_num,
+						       force_update,
+						       &qcfg->vlarb_high[1],
+						       len, 3)) != IB_SUCCESS)
+			return status;
+	}
+
+	return status;
+}
+
+static ib_api_status_t sl2vl_update_table(osm_sm_t * sm,
+					  osm_physp_t * p, uint8_t in_port,
+					  uint8_t out_port,
+					  unsigned force_update,
+					  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;
+	unsigned vl_mask;
+	uint8_t vl1, vl2;
+	int i;
+
+	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;
+
+	for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) {
+		vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4;
+		vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf;
+		if (vl1 != 15)
+			vl1 &= vl_mask;
+		if (vl2 != 15)
+			vl2 &= vl_mask;
+		tbl.raw_vl_by_sl[i] = (vl1 << 4) | vl2;
+	}
+
+	if (!force_update && (p_tbl = osm_physp_get_slvl_tbl(p, in_port)) &&
+	    !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(sm, 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_sm_t * sm, osm_port_t * p_port,
+				    osm_physp_t * p, uint8_t port_num,
+				    unsigned force_update,
+				    const struct qos_config *qcfg)
+{
+	ib_api_status_t status;
+	uint8_t i, num_ports;
+	osm_physp_t *p_physp;
+
+	if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) {
+		if (ib_port_info_get_vl_cap(&p->port_info) == 1) {
+			/* Check port 0's capability mask */
+			p_physp = p_port->p_physp;
+			if (!
+			    (p_physp->port_info.
+			     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->port_info.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(sm, p, i, port_num,
+				       force_update, &qcfg->sl2vl);
+		if (status != IB_SUCCESS)
+			return status;
+	}
+
+	return IB_SUCCESS;
+}
+
+static ib_api_status_t qos_physp_setup(osm_log_t * p_log, osm_sm_t * sm,
+				       osm_port_t * p_port, osm_physp_t * p,
+				       uint8_t port_num,
+				       unsigned force_update,
+				       const struct qos_config *qcfg)
+{
+	ib_api_status_t status;
+
+	/* OpVLs should be ok at this moment - just use it */
+
+	/* setup VL high limit on the physp later to be updated by link mgr */
+	p->vl_high_limit = qcfg->vl_high_limit;
+
+	/* setup VLArbitration */
+	status = vlarb_update(sm, p, port_num, force_update, qcfg);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "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(sm, p_port, p, port_num, force_update, qcfg);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "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;
+	unsigned force_update;
+	uint8_t i;
+
+	if (!p_osm->subn.opt.qos)
+		return OSM_SIGNAL_DONE;
+
+	OSM_LOG_ENTER(&p_osm->log);
+
+	qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options,
+			 &p_osm->subn.opt.qos_options);
+	qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options,
+			 &p_osm->subn.opt.qos_options);
+	qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options,
+			 &p_osm->subn.opt.qos_options);
+	qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options,
+			 &p_osm->subn.opt.qos_options);
+
+	cl_plock_excl_acquire(&p_osm->lock);
+
+	/* read QoS policy config file */
+	osm_qos_parse_policy_file(&p_osm->subn);
+
+	p_tbl = &p_osm->subn.port_guid_tbl;
+	p_next = cl_qmap_head(p_tbl);
+	while (p_next != cl_qmap_end(p_tbl)) {
+		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_node_get_num_physp(p_node);
+			for (i = 1; i < num_physp; i++) {
+				p_physp = osm_node_get_physp_ptr(p_node, i);
+				if (!p_physp)
+					continue;
+				force_update = p_physp->need_update ||
+				    p_osm->subn.need_update;
+				status =
+				    qos_physp_setup(&p_osm->log, &p_osm->sm,
+						    p_port, p_physp, i,
+						    force_update, &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 = p_port->p_physp;
+		if (!p_physp)
+			continue;
+
+		force_update = p_physp->need_update || p_osm->subn.need_update;
+		status = qos_physp_setup(&p_osm->log, &p_osm->sm,
+					 p_port, p_physp, 0, force_update, 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;
+
+	if (opt->high_limit >= 0)
+		cfg->vl_high_limit = (uint8_t) opt->high_limit;
+	else
+		cfg->vl_high_limit = (uint8_t) dflt->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]);
+
+}
diff --git a/opensm/osm_qos_parser_l.c b/opensm/osm_qos_parser_l.c
new file mode 100644
index 0000000..07a5cbb
--- /dev/null
+++ b/opensm/osm_qos_parser_l.c
@@ -0,0 +1,2672 @@
+
+#line 3 "osm_qos_parser_l.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 82
+#define YY_END_OF_BUFFER 83
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[551] =
+    {   0,
+        0,    0,   83,   81,    3,    4,   81,   81,   79,   78,
+       76,   75,   75,   77,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,    3,    2,    0,   80,    0,    1,
+       75,    0,    0,    0,   57,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   74,   60,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,   45,    0,    0,   39,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   67,    0,    0,
+        0,   65,   59,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   45,    0,   39,    0,   34,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   69,    0,
+        0,   67,    0,    0,    0,   65,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,   40,    0,    0,    0,
+       33,    0,    0,    0,    0,    0,   54,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   34,    0,    0,
+
+        0,    0,    0,    0,    0,    0,   72,    0,    0,   69,
+        0,   56,    0,    0,   58,    0,    0,    0,    0,    0,
+        0,   40,    0,   35,    0,   33,    0,    0,    0,    0,
+       54,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       72,    0,    0,    0,    0,    0,    0,   43,    0,    0,
+        0,    0,    0,   35,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   51,    0,    0,    0,    0,    0,   63,    0,
+        0,    0,   61,    0,    0,    0,    0,    0,    0,    0,
+
+       43,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    5,    0,
+        0,    0,    0,   51,    0,    0,    0,    0,    0,    0,
+        0,   61,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,   23,    0,   11,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       73,    0,    0,    0,    0,    0,    0,   41,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   46,    0,   32,
+        0,    0,   31,    0,   49,    9,    0,   29,    0,   30,
+
+        0,   50,    0,   21,    0,    0,    0,    0,    0,    0,
+        0,    0,   37,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   41,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   46,   32,    0,   31,   49,    7,   29,
+       30,   50,    0,    0,    0,   47,    0,   53,   19,    0,
+        0,    0,   36,   37,   15,    0,    0,    0,    0,   68,
+       66,    0,    0,   42,    0,   52,    0,    0,    0,    0,
+        6,    0,    0,    0,    0,    0,   48,    0,    0,   47,
+       53,    0,   44,   17,    0,   36,   13,    0,    0,   70,
+        0,   42,   52,    0,   24,    0,   12,    0,    0,    0,
+
+        0,   48,    0,    0,   44,    0,   62,    0,    0,   10,
+       22,    0,    0,    0,    0,    0,    0,   27,    0,   38,
+        0,    0,    8,    0,   20,    0,   16,    0,    0,   55,
+       25,   38,    0,    0,    0,   18,   14,   55,    0,    0,
+        0,    0,    0,   28,    0,    0,   26,   64,   71,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
+        1,    6,    1,    7,    8,    1,    1,    9,   10,   11,
+       10,   10,   10,   10,   10,   10,   10,   12,    1,    1,
+        1,    1,    1,    1,   13,   14,   15,   16,   17,   18,
+        1,   19,   20,    1,    1,   21,    1,   22,   23,   24,
+        1,   25,   26,   27,   28,    1,   29,   30,   31,    1,
+        1,    1,    1,    1,    1,    1,   32,   33,   34,   35,
+
+       36,   37,   38,   39,   40,    1,   41,   42,   43,   44,
+       45,   46,   47,   48,   49,   50,   51,   52,   53,   30,
+       54,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[55] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    2,
+        2,    1,    2,    2,    2,    2,    2,    2,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    2,    2,    2,    2,    2,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[554] =
+    {   0,
+        0,    0,  759,  760,   53,  760,  754,  754,  760,  760,
+      760,   48,   51,  760,   42,   53,   51,   43,   56,   77,
+       54,   54,  712,  707,  706,  703,   38,   63,  707,   84,
+      115,  706,  701,  707,   71,  760,  744,  760,  744,  760,
+       71,    0,   76,   68,  760,   87,   88,   92,   77,   86,
+       93,   94,   96,  101,  698,  109,  710,  699,  698,  691,
+      698,  705,  104,  703,  690,  688,  686,  113,  154,  684,
+      133,  698,  115,    0,  760,  141,  140,  129,  134,  168,
+      135,  169,  146,  171,  140,  688,  682,  723,  687,  678,
+      720,  691,  690,  684,  674,  684,  668,  671,  712,  683,
+
+      666,  172,  665,  714,  667,  175,  712,  177,  674,  664,
+      184,  186,  164,  179,  192,  193,  194,  709,  180,  196,
+      199,  708,  760,  200,  204,  194,  660,  668,  171,  209,
+      661,  664,  212,  697,  668,  663,  694,  217,  693,  188,
+      692,  659,  656,  695,  662,  693,  231,  692,  653,  659,
+      211,  650,  654,  657,  204,  240,  246,  224,  686,  225,
+      642,  684,  216,  232,  640,  682,  236,  651,  230,  633,
+      637,  635,  634,  636,  635,  253,  674,  254,  635,  260,
+      672,  623,  622,  621,  637,  261,  667,  206,  626,  631,
+      634,  629,  622,  621,  628,  653,  624,  657,  620,  649,
+
+      620,  607,  606,  224,  273,  257,  651,  265,  607,  649,
+      602,  760,  601,  600,  760,  275,  615,  598,  596,  633,
+      611,  640,  277,  639,  597,  637,  584,  629,  596,  595,
+      632,  233,  601,  600,  579,  580,  579,  582,  587,  590,
+      241,  280,  586,  255,  570,  571,  584,  286,  266,  580,
+      618,  571,  568,  567,  578,  294,  258,  613,  564,  563,
+      604,  559,  562,  607,  568,  561,  564,  560,  554,  558,
+      562,  558,  551,  563,  564,  546,  547,  552,  586,  559,
+      560,  297,  589,  582,  549,  543,  553,  554,  760,  545,
+      548,  298,  581,  546,  531,  572,  571,  542,  529,  531,
+
+      573,  534,  565,  271,  530,  538,  520,  533,  528,  523,
+      517,  514,  529,  527,  513,  519,  521,  513,  760,  518,
+      517,  511,  522,  552,  511,  514,  498,  505,  516,  514,
+      497,  544,  491,  536,  499,  498,  491,  495,  305,  494,
+      500,  501,  504,  499,  492,  525,  524,  313,  314,  494,
+      316,  317,  484,  319,  321,  322,  293,  521,  760,  478,
+      492,  480,  483,  484,  484,  325,  476,  479,  484,  511,
+      760,  474,  466,  465,  507,  471,  328,  511,  468,  463,
+      458,  459,  458,  461,  286,  289,  339,  504,  341,  503,
+      468,  342,  501,  343,  500,  452,  344,  498,  345,  497,
+
+      346,  496,  453,  760,  448,  347,  348,  459,  458,  450,
+      350,  359,  490,  455,  454,  481,  442,  436,  443,  442,
+      438,  361,  481,  362,  437,  445,  446,  428,  429,  443,
+      444,  441,  442,  471,  470,  363,  469,  468,  760,  467,
+      466,  465,  434,  414,  364,  462,  365,  461,  760,  366,
+      422,  367,  459,  458,  760,  410,  418,  412,  413,  760,
+      760,  410,  368,  452,  370,  451,  401,  409,  411,  403,
+      760,  403,  414,  401,  412,  379,  442,  400,  400,  439,
+      438,  381,  437,  760,  388,  435,  760,  401,  387,  760,
+      386,  431,  430,  385,  381,  421,  760,  382,  385,  380,
+
+      383,  422,  387,  386,  419,  382,  760,  370,  364,  364,
+      760,  364,  375,  374,  373,  372,  383,  358,  384,  404,
+      397,  396,  760,  352,  760,  353,  760,  352,  385,  398,
+      760,  397,  360,  354,  348,  760,  760,  387,  337,  281,
+      266,  253,  236,  161,   75,   42,  760,  760,  760,  760,
+      415,  417,   63
+    } ;
+
+static yyconst flex_int16_t yy_def[554] =
+    {   0,
+      550,    1,  550,  550,  550,  550,  551,  552,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  551,  550,  552,  550,
+      550,  553,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  553,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,    0,
+      550,  550,  550
+    } ;
+
+static yyconst flex_int16_t yy_nxt[815] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+       13,   14,   15,    4,   16,   17,    4,    4,    4,   18,
+        4,    4,    4,    4,   19,   20,    4,    4,    4,    4,
+        4,   21,    4,   16,   22,   23,   24,   25,    4,   18,
+        4,    4,   26,   27,    4,   28,   29,   30,   31,   32,
+       33,   34,    4,    4,   35,   36,   41,   41,   41,   41,
+       41,   41,   43,   44,   74,   45,   47,   46,   48,   61,
+       46,   49,   35,   36,   43,   44,  549,   42,   50,   41,
+       41,   41,   62,   43,   45,   44,   46,   55,   47,   56,
+       49,   48,   51,   52,   63,   43,   75,   44,   76,   49,
+
+       50,   53,   80,   64,   77,   54,   50,   65,   79,  548,
+       78,   51,   52,   81,   83,   67,   82,   75,   49,   84,
+       85,   76,  109,   77,   53,   80,   77,   79,   50,   54,
+       51,   52,   78,   83,  106,   83,   81,   94,   82,   53,
+       85,   84,  111,   54,  107,   77,  110,  112,  114,   51,
+       68,   95,  113,   96,   83,  102,   69,   87,  115,   70,
+      101,  119,   53,  123,  103,  104,  126,   54,  114,  116,
+      120,  113,  124,  102,  117,  121,  106,  125,  147,  118,
+      122,  115,  123,  104,  119,  111,  107,  151,  148,  126,
+      112,  155,  156,  157,  116,  160,  163,  120,  158,  117,
+
+      164,  124,  121,  159,  118,  167,  125,  122,  169,  547,
+      176,  156,  151,  180,  155,  163,  172,  173,  186,  174,
+      177,  189,  175,  181,  204,  208,  160,  169,  187,  190,
+      191,  152,  147,  164,  153,  154,  192,  167,  193,  161,
+      212,  205,  148,  232,  165,  204,  206,  157,  215,  233,
+      248,  207,  158,  168,  176,  223,  152,  159,  249,  153,
+      154,  180,  186,  212,  177,  224,  208,  249,  215,  209,
+      161,  181,  187,  248,  205,  546,  256,  165,  223,  206,
+      270,  282,  257,  271,  207,  168,  258,  292,  224,  280,
+      281,  283,  545,  285,  299,  256,  286,  293,  282,  292,
+
+      403,  544,  250,  287,  288,  258,  377,  300,  283,  293,
+      209,  250,  342,  343,  387,  389,  378,  392,  394,  344,
+      397,  345,  399,  401,  388,  390,  412,  393,  395,  377,
+      398,  543,  400,  402,  430,  431,  413,  432,  433,  378,
+      387,  404,  389,  392,  394,  397,  399,  401,  445,  447,
+      388,  452,  390,  393,  395,  398,  400,  402,  446,  448,
+      412,  453,  463,  465,  476,  445,  447,  482,  452,  463,
+      413,  465,  464,  466,  477,  446,  448,  483,  453,  464,
+      476,  466,  482,  519,  529,  519,  529,  542,  538,  541,
+      477,  540,  483,  520,  530,  520,  530,  539,  532,  538,
+
+      537,  536,  535,  534,  533,  532,  531,  528,  527,  526,
+      525,  524,  523,  522,  484,   37,   37,   39,   39,  521,
+      505,  518,  517,  502,  516,  515,  514,  513,  512,  511,
+      510,  493,  492,  509,  508,  507,  486,  506,  505,  481,
+      480,  504,  503,  502,  501,  500,  499,  498,  497,  496,
+      495,  494,  493,  492,  491,  490,  489,  488,  487,  454,
+      486,  485,  481,  480,  479,  478,  442,  441,  440,  438,
+      437,  435,  434,  475,  474,  473,  472,  471,  470,  469,
+      468,  467,  423,  462,  461,  460,  459,  458,  457,  456,
+      455,  454,  451,  450,  449,  444,  443,  442,  441,  440,
+
+      439,  438,  437,  436,  435,  434,  429,  428,  427,  426,
+      425,  424,  423,  422,  421,  420,  419,  418,  417,  416,
+      415,  414,  411,  410,  409,  408,  407,  406,  405,  396,
+      391,  386,  385,  384,  383,  382,  381,  380,  379,  376,
+      375,  374,  373,  372,  371,  332,  370,  369,  368,  367,
+      366,  365,  364,  324,  363,  362,  361,  360,  359,  358,
+      357,  356,  355,  354,  353,  352,  351,  350,  349,  348,
+      347,  346,  341,  340,  301,  339,  338,  337,  336,  335,
+      334,  333,  332,  331,  330,  329,  328,  327,  326,  325,
+      324,  323,  322,  321,  320,  319,  318,  317,  316,  315,
+
+      314,  313,  312,  311,  310,  309,  308,  307,  264,  306,
+      305,  304,  303,  302,  301,  298,  297,  296,  295,  251,
+      294,  291,  290,  289,  284,  279,  278,  277,  276,  275,
+      274,  273,  272,  231,  269,  268,  267,  266,  226,  265,
+      264,  222,  263,  262,  261,  260,  259,  255,  254,  253,
+      210,  252,  251,  247,  246,  245,  244,  243,  198,  242,
+      241,  240,  239,  238,  237,  236,  235,  234,  231,  230,
+      229,  228,  227,  226,  225,  222,  221,  220,  219,  218,
+      217,  216,  214,  166,  213,  162,  211,  210,  203,  202,
+      201,  200,  199,  198,  146,  197,  144,  196,  195,  194,
+
+      188,  185,  184,  183,  182,  179,  178,  171,  170,  166,
+      162,  150,  149,  146,  145,  144,  143,  142,  141,  140,
+      139,  138,  137,  136,  135,  134,  133,  132,  131,  130,
+      129,  128,  127,  108,  105,  100,   99,   98,   97,   93,
+       92,   91,   90,   89,   88,   86,   40,   38,   73,   72,
+       71,   66,   60,   59,   58,   57,   40,   38,  550,    3,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550
+    } ;
+
+static yyconst flex_int16_t yy_chk[815] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    5,    5,   12,   12,   12,   13,
+       13,   13,   15,   15,  553,   16,   18,   17,   18,   27,
+       22,   19,   35,   35,   21,   21,  546,   12,   19,   41,
+       41,   41,   27,   15,   16,   15,   17,   21,   18,   22,
+       19,   18,   20,   20,   28,   21,   43,   21,   44,   30,
+
+       19,   20,   49,   28,   46,   20,   30,   28,   48,  545,
+       47,   20,   20,   50,   52,   30,   51,   43,   30,   53,
+       54,   44,   73,   46,   20,   49,   56,   48,   30,   20,
+       31,   31,   47,   68,   71,   52,   50,   63,   51,   31,
+       54,   53,   76,   31,   71,   56,   73,   76,   78,   31,
+       31,   63,   77,   63,   68,   69,   31,   56,   79,   31,
+       68,   81,   31,   83,   69,   69,   85,   31,   78,   80,
+       82,   77,   84,  102,   80,   82,  106,   84,  108,   80,
+       82,   79,   83,  102,   81,  111,  106,  112,  108,   85,
+      111,  113,  114,  115,  116,  117,  119,  120,  115,  116,
+
+      121,  124,  120,  115,  116,  125,  124,  120,  126,  544,
+      130,  114,  151,  133,  113,  119,  129,  129,  138,  129,
+      130,  140,  129,  133,  155,  158,  160,  126,  138,  140,
+      140,  112,  147,  164,  112,  112,  140,  167,  140,  117,
+      163,  156,  147,  188,  121,  155,  156,  157,  169,  188,
+      204,  156,  157,  125,  176,  178,  151,  157,  206,  151,
+      151,  180,  186,  163,  176,  178,  208,  249,  169,  158,
+      160,  180,  186,  204,  205,  543,  216,  164,  223,  205,
+      232,  242,  216,  232,  205,  167,  216,  248,  223,  241,
+      241,  242,  542,  244,  257,  256,  244,  248,  282,  292,
+
+      357,  541,  206,  244,  244,  256,  339,  257,  282,  292,
+      208,  249,  304,  304,  348,  349,  339,  351,  352,  304,
+      354,  304,  355,  356,  348,  349,  366,  351,  352,  377,
+      354,  540,  355,  356,  385,  385,  366,  386,  386,  377,
+      387,  357,  389,  392,  394,  397,  399,  401,  406,  407,
+      387,  411,  389,  392,  394,  397,  399,  401,  406,  407,
+      412,  411,  422,  424,  436,  445,  447,  450,  452,  463,
+      412,  465,  422,  424,  436,  445,  447,  450,  452,  463,
+      476,  465,  482,  506,  517,  519,  529,  539,  538,  535,
+      476,  534,  482,  506,  517,  519,  529,  533,  532,  530,
+
+      528,  526,  524,  522,  521,  520,  518,  516,  515,  514,
+      513,  512,  510,  509,  450,  551,  551,  552,  552,  508,
+      505,  504,  503,  502,  501,  500,  499,  498,  496,  495,
+      494,  493,  492,  491,  489,  488,  486,  485,  483,  481,
+      480,  479,  478,  477,  475,  474,  473,  472,  470,  469,
+      468,  467,  466,  464,  462,  459,  458,  457,  456,  454,
+      453,  451,  448,  446,  444,  443,  442,  441,  440,  438,
+      437,  435,  434,  433,  432,  431,  430,  429,  428,  427,
+      426,  425,  423,  421,  420,  419,  418,  417,  416,  415,
+      414,  413,  410,  409,  408,  405,  403,  402,  400,  398,
+
+      396,  395,  393,  391,  390,  388,  384,  383,  382,  381,
+      380,  379,  378,  376,  375,  374,  373,  372,  370,  369,
+      368,  367,  365,  364,  363,  362,  361,  360,  358,  353,
+      350,  347,  346,  345,  344,  343,  342,  341,  340,  338,
+      337,  336,  335,  334,  333,  332,  331,  330,  329,  328,
+      327,  326,  325,  324,  323,  322,  321,  320,  318,  317,
+      316,  315,  314,  313,  312,  311,  310,  309,  308,  307,
+      306,  305,  303,  302,  301,  300,  299,  298,  297,  296,
+      295,  294,  293,  291,  290,  288,  287,  286,  285,  284,
+      283,  281,  280,  279,  278,  277,  276,  275,  274,  273,
+
+      272,  271,  270,  269,  268,  267,  266,  265,  264,  263,
+      262,  261,  260,  259,  258,  255,  254,  253,  252,  251,
+      250,  247,  246,  245,  243,  240,  239,  238,  237,  236,
+      235,  234,  233,  231,  230,  229,  228,  227,  226,  225,
+      224,  222,  221,  220,  219,  218,  217,  214,  213,  211,
+      210,  209,  207,  203,  202,  201,  200,  199,  198,  197,
+      196,  195,  194,  193,  192,  191,  190,  189,  187,  185,
+      184,  183,  182,  181,  179,  177,  175,  174,  173,  172,
+      171,  170,  168,  166,  165,  162,  161,  159,  154,  153,
+      152,  150,  149,  148,  146,  145,  144,  143,  142,  141,
+
+      139,  137,  136,  135,  134,  132,  131,  128,  127,  122,
+      118,  110,  109,  107,  105,  104,  103,  101,  100,   99,
+       98,   97,   96,   95,   94,   93,   92,   91,   90,   89,
+       88,   87,   86,   72,   70,   67,   66,   65,   64,   62,
+       61,   60,   59,   58,   57,   55,   39,   37,   34,   33,
+       32,   29,   26,   25,   24,   23,    8,    7,    3,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+
+      550,  550,  550,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  550
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "osm_qos_parser_l.l"
+#line 2 "osm_qos_parser_l.l"
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Lexer of OSM QoS parser.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#include <opensm/osm_qos_policy.h>
+#include "osm_qos_parser_y.h"
+
+#define HANDLE_IF_IN_DESCRIPTION   if (in_description) { yylval = strdup(yytext); return TK_TEXT; }
+
+#define SAVE_POS save_pos()
+static void save_pos();
+
+extern int column_num;
+extern int line_num;
+extern FILE * yyin;
+extern YYSTYPE yylval;
+
+boolean_t in_description = FALSE;
+boolean_t in_list_of_hex_num_ranges = FALSE;
+boolean_t in_node_type = FALSE;
+boolean_t in_list_of_numbers = FALSE;
+boolean_t in_list_of_strings = FALSE;
+boolean_t in_list_of_num_pairs = FALSE;
+boolean_t in_asterisk_or_list_of_numbers = FALSE;
+boolean_t in_list_of_num_ranges = FALSE;
+boolean_t in_single_string = FALSE;
+boolean_t in_single_number = FALSE;
+
+static void reset_new_line_flags();
+#define RESET_NEW_LINE_FLAGS reset_new_line_flags()
+
+#define START_USE            {in_description = TRUE;}     /* list of strings including whitespace (description) */
+#define START_PORT_GUID      {in_list_of_hex_num_ranges = TRUE;} /* comma-separated list of hex num ranges */
+#define START_PORT_NAME      {in_list_of_strings = TRUE;} /* comma-separated list of following strings: ../../.. */
+#define START_PARTITION      {in_single_string = TRUE;}   /* single string w/o whitespaces (partition name) */
+#define START_NAME           {in_single_string = TRUE;}   /* single string w/o whitespaces (port group name) */
+#define START_QOS_LEVEL_NAME {in_single_string = TRUE;}   /* single string w/o whitespaces (qos level name in match rule) */
+
+#define START_NODE_TYPE     {in_node_type = TRUE;}       /* comma-separated list of node types (ROUTER,CA,...) */
+#define START_SL2VL_TABLE   {in_list_of_numbers = TRUE;} /* comma-separated list of hex or dec numbers */
+
+#define START_GROUP         {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS        {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS_TO     {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS_FROM   {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_SOURCE        {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_DESTINATION   {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+
+#define START_VLARB_HIGH    {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */
+#define START_VLARB_LOW     {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */
+
+#define START_TO            {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */
+#define START_FROM          {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */
+
+#define START_PATH_BITS     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_QOS_CLASS     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_SERVICE_ID    {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_PKEY          {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+
+#define START_SL               {in_single_number = TRUE;}   /* single number */
+#define START_VLARB_HIGH_LIMIT {in_single_number = TRUE;}   /* single number */
+#define START_MTU_LIMIT        {in_single_number = TRUE;}   /* single number */
+#define START_RATE_LIMIT       {in_single_number = TRUE;}   /* single number */
+#define START_PACKET_LIFE      {in_single_number = TRUE;}   /* single number */
+
+#define START_ULP_DEFAULT       {in_single_number = TRUE;}      /* single number */
+#define START_ULP_ANY           {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_SDP_DEFAULT   {in_single_number = TRUE;}      /* single number */
+#define START_ULP_SDP_PORT      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_RDS_DEFAULT   {in_single_number = TRUE;}      /* single number */
+#define START_ULP_RDS_PORT      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_ISER_DEFAULT  {in_single_number = TRUE;}      /* single number */
+#define START_ULP_ISER_PORT     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_SRP_GUID      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_IPOIB_DEFAULT {in_single_number = TRUE;}      /* single number */
+#define START_ULP_IPOIB_PKEY    {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+
+
+#define YY_NO_INPUT 1
+#line 933 "osm_qos_parser_l.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		int n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 201 "osm_qos_parser_l.l"
+
+
+
+#line 1117 "osm_qos_parser_l.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 551 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 760 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 204 "osm_qos_parser_l.l"
+{ SAVE_POS; RESET_NEW_LINE_FLAGS; } /* swallow comment */
+	YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 205 "osm_qos_parser_l.l"
+{ SAVE_POS; RESET_NEW_LINE_FLAGS; } /* trailing blanks with new line */
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 206 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; }
+	YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 207 "osm_qos_parser_l.l"
+{ SAVE_POS; RESET_NEW_LINE_FLAGS; }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 209 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_START; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 210 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_END; }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 212 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_START; }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 213 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_END; }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 214 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_START; }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 215 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_END; }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 217 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_START; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 218 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_END; }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 219 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_START; }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 220 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_END; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 221 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_START; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 222 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_END; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 224 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_START; }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 225 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_END; }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 226 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_START; }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 227 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_END; }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 229 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_START; }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 230 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_END; }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 231 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_START; }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 232 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_END; }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 234 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_START; }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 235 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_END; }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 236 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_START; }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 237 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_END; }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 239 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_GUID;    return TK_PORT_GUID;  }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 240 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_NAME;    return TK_PORT_NAME;  }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 241 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PARTITION;    return TK_PARTITION;  }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 242 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NODE_TYPE;    return TK_NODE_TYPE;  }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 243 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NAME;         return TK_NAME;       }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 244 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_USE;          return TK_USE;        }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 245 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_GROUP;        return TK_GROUP;      }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 246 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH;   return TK_VLARB_HIGH; }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 247 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_LOW;    return TK_VLARB_LOW;  }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 248 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH_LIMIT; return TK_VLARB_HIGH_LIMIT;}
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 249 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_TO;           return TK_TO;         }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 250 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_FROM;         return TK_FROM;       }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 251 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_TO;    return TK_ACROSS_TO;  }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 252 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_FROM;  return TK_ACROSS_FROM;}
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 253 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS;       return TK_ACROSS;     }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 254 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL2VL_TABLE;  return TK_SL2VL_TABLE;}
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 255 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL;           return TK_SL;         }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 256 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_MTU_LIMIT;    return TK_MTU_LIMIT;  }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 257 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_RATE_LIMIT;   return TK_RATE_LIMIT; }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 258 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PACKET_LIFE;  return TK_PACKET_LIFE;}
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 259 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PATH_BITS;    return TK_PATH_BITS;  }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 260 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_CLASS;    return TK_QOS_CLASS;  }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 261 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SOURCE;       return TK_SOURCE;     }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 262 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_DESTINATION;  return TK_DESTINATION;}
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 263 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SERVICE_ID;   return TK_SERVICE_ID; }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 264 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PKEY;         return TK_PKEY;       }
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 265 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_LEVEL_NAME; return TK_QOS_LEVEL_NAME;}
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 267 "osm_qos_parser_l.l"
+{ SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ROUTER; yylval = strdup(yytext); return TK_TEXT; }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 268 "osm_qos_parser_l.l"
+{ SAVE_POS; if (in_node_type) return TK_NODE_TYPE_CA;     yylval = strdup(yytext); return TK_TEXT; }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 269 "osm_qos_parser_l.l"
+{ SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SWITCH; yylval = strdup(yytext); return TK_TEXT; }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 270 "osm_qos_parser_l.l"
+{ SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SELF;   yylval = strdup(yytext); return TK_TEXT; }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 271 "osm_qos_parser_l.l"
+{ SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ALL;    yylval = strdup(yytext); return TK_TEXT; }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 273 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_DEFAULT; return TK_ULP_DEFAULT; }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 274 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SERVICE_ID; }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 275 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_PKEY; }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 276 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_TARGET_PORT_GUID; }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 278 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_SDP_DEFAULT; }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 279 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_SDP_PORT; }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 281 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_DEFAULT; return TK_ULP_RDS_DEFAULT; }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 282 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_PORT; return TK_ULP_RDS_PORT; }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 284 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_ISER_DEFAULT; }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 285 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_ISER_PORT; }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 287 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SRP_GUID; return TK_ULP_SRP_GUID; }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 289 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_DEFAULT; return TK_ULP_IPOIB_DEFAULT; }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 290 "osm_qos_parser_l.l"
+{ SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_PKEY; return TK_ULP_IPOIB_PKEY; }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 292 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        yylval = strdup(yytext);
+                        if (in_description || in_list_of_strings || in_single_string)
+                            return TK_TEXT;
+                        return TK_NUMBER;
+                    }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 300 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        yylval = strdup(yytext);
+                        if (in_description || in_list_of_strings || in_single_string)
+                            return TK_TEXT;
+                        return TK_NUMBER;
+                    }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 309 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_DASH;
+                    }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 319 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_DOTDOT;
+                    }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 329 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        if (in_description)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_COMMA;
+                    }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 339 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_ASTERISK;
+                    }
+	YY_BREAK
+case 80:
+/* rule 80 can match eol */
+YY_RULE_SETUP
+#line 349 "osm_qos_parser_l.l"
+{
+                        SAVE_POS;
+                        yylval = strdup(&yytext[1]);
+                        yylval[strlen(yylval)-1] = '\0';
+                        return TK_TEXT;
+                    }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 356 "osm_qos_parser_l.l"
+{ SAVE_POS; yylval = strdup(yytext); return TK_TEXT;}
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 358 "osm_qos_parser_l.l"
+ECHO;
+	YY_BREAK
+#line 1663 "osm_qos_parser_l.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 551 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 551 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 550);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef _UNISTD_H /* assume unistd.h has isatty() for us */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __THROW /* this is a gnuism */
+extern int isatty (int ) __THROW;
+#else
+extern int isatty (int );
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 358 "osm_qos_parser_l.l"
+
+
+
+
+/*********************************************
+ *********************************************/
+
+static void save_pos()
+{
+    int i;
+    for (i = 0; i < yyleng; i++)
+    {
+        if (yytext[i] == '\n')
+        {
+            line_num ++;
+            column_num = 1;
+        }
+        else
+            column_num ++;
+    }
+}
+
+/*********************************************
+ *********************************************/
+
+static void reset_new_line_flags()
+{
+    in_description = FALSE;
+    in_list_of_hex_num_ranges = FALSE;
+    in_node_type = FALSE;
+    in_list_of_numbers = FALSE;
+    in_list_of_strings = FALSE;
+    in_list_of_num_pairs = FALSE;
+    in_asterisk_or_list_of_numbers = FALSE;
+    in_list_of_num_ranges = FALSE;
+    in_single_string = FALSE;
+    in_single_number = FALSE;
+}
+
diff --git a/opensm/osm_qos_parser_l.l b/opensm/osm_qos_parser_l.l
new file mode 100644
index 0000000..ecdee8a
--- /dev/null
+++ b/opensm/osm_qos_parser_l.l
@@ -0,0 +1,394 @@
+%{
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Lexer of OSM QoS parser.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#include <opensm/osm_qos_policy.h>
+#include "osm_qos_parser_y.h"
+
+#define HANDLE_IF_IN_DESCRIPTION   if (in_description) { yylval = strdup(yytext); return TK_TEXT; }
+
+#define SAVE_POS save_pos()
+static void save_pos();
+
+extern int column_num;
+extern int line_num;
+extern FILE * yyin;
+extern YYSTYPE yylval;
+
+boolean_t in_description = FALSE;
+boolean_t in_list_of_hex_num_ranges = FALSE;
+boolean_t in_node_type = FALSE;
+boolean_t in_list_of_numbers = FALSE;
+boolean_t in_list_of_strings = FALSE;
+boolean_t in_list_of_num_pairs = FALSE;
+boolean_t in_asterisk_or_list_of_numbers = FALSE;
+boolean_t in_list_of_num_ranges = FALSE;
+boolean_t in_single_string = FALSE;
+boolean_t in_single_number = FALSE;
+
+static void reset_new_line_flags();
+#define RESET_NEW_LINE_FLAGS reset_new_line_flags()
+
+#define START_USE            {in_description = TRUE;}     /* list of strings including whitespace (description) */
+#define START_PORT_GUID      {in_list_of_hex_num_ranges = TRUE;} /* comma-separated list of hex num ranges */
+#define START_PORT_NAME      {in_list_of_strings = TRUE;} /* comma-separated list of following strings: ../../.. */
+#define START_PARTITION      {in_single_string = TRUE;}   /* single string w/o whitespaces (partition name) */
+#define START_NAME           {in_single_string = TRUE;}   /* single string w/o whitespaces (port group name) */
+#define START_QOS_LEVEL_NAME {in_single_string = TRUE;}   /* single string w/o whitespaces (qos level name in match rule) */
+
+#define START_NODE_TYPE     {in_node_type = TRUE;}       /* comma-separated list of node types (ROUTER,CA,...) */
+#define START_SL2VL_TABLE   {in_list_of_numbers = TRUE;} /* comma-separated list of hex or dec numbers */
+
+#define START_GROUP         {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS        {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS_TO     {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_ACROSS_FROM   {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_SOURCE        {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+#define START_DESTINATION   {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */
+
+#define START_VLARB_HIGH    {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */
+#define START_VLARB_LOW     {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */
+
+#define START_TO            {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */
+#define START_FROM          {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */
+
+#define START_PATH_BITS     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_QOS_CLASS     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_SERVICE_ID    {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_PKEY          {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+
+#define START_SL               {in_single_number = TRUE;}   /* single number */
+#define START_VLARB_HIGH_LIMIT {in_single_number = TRUE;}   /* single number */
+#define START_MTU_LIMIT        {in_single_number = TRUE;}   /* single number */
+#define START_RATE_LIMIT       {in_single_number = TRUE;}   /* single number */
+#define START_PACKET_LIFE      {in_single_number = TRUE;}   /* single number */
+
+#define START_ULP_DEFAULT       {in_single_number = TRUE;}      /* single number */
+#define START_ULP_ANY           {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_SDP_DEFAULT   {in_single_number = TRUE;}      /* single number */
+#define START_ULP_SDP_PORT      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_RDS_DEFAULT   {in_single_number = TRUE;}      /* single number */
+#define START_ULP_RDS_PORT      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_ISER_DEFAULT  {in_single_number = TRUE;}      /* single number */
+#define START_ULP_ISER_PORT     {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_SRP_GUID      {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+#define START_ULP_IPOIB_DEFAULT {in_single_number = TRUE;}      /* single number */
+#define START_ULP_IPOIB_PKEY    {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
+
+
+%}
+
+%option nounput noinput
+
+QOS_ULPS_START          qos\-ulps
+QOS_ULPS_END            end\-qos\-ulps
+PORT_GROUPS_START       port\-groups
+PORT_GROUPS_END         end\-port\-groups
+PORT_GROUP_START        port\-group
+PORT_GROUP_END          end\-port\-group
+PORT_NUM                port\-num
+NAME                    name
+USE                     use
+PORT_GUID               port\-guid
+TARGET_PORT_GUID        target\-port\-guid
+PORT_NAME               port\-name
+PARTITION               partition
+NODE_TYPE               node\-type
+QOS_SETUP_START         qos\-setup
+QOS_SETUP_END           end\-qos\-setup
+VLARB_TABLES_START      vlarb\-tables
+VLARB_TABLES_END        end\-vlarb\-tables
+VLARB_SCOPE_START       vlarb\-scope
+VLARB_SCOPE_END         end\-vlarb\-scope
+GROUP                   group
+ACROSS                  across
+VLARB_HIGH              vlarb\-high
+VLARB_LOW               vlarb\-low
+VLARB_HIGH_LIMIT        vl\-high\-limit
+SL2VL_TABLES_START      sl2vl\-tables
+SL2VL_TABLES_END        end\-sl2vl\-tables
+SL2VL_SCOPE_START       sl2vl\-scope
+SL2VL_SCOPE_END         end\-sl2vl\-scope
+TO                      to
+FROM                    from
+ACROSS_TO               across\-to
+ACROSS_FROM             across\-from
+SL2VL_TABLE             sl2vl\-table
+QOS_LEVELS_START        qos\-levels
+QOS_LEVELS_END          end\-qos\-levels
+QOS_LEVEL_START         qos\-level
+QOS_LEVEL_END           end\-qos\-level
+SL                      sl
+MTU_LIMIT               mtu\-limit
+RATE_LIMIT              rate\-limit
+PACKET_LIFE             packet\-life
+PATH_BITS               path\-bits
+QOS_MATCH_RULES_START   qos\-match\-rules
+QOS_MATCH_RULES_END     end\-qos\-match\-rules
+QOS_MATCH_RULE_START    qos\-match\-rule
+QOS_MATCH_RULE_END      end\-qos\-match\-rule
+QOS_CLASS               qos\-class
+SOURCE                  source
+DESTINATION             destination
+SERVICE_ID              service\-id
+PKEY                    pkey
+QOS_LEVEL_NAME          qos\-level\-name
+
+ROUTER                  [Rr][Oo][Uu][Tt][Ee][Rr]
+CA                      [Cc][Aa]
+SWITCH                  [Ss][Ww][Ii][Tt][Cc][Hh]
+SELF                    [Ss][Ee][Ll][Ff]
+ALL                     [Aa][Ll][Ll]
+
+ULP_SDP                 [Ss][Dd][Pp]
+ULP_SRP                 [Ss][Rr][Pp]
+ULP_RDS                 [Rr][Dd][Ss]
+ULP_IPOIB               [Ii][Pp][Oo][Ii][Bb]
+ULP_ISER                [Ii][Ss][Ee][Rr]
+ULP_ANY                 [Aa][Nn][Yy]
+ULP_DEFAULT             [Dd][Ee][Ff][Aa][Uu][Ll][Tt]
+
+WHITE                   [ \t]+
+NEW_LINE                \n
+COMMENT		            \#.*\n
+WHITE_DOTDOT_WHITE      [ \t]*:[ \t]*
+WHITE_COMMA_WHITE       [ \t]*,[ \t]*
+QUOTED_TEXT             \"[^\"]*\"
+
+%%
+
+
+{COMMENT}               { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* swallow comment */
+{WHITE}{NEW_LINE}       { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* trailing blanks with new line */
+{WHITE}                 { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; }
+{NEW_LINE}              { SAVE_POS; RESET_NEW_LINE_FLAGS; }
+
+{QOS_ULPS_START}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_START; }
+{QOS_ULPS_END}          { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_END; }
+
+{PORT_GROUPS_START}     { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_START; }
+{PORT_GROUPS_END}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_END; }
+{PORT_GROUP_START}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_START; }
+{PORT_GROUP_END}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_END; }
+
+{QOS_SETUP_START}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_START; }
+{QOS_SETUP_END}         { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_END; }
+{VLARB_TABLES_START}    { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_START; }
+{VLARB_TABLES_END}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_END; }
+{VLARB_SCOPE_START}     { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_START; }
+{VLARB_SCOPE_END}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_END; }
+
+{SL2VL_TABLES_START}    { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_START; }
+{SL2VL_TABLES_END}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_END; }
+{SL2VL_SCOPE_START}     { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_START; }
+{SL2VL_SCOPE_END}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_END; }
+
+{QOS_LEVELS_START}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_START; }
+{QOS_LEVELS_END}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_END; }
+{QOS_LEVEL_START}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_START; }
+{QOS_LEVEL_END}         { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_END; }
+
+{QOS_MATCH_RULES_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_START; }
+{QOS_MATCH_RULES_END}   { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_END; }
+{QOS_MATCH_RULE_START}  { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_START; }
+{QOS_MATCH_RULE_END}    { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_END; }
+
+{PORT_GUID}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_GUID;    return TK_PORT_GUID;  }
+{PORT_NAME}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_NAME;    return TK_PORT_NAME;  }
+{PARTITION}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PARTITION;    return TK_PARTITION;  }
+{NODE_TYPE}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NODE_TYPE;    return TK_NODE_TYPE;  }
+{NAME}{WHITE_DOTDOT_WHITE}             { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NAME;         return TK_NAME;       }
+{USE}{WHITE_DOTDOT_WHITE}              { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_USE;          return TK_USE;        }
+{GROUP}{WHITE_DOTDOT_WHITE}            { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_GROUP;        return TK_GROUP;      }
+{VLARB_HIGH}{WHITE_DOTDOT_WHITE}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH;   return TK_VLARB_HIGH; }
+{VLARB_LOW}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_LOW;    return TK_VLARB_LOW;  }
+{VLARB_HIGH_LIMIT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH_LIMIT; return TK_VLARB_HIGH_LIMIT;}
+{TO}{WHITE_DOTDOT_WHITE}               { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_TO;           return TK_TO;         }
+{FROM}{WHITE_DOTDOT_WHITE}             { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_FROM;         return TK_FROM;       }
+{ACROSS_TO}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_TO;    return TK_ACROSS_TO;  }
+{ACROSS_FROM}{WHITE_DOTDOT_WHITE}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_FROM;  return TK_ACROSS_FROM;}
+{ACROSS}{WHITE_DOTDOT_WHITE}           { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS;       return TK_ACROSS;     }
+{SL2VL_TABLE}{WHITE_DOTDOT_WHITE}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL2VL_TABLE;  return TK_SL2VL_TABLE;}
+{SL}{WHITE_DOTDOT_WHITE}               { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL;           return TK_SL;         }
+{MTU_LIMIT}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_MTU_LIMIT;    return TK_MTU_LIMIT;  }
+{RATE_LIMIT}{WHITE_DOTDOT_WHITE}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_RATE_LIMIT;   return TK_RATE_LIMIT; }
+{PACKET_LIFE}{WHITE_DOTDOT_WHITE}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PACKET_LIFE;  return TK_PACKET_LIFE;}
+{PATH_BITS}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PATH_BITS;    return TK_PATH_BITS;  }
+{QOS_CLASS}{WHITE_DOTDOT_WHITE}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_CLASS;    return TK_QOS_CLASS;  }
+{SOURCE}{WHITE_DOTDOT_WHITE}           { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SOURCE;       return TK_SOURCE;     }
+{DESTINATION}{WHITE_DOTDOT_WHITE}      { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_DESTINATION;  return TK_DESTINATION;}
+{SERVICE_ID}{WHITE_DOTDOT_WHITE}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SERVICE_ID;   return TK_SERVICE_ID; }
+{PKEY}{WHITE_DOTDOT_WHITE}             { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PKEY;         return TK_PKEY;       }
+{QOS_LEVEL_NAME}{WHITE_DOTDOT_WHITE}   { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_LEVEL_NAME; return TK_QOS_LEVEL_NAME;}
+
+{ROUTER}                  { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ROUTER; yylval = strdup(yytext); return TK_TEXT; }
+{CA}                      { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_CA;     yylval = strdup(yytext); return TK_TEXT; }
+{SWITCH}                  { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SWITCH; yylval = strdup(yytext); return TK_TEXT; }
+{SELF}                    { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SELF;   yylval = strdup(yytext); return TK_TEXT; }
+{ALL}                     { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ALL;    yylval = strdup(yytext); return TK_TEXT; }
+
+{ULP_DEFAULT}{WHITE_DOTDOT_WHITE}              { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_DEFAULT; return TK_ULP_DEFAULT; }
+{ULP_ANY}{WHITE_COMMA_WHITE}{SERVICE_ID}       { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SERVICE_ID; }
+{ULP_ANY}{WHITE_COMMA_WHITE}{PKEY}             { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_PKEY; }
+{ULP_ANY}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_TARGET_PORT_GUID; }
+
+{ULP_SDP}{WHITE_DOTDOT_WHITE}                  { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_SDP_DEFAULT; }
+{ULP_SDP}{WHITE_COMMA_WHITE}{PORT_NUM}         { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_SDP_PORT; }
+
+{ULP_RDS}{WHITE_DOTDOT_WHITE}                  { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_DEFAULT; return TK_ULP_RDS_DEFAULT; }
+{ULP_RDS}{WHITE_COMMA_WHITE}{PORT_NUM}         { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_PORT; return TK_ULP_RDS_PORT; }
+
+{ULP_ISER}{WHITE_DOTDOT_WHITE}                 { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_ISER_DEFAULT; }
+{ULP_ISER}{WHITE_COMMA_WHITE}{PORT_NUM}        { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_ISER_PORT; }
+
+{ULP_SRP}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SRP_GUID; return TK_ULP_SRP_GUID; }
+
+{ULP_IPOIB}{WHITE_DOTDOT_WHITE}                { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_DEFAULT; return TK_ULP_IPOIB_DEFAULT; }
+{ULP_IPOIB}{WHITE_COMMA_WHITE}{PKEY}           { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_PKEY; return TK_ULP_IPOIB_PKEY; }
+
+0[xX][0-9a-fA-F]+  {
+                        SAVE_POS;
+                        yylval = strdup(yytext);
+                        if (in_description || in_list_of_strings || in_single_string)
+                            return TK_TEXT;
+                        return TK_NUMBER;
+                    }
+
+[0-9]+              {
+                        SAVE_POS;
+                        yylval = strdup(yytext);
+                        if (in_description || in_list_of_strings || in_single_string)
+                            return TK_TEXT;
+                        return TK_NUMBER;
+                    }
+
+
+-                   {
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_DASH;
+                    }
+
+:                   {
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_DOTDOT;
+                    }
+
+,                   {
+                        SAVE_POS;
+                        if (in_description)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_COMMA;
+                    }
+
+\*                  {
+                        SAVE_POS;
+                        if (in_description || in_list_of_strings || in_single_string)
+                        {
+                            yylval = strdup(yytext);
+                            return TK_TEXT;
+                        }
+                        return TK_ASTERISK;
+                    }
+
+{QUOTED_TEXT}       {
+                        SAVE_POS;
+                        yylval = strdup(&yytext[1]);
+                        yylval[strlen(yylval)-1] = '\0';
+                        return TK_TEXT;
+                    }
+
+.                   { SAVE_POS; yylval = strdup(yytext); return TK_TEXT;}
+
+%%
+
+
+/*********************************************
+ *********************************************/
+
+static void save_pos()
+{
+    int i;
+    for (i = 0; i < yyleng; i++)
+    {
+        if (yytext[i] == '\n')
+        {
+            line_num ++;
+            column_num = 1;
+        }
+        else
+            column_num ++;
+    }
+}
+
+/*********************************************
+ *********************************************/
+
+static void reset_new_line_flags()
+{
+    in_description = FALSE;
+    in_list_of_hex_num_ranges = FALSE;
+    in_node_type = FALSE;
+    in_list_of_numbers = FALSE;
+    in_list_of_strings = FALSE;
+    in_list_of_num_pairs = FALSE;
+    in_asterisk_or_list_of_numbers = FALSE;
+    in_list_of_num_ranges = FALSE;
+    in_single_string = FALSE;
+    in_single_number = FALSE;
+}
diff --git a/opensm/osm_qos_parser_y.c b/opensm/osm_qos_parser_y.c
new file mode 100644
index 0000000..3ffd75b
--- /dev/null
+++ b/opensm/osm_qos_parser_y.c
@@ -0,0 +1,5177 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 1 "osm_qos_parser_y.y"
+
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 HNR Consulting. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Grammar of OSM QoS parser.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_qos_policy.h>
+
+#define OSM_QOS_POLICY_MAX_LINE_LEN         1024*10
+#define OSM_QOS_POLICY_SL2VL_TABLE_LEN      IB_MAX_NUM_VLS
+#define OSM_QOS_POLICY_MAX_VL_NUM           IB_MAX_NUM_VLS
+
+typedef struct tmp_parser_struct_t_ {
+    char       str[OSM_QOS_POLICY_MAX_LINE_LEN];
+    uint64_t   num_pair[2];
+    cl_list_t  str_list;
+    cl_list_t  num_list;
+    cl_list_t  num_pair_list;
+} tmp_parser_struct_t;
+
+static void __parser_tmp_struct_init();
+static void __parser_tmp_struct_reset();
+static void __parser_tmp_struct_destroy();
+
+static char * __parser_strip_white(char * str);
+
+static void __parser_str2uint64(uint64_t * p_val, char * str);
+
+static void __parser_port_group_start();
+static int __parser_port_group_end();
+
+static void __parser_sl2vl_scope_start();
+static int __parser_sl2vl_scope_end();
+
+static void __parser_vlarb_scope_start();
+static int __parser_vlarb_scope_end();
+
+static void __parser_qos_level_start();
+static int __parser_qos_level_end();
+
+static void __parser_match_rule_start();
+static int __parser_match_rule_end();
+
+static void __parser_ulp_match_rule_start();
+static int __parser_ulp_match_rule_end();
+
+static void __pkey_rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len);
+
+static void __rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len);
+
+static void __merge_rangearr(
+    uint64_t  **   range_arr_1,
+    unsigned       range_len_1,
+    uint64_t  **   range_arr_2,
+    unsigned       range_len_2,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len );
+
+static void __parser_add_port_to_port_map(
+    cl_qmap_t   * p_map,
+    osm_physp_t * p_physp);
+
+static void __parser_add_guid_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len);
+
+static void __parser_add_pkey_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len);
+
+static void __parser_add_partition_list_to_port_map(
+    cl_qmap_t  * p_map,
+    cl_list_t  * p_list);
+
+static void __parser_add_map_to_port_map(
+    cl_qmap_t * p_dmap,
+    cl_map_t  * p_smap);
+
+static int __validate_pkeys(
+    uint64_t ** range_arr,
+    unsigned    range_len,
+    boolean_t   is_ipoib);
+
+static void __setup_simple_qos_levels();
+static void __clear_simple_qos_levels();
+static void __setup_ulp_match_rules();
+static void __process_ulp_match_rules();
+static void yyerror(const char *format, ...);
+
+extern char * yytext;
+extern int yylex (void);
+extern FILE * yyin;
+extern int errno;
+int yyparse();
+
+#define RESET_BUFFER  __parser_tmp_struct_reset()
+
+tmp_parser_struct_t tmp_parser_struct;
+
+int column_num;
+int line_num;
+
+osm_qos_policy_t       * p_qos_policy = NULL;
+osm_qos_port_group_t   * p_current_port_group = NULL;
+osm_qos_sl2vl_scope_t  * p_current_sl2vl_scope = NULL;
+osm_qos_vlarb_scope_t  * p_current_vlarb_scope = NULL;
+osm_qos_level_t        * p_current_qos_level = NULL;
+osm_qos_match_rule_t   * p_current_qos_match_rule = NULL;
+osm_log_t              * p_qos_parser_osm_log;
+
+/* 16 Simple QoS Levels - one for each SL */
+static osm_qos_level_t osm_qos_policy_simple_qos_levels[16];
+
+/* Default Simple QoS Level */
+osm_qos_level_t __default_simple_qos_level;
+
+/*
+ * List of match rules that will be generated by the
+ * qos-ulp section. These rules are concatenated to
+ * the end of the usual matching rules list at the
+ * end of parsing.
+ */
+static cl_list_t __ulp_match_rules;
+
+/***************************************************/
+
+
+
+/* Line 189 of yacc.c  */
+#line 260 "osm_qos_parser_y.c"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TK_NUMBER = 258,
+     TK_DASH = 259,
+     TK_DOTDOT = 260,
+     TK_COMMA = 261,
+     TK_ASTERISK = 262,
+     TK_TEXT = 263,
+     TK_QOS_ULPS_START = 264,
+     TK_QOS_ULPS_END = 265,
+     TK_PORT_GROUPS_START = 266,
+     TK_PORT_GROUPS_END = 267,
+     TK_PORT_GROUP_START = 268,
+     TK_PORT_GROUP_END = 269,
+     TK_QOS_SETUP_START = 270,
+     TK_QOS_SETUP_END = 271,
+     TK_VLARB_TABLES_START = 272,
+     TK_VLARB_TABLES_END = 273,
+     TK_VLARB_SCOPE_START = 274,
+     TK_VLARB_SCOPE_END = 275,
+     TK_SL2VL_TABLES_START = 276,
+     TK_SL2VL_TABLES_END = 277,
+     TK_SL2VL_SCOPE_START = 278,
+     TK_SL2VL_SCOPE_END = 279,
+     TK_QOS_LEVELS_START = 280,
+     TK_QOS_LEVELS_END = 281,
+     TK_QOS_LEVEL_START = 282,
+     TK_QOS_LEVEL_END = 283,
+     TK_QOS_MATCH_RULES_START = 284,
+     TK_QOS_MATCH_RULES_END = 285,
+     TK_QOS_MATCH_RULE_START = 286,
+     TK_QOS_MATCH_RULE_END = 287,
+     TK_NAME = 288,
+     TK_USE = 289,
+     TK_PORT_GUID = 290,
+     TK_PORT_NAME = 291,
+     TK_PARTITION = 292,
+     TK_NODE_TYPE = 293,
+     TK_GROUP = 294,
+     TK_ACROSS = 295,
+     TK_VLARB_HIGH = 296,
+     TK_VLARB_LOW = 297,
+     TK_VLARB_HIGH_LIMIT = 298,
+     TK_TO = 299,
+     TK_FROM = 300,
+     TK_ACROSS_TO = 301,
+     TK_ACROSS_FROM = 302,
+     TK_SL2VL_TABLE = 303,
+     TK_SL = 304,
+     TK_MTU_LIMIT = 305,
+     TK_RATE_LIMIT = 306,
+     TK_PACKET_LIFE = 307,
+     TK_PATH_BITS = 308,
+     TK_QOS_CLASS = 309,
+     TK_SOURCE = 310,
+     TK_DESTINATION = 311,
+     TK_SERVICE_ID = 312,
+     TK_QOS_LEVEL_NAME = 313,
+     TK_PKEY = 314,
+     TK_NODE_TYPE_ROUTER = 315,
+     TK_NODE_TYPE_CA = 316,
+     TK_NODE_TYPE_SWITCH = 317,
+     TK_NODE_TYPE_SELF = 318,
+     TK_NODE_TYPE_ALL = 319,
+     TK_ULP_DEFAULT = 320,
+     TK_ULP_ANY_SERVICE_ID = 321,
+     TK_ULP_ANY_PKEY = 322,
+     TK_ULP_ANY_TARGET_PORT_GUID = 323,
+     TK_ULP_SDP_DEFAULT = 324,
+     TK_ULP_SDP_PORT = 325,
+     TK_ULP_RDS_DEFAULT = 326,
+     TK_ULP_RDS_PORT = 327,
+     TK_ULP_ISER_DEFAULT = 328,
+     TK_ULP_ISER_PORT = 329,
+     TK_ULP_SRP_GUID = 330,
+     TK_ULP_IPOIB_DEFAULT = 331,
+     TK_ULP_IPOIB_PKEY = 332
+   };
+#endif
+/* Tokens.  */
+#define TK_NUMBER 258
+#define TK_DASH 259
+#define TK_DOTDOT 260
+#define TK_COMMA 261
+#define TK_ASTERISK 262
+#define TK_TEXT 263
+#define TK_QOS_ULPS_START 264
+#define TK_QOS_ULPS_END 265
+#define TK_PORT_GROUPS_START 266
+#define TK_PORT_GROUPS_END 267
+#define TK_PORT_GROUP_START 268
+#define TK_PORT_GROUP_END 269
+#define TK_QOS_SETUP_START 270
+#define TK_QOS_SETUP_END 271
+#define TK_VLARB_TABLES_START 272
+#define TK_VLARB_TABLES_END 273
+#define TK_VLARB_SCOPE_START 274
+#define TK_VLARB_SCOPE_END 275
+#define TK_SL2VL_TABLES_START 276
+#define TK_SL2VL_TABLES_END 277
+#define TK_SL2VL_SCOPE_START 278
+#define TK_SL2VL_SCOPE_END 279
+#define TK_QOS_LEVELS_START 280
+#define TK_QOS_LEVELS_END 281
+#define TK_QOS_LEVEL_START 282
+#define TK_QOS_LEVEL_END 283
+#define TK_QOS_MATCH_RULES_START 284
+#define TK_QOS_MATCH_RULES_END 285
+#define TK_QOS_MATCH_RULE_START 286
+#define TK_QOS_MATCH_RULE_END 287
+#define TK_NAME 288
+#define TK_USE 289
+#define TK_PORT_GUID 290
+#define TK_PORT_NAME 291
+#define TK_PARTITION 292
+#define TK_NODE_TYPE 293
+#define TK_GROUP 294
+#define TK_ACROSS 295
+#define TK_VLARB_HIGH 296
+#define TK_VLARB_LOW 297
+#define TK_VLARB_HIGH_LIMIT 298
+#define TK_TO 299
+#define TK_FROM 300
+#define TK_ACROSS_TO 301
+#define TK_ACROSS_FROM 302
+#define TK_SL2VL_TABLE 303
+#define TK_SL 304
+#define TK_MTU_LIMIT 305
+#define TK_RATE_LIMIT 306
+#define TK_PACKET_LIFE 307
+#define TK_PATH_BITS 308
+#define TK_QOS_CLASS 309
+#define TK_SOURCE 310
+#define TK_DESTINATION 311
+#define TK_SERVICE_ID 312
+#define TK_QOS_LEVEL_NAME 313
+#define TK_PKEY 314
+#define TK_NODE_TYPE_ROUTER 315
+#define TK_NODE_TYPE_CA 316
+#define TK_NODE_TYPE_SWITCH 317
+#define TK_NODE_TYPE_SELF 318
+#define TK_NODE_TYPE_ALL 319
+#define TK_ULP_DEFAULT 320
+#define TK_ULP_ANY_SERVICE_ID 321
+#define TK_ULP_ANY_PKEY 322
+#define TK_ULP_ANY_TARGET_PORT_GUID 323
+#define TK_ULP_SDP_DEFAULT 324
+#define TK_ULP_SDP_PORT 325
+#define TK_ULP_RDS_DEFAULT 326
+#define TK_ULP_RDS_PORT 327
+#define TK_ULP_ISER_DEFAULT 328
+#define TK_ULP_ISER_PORT 329
+#define TK_ULP_SRP_GUID 330
+#define TK_ULP_IPOIB_DEFAULT 331
+#define TK_ULP_IPOIB_PKEY 332
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 264 of yacc.c  */
+#line 456 "osm_qos_parser_y.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+	Stack = &yyptr->Stack_alloc;					\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  3
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   262
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  78
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  165
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  238
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  328
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   332
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     5,     6,     9,    11,    13,    15,    17,
+      19,    23,    25,    28,    32,    34,    37,    41,    43,    45,
+      46,    49,    51,    53,    55,    57,    59,    61,    63,    67,
+      68,    71,    74,    78,    79,    82,    86,    88,    90,    91,
+      94,    96,    98,   100,   102,   104,   108,   109,   112,   116,
+     118,   120,   121,   124,   126,   128,   130,   132,   134,   136,
+     138,   142,   143,   146,   150,   152,   154,   155,   158,   160,
+     162,   164,   166,   168,   170,   172,   174,   178,   179,   182,
+     186,   188,   190,   191,   194,   196,   198,   200,   202,   204,
+     206,   208,   211,   212,   218,   219,   225,   226,   232,   233,
+     237,   238,   244,   245,   249,   250,   256,   257,   261,   262,
+     268,   269,   275,   276,   280,   281,   287,   289,   291,   293,
+     295,   297,   299,   301,   303,   305,   307,   309,   311,   313,
+     316,   318,   321,   323,   326,   328,   331,   333,   336,   338,
+     341,   343,   346,   348,   350,   354,   356,   358,   360,   362,
+     364,   366,   368,   370,   372,   374,   377,   379,   382,   384,
+     387,   389,   392,   394,   397,   399,   402,   404,   407,   409,
+     412,   414,   417,   419,   422,   424,   427,   429,   431,   433,
+     435,   437,   439,   441,   443,   445,   448,   450,   453,   455,
+     458,   460,   463,   465,   468,   470,   473,   475,   478,   480,
+     483,   485,   488,   490,   493,   495,   498,   500,   503,   505,
+     508,   510,   513,   515,   518,   520,   523,   525,   527,   529,
+     532,   534,   536,   540,   542,   544,   548,   550,   554,   560,
+     562,   564,   566,   568,   572,   578,   582,   584,   586
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int16 yyrhs[] =
+{
+      79,     0,    -1,    80,    -1,    -1,    80,    81,    -1,    82,
+      -1,    84,    -1,    91,    -1,   107,    -1,   114,    -1,     9,
+      83,    10,    -1,   121,    -1,    83,   121,    -1,    11,    85,
+      12,    -1,    86,    -1,    85,    86,    -1,    87,    89,    88,
+      -1,    13,    -1,    14,    -1,    -1,    89,    90,    -1,   147,
+      -1,   149,    -1,   153,    -1,   151,    -1,   155,    -1,   157,
+      -1,   159,    -1,    15,    92,    16,    -1,    -1,    92,    93,
+      -1,    92,   100,    -1,    17,    94,    18,    -1,    -1,    94,
+      95,    -1,    96,    98,    97,    -1,    19,    -1,    20,    -1,
+      -1,    98,    99,    -1,   168,    -1,   170,    -1,   174,    -1,
+     176,    -1,   172,    -1,    21,   101,    22,    -1,    -1,   101,
+     102,    -1,   103,   105,   104,    -1,    23,    -1,    24,    -1,
+      -1,   105,   106,    -1,   178,    -1,   180,    -1,   182,    -1,
+     184,    -1,   186,    -1,   188,    -1,   196,    -1,    25,   108,
+      26,    -1,    -1,   108,   109,    -1,   110,   112,   111,    -1,
+      27,    -1,    28,    -1,    -1,   112,   113,    -1,   198,    -1,
+     200,    -1,   202,    -1,   204,    -1,   206,    -1,   208,    -1,
+     210,    -1,   212,    -1,    29,   115,    30,    -1,    -1,   115,
+     116,    -1,   117,   119,   118,    -1,    31,    -1,    32,    -1,
+      -1,   119,   120,    -1,   214,    -1,   216,    -1,   222,    -1,
+     218,    -1,   220,    -1,   224,    -1,   226,    -1,    65,   232,
+      -1,    -1,   134,   238,     5,   122,   146,    -1,    -1,   135,
+     238,     5,   123,   146,    -1,    -1,   136,   238,     5,   124,
+     146,    -1,    -1,   137,   125,   146,    -1,    -1,   138,   238,
+       5,   126,   146,    -1,    -1,   139,   127,   146,    -1,    -1,
+     140,   238,     5,   128,   146,    -1,    -1,   141,   129,   146,
+      -1,    -1,   142,   238,     5,   130,   146,    -1,    -1,   143,
+     238,     5,   131,   146,    -1,    -1,   144,   132,   146,    -1,
+      -1,   145,   238,     5,   133,   146,    -1,    66,    -1,    67,
+      -1,    68,    -1,    69,    -1,    70,    -1,    71,    -1,    72,
+      -1,    73,    -1,    74,    -1,    75,    -1,    76,    -1,    77,
+      -1,   232,    -1,   148,   228,    -1,    33,    -1,   150,   228,
+      -1,    34,    -1,   152,   231,    -1,    36,    -1,   154,   238,
+      -1,    35,    -1,   156,   238,    -1,    59,    -1,   158,   231,
+      -1,    37,    -1,   160,   161,    -1,    38,    -1,   162,    -1,
+     161,     6,   162,    -1,   163,    -1,   164,    -1,   165,    -1,
+     166,    -1,   167,    -1,    61,    -1,    62,    -1,    60,    -1,
+      64,    -1,    63,    -1,   169,   231,    -1,    39,    -1,   171,
+     231,    -1,    40,    -1,   173,   232,    -1,    43,    -1,   175,
+     235,    -1,    41,    -1,   177,   235,    -1,    42,    -1,   179,
+     231,    -1,    39,    -1,   181,   231,    -1,    40,    -1,   183,
+     231,    -1,    47,    -1,   185,   231,    -1,    46,    -1,   187,
+     190,    -1,    45,    -1,   189,   192,    -1,    44,    -1,   191,
+      -1,   194,    -1,     7,    -1,   193,    -1,   195,    -1,     7,
+      -1,   238,    -1,   238,    -1,   197,   233,    -1,    48,    -1,
+     199,   228,    -1,    33,    -1,   201,   228,    -1,    34,    -1,
+     203,   232,    -1,    49,    -1,   205,   232,    -1,    50,    -1,
+     207,   232,    -1,    51,    -1,   209,   232,    -1,    52,    -1,
+     211,   238,    -1,    53,    -1,   213,   238,    -1,    59,    -1,
+     215,   228,    -1,    34,    -1,   217,   238,    -1,    54,    -1,
+     219,   231,    -1,    55,    -1,   221,   231,    -1,    56,    -1,
+     223,   228,    -1,    58,    -1,   225,   238,    -1,    57,    -1,
+     227,   238,    -1,    59,    -1,   229,    -1,   230,    -1,   229,
+     230,    -1,     8,    -1,   228,    -1,   231,     6,   228,    -1,
+     234,    -1,   234,    -1,   233,     6,   234,    -1,     3,    -1,
+     236,     5,   237,    -1,   235,     6,   236,     5,   237,    -1,
+       3,    -1,     3,    -1,   239,    -1,   240,    -1,   241,     4,
+     242,    -1,   239,     6,   241,     4,   242,    -1,   239,     6,
+     240,    -1,     3,    -1,     3,    -1,     3,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   276,   276,   279,   280,   283,   284,   285,   286,   287,
+     311,   314,   315,   344,   347,   348,   351,   354,   359,   365,
+     366,   369,   370,   371,   372,   373,   374,   375,   402,   405,
+     406,   407,   412,   415,   416,   419,   422,   427,   433,   434,
+     449,   450,   451,   452,   453,   458,   461,   462,   465,   468,
+     473,   479,   480,   499,   500,   501,   502,   503,   504,   505,
+     529,   532,   533,   536,   539,   544,   550,   551,   554,   555,
+     556,   557,   558,   559,   560,   561,   583,   586,   587,   590,
+     593,   598,   604,   605,   608,   609,   610,   611,   612,   613,
+     614,   636,   654,   654,   675,   675,   696,   696,   731,   731,
+     744,   744,   777,   777,   790,   790,   823,   823,   836,   836,
+     869,   869,   905,   905,   925,   925,   956,   959,   962,   965,
+     968,   971,   974,   977,   980,   983,   986,   989,   993,  1032,
+    1055,  1060,  1083,  1088,  1154,  1159,  1179,  1184,  1204,  1209,
+    1217,  1222,  1227,  1232,  1233,  1236,  1237,  1238,  1239,  1240,
+    1243,  1249,  1255,  1261,  1269,  1291,  1308,  1313,  1330,  1335,
+    1353,  1358,  1375,  1380,  1397,  1413,  1430,  1435,  1454,  1459,
+    1476,  1481,  1499,  1504,  1509,  1514,  1519,  1524,  1525,  1528,
+    1535,  1536,  1539,  1546,  1578,  1611,  1654,  1671,  1694,  1699,
+    1722,  1727,  1747,  1752,  1772,  1778,  1798,  1804,  1824,  1830,
+    1865,  1870,  1903,  1920,  1943,  1948,  1982,  1987,  2004,  2009,
+    2026,  2031,  2054,  2059,  2092,  2097,  2130,  2141,  2148,  2149,
+    2152,  2159,  2160,  2165,  2168,  2169,  2172,  2180,  2186,  2194,
+    2200,  2206,  2209,  2215,  2227,  2239,  2247,  2254,  2260
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "TK_NUMBER", "TK_DASH", "TK_DOTDOT",
+  "TK_COMMA", "TK_ASTERISK", "TK_TEXT", "TK_QOS_ULPS_START",
+  "TK_QOS_ULPS_END", "TK_PORT_GROUPS_START", "TK_PORT_GROUPS_END",
+  "TK_PORT_GROUP_START", "TK_PORT_GROUP_END", "TK_QOS_SETUP_START",
+  "TK_QOS_SETUP_END", "TK_VLARB_TABLES_START", "TK_VLARB_TABLES_END",
+  "TK_VLARB_SCOPE_START", "TK_VLARB_SCOPE_END", "TK_SL2VL_TABLES_START",
+  "TK_SL2VL_TABLES_END", "TK_SL2VL_SCOPE_START", "TK_SL2VL_SCOPE_END",
+  "TK_QOS_LEVELS_START", "TK_QOS_LEVELS_END", "TK_QOS_LEVEL_START",
+  "TK_QOS_LEVEL_END", "TK_QOS_MATCH_RULES_START", "TK_QOS_MATCH_RULES_END",
+  "TK_QOS_MATCH_RULE_START", "TK_QOS_MATCH_RULE_END", "TK_NAME", "TK_USE",
+  "TK_PORT_GUID", "TK_PORT_NAME", "TK_PARTITION", "TK_NODE_TYPE",
+  "TK_GROUP", "TK_ACROSS", "TK_VLARB_HIGH", "TK_VLARB_LOW",
+  "TK_VLARB_HIGH_LIMIT", "TK_TO", "TK_FROM", "TK_ACROSS_TO",
+  "TK_ACROSS_FROM", "TK_SL2VL_TABLE", "TK_SL", "TK_MTU_LIMIT",
+  "TK_RATE_LIMIT", "TK_PACKET_LIFE", "TK_PATH_BITS", "TK_QOS_CLASS",
+  "TK_SOURCE", "TK_DESTINATION", "TK_SERVICE_ID", "TK_QOS_LEVEL_NAME",
+  "TK_PKEY", "TK_NODE_TYPE_ROUTER", "TK_NODE_TYPE_CA",
+  "TK_NODE_TYPE_SWITCH", "TK_NODE_TYPE_SELF", "TK_NODE_TYPE_ALL",
+  "TK_ULP_DEFAULT", "TK_ULP_ANY_SERVICE_ID", "TK_ULP_ANY_PKEY",
+  "TK_ULP_ANY_TARGET_PORT_GUID", "TK_ULP_SDP_DEFAULT", "TK_ULP_SDP_PORT",
+  "TK_ULP_RDS_DEFAULT", "TK_ULP_RDS_PORT", "TK_ULP_ISER_DEFAULT",
+  "TK_ULP_ISER_PORT", "TK_ULP_SRP_GUID", "TK_ULP_IPOIB_DEFAULT",
+  "TK_ULP_IPOIB_PKEY", "$accept", "head", "qos_policy_entries",
+  "qos_policy_entry", "qos_ulps_section", "qos_ulps",
+  "port_groups_section", "port_groups", "port_group", "port_group_start",
+  "port_group_end", "port_group_entries", "port_group_entry",
+  "qos_setup_section", "qos_setup_items", "vlarb_tables",
+  "vlarb_scope_items", "vlarb_scope", "vlarb_scope_start",
+  "vlarb_scope_end", "vlarb_scope_entries", "vlarb_scope_entry",
+  "sl2vl_tables", "sl2vl_scope_items", "sl2vl_scope", "sl2vl_scope_start",
+  "sl2vl_scope_end", "sl2vl_scope_entries", "sl2vl_scope_entry",
+  "qos_levels_section", "qos_levels", "qos_level", "qos_level_start",
+  "qos_level_end", "qos_level_entries", "qos_level_entry",
+  "qos_match_rules_section", "qos_match_rules", "qos_match_rule",
+  "qos_match_rule_start", "qos_match_rule_end", "qos_match_rule_entries",
+  "qos_match_rule_entry", "qos_ulp", "$@1", "$@2", "$@3", "$@4", "$@5",
+  "$@6", "$@7", "$@8", "$@9", "$@10", "$@11", "$@12",
+  "qos_ulp_type_any_service", "qos_ulp_type_any_pkey",
+  "qos_ulp_type_any_target_port_guid", "qos_ulp_type_sdp_default",
+  "qos_ulp_type_sdp_port", "qos_ulp_type_rds_default",
+  "qos_ulp_type_rds_port", "qos_ulp_type_iser_default",
+  "qos_ulp_type_iser_port", "qos_ulp_type_srp_guid",
+  "qos_ulp_type_ipoib_default", "qos_ulp_type_ipoib_pkey", "qos_ulp_sl",
+  "port_group_name", "port_group_name_start", "port_group_use",
+  "port_group_use_start", "port_group_port_name",
+  "port_group_port_name_start", "port_group_port_guid",
+  "port_group_port_guid_start", "port_group_pkey", "port_group_pkey_start",
+  "port_group_partition", "port_group_partition_start",
+  "port_group_node_type", "port_group_node_type_start",
+  "port_group_node_type_list", "node_type_item", "node_type_ca",
+  "node_type_switch", "node_type_router", "node_type_all",
+  "node_type_self", "vlarb_scope_group", "vlarb_scope_group_start",
+  "vlarb_scope_across", "vlarb_scope_across_start",
+  "vlarb_scope_vlarb_high_limit", "vlarb_scope_vlarb_high_limit_start",
+  "vlarb_scope_vlarb_high", "vlarb_scope_vlarb_high_start",
+  "vlarb_scope_vlarb_low", "vlarb_scope_vlarb_low_start",
+  "sl2vl_scope_group", "sl2vl_scope_group_start", "sl2vl_scope_across",
+  "sl2vl_scope_across_start", "sl2vl_scope_across_from",
+  "sl2vl_scope_across_from_start", "sl2vl_scope_across_to",
+  "sl2vl_scope_across_to_start", "sl2vl_scope_from",
+  "sl2vl_scope_from_start", "sl2vl_scope_to", "sl2vl_scope_to_start",
+  "sl2vl_scope_from_list_or_asterisk", "sl2vl_scope_from_asterisk",
+  "sl2vl_scope_to_list_or_asterisk", "sl2vl_scope_to_asterisk",
+  "sl2vl_scope_from_list_of_ranges", "sl2vl_scope_to_list_of_ranges",
+  "sl2vl_scope_sl2vl_table", "sl2vl_scope_sl2vl_table_start",
+  "qos_level_name", "qos_level_name_start", "qos_level_use",
+  "qos_level_use_start", "qos_level_sl", "qos_level_sl_start",
+  "qos_level_mtu_limit", "qos_level_mtu_limit_start",
+  "qos_level_rate_limit", "qos_level_rate_limit_start",
+  "qos_level_packet_life", "qos_level_packet_life_start",
+  "qos_level_path_bits", "qos_level_path_bits_start", "qos_level_pkey",
+  "qos_level_pkey_start", "qos_match_rule_use", "qos_match_rule_use_start",
+  "qos_match_rule_qos_class", "qos_match_rule_qos_class_start",
+  "qos_match_rule_source", "qos_match_rule_source_start",
+  "qos_match_rule_destination", "qos_match_rule_destination_start",
+  "qos_match_rule_qos_level_name", "qos_match_rule_qos_level_name_start",
+  "qos_match_rule_service_id", "qos_match_rule_service_id_start",
+  "qos_match_rule_pkey", "qos_match_rule_pkey_start", "single_string",
+  "single_string_elems", "single_string_element", "string_list",
+  "single_number", "num_list", "number", "num_list_with_dotdot",
+  "number_from_pair_1", "number_from_pair_2", "list_of_ranges",
+  "num_list_with_dash", "single_number_from_range", "number_from_range_1",
+  "number_from_range_2", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    78,    79,    80,    80,    81,    81,    81,    81,    81,
+      82,    83,    83,    84,    85,    85,    86,    87,    88,    89,
+      89,    90,    90,    90,    90,    90,    90,    90,    91,    92,
+      92,    92,    93,    94,    94,    95,    96,    97,    98,    98,
+      99,    99,    99,    99,    99,   100,   101,   101,   102,   103,
+     104,   105,   105,   106,   106,   106,   106,   106,   106,   106,
+     107,   108,   108,   109,   110,   111,   112,   112,   113,   113,
+     113,   113,   113,   113,   113,   113,   114,   115,   115,   116,
+     117,   118,   119,   119,   120,   120,   120,   120,   120,   120,
+     120,   121,   122,   121,   123,   121,   124,   121,   125,   121,
+     126,   121,   127,   121,   128,   121,   129,   121,   130,   121,
+     131,   121,   132,   121,   133,   121,   134,   135,   136,   137,
+     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
+     158,   159,   160,   161,   161,   162,   162,   162,   162,   162,
+     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
+     173,   174,   175,   176,   177,   178,   179,   180,   181,   182,
+     183,   184,   185,   186,   187,   188,   189,   190,   190,   191,
+     192,   192,   193,   194,   195,   196,   197,   198,   199,   200,
+     201,   202,   203,   204,   205,   206,   207,   208,   209,   210,
+     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
+     221,   222,   223,   224,   225,   226,   227,   228,   229,   229,
+     230,   231,   231,   232,   233,   233,   234,   235,   235,   236,
+     237,   238,   239,   239,   239,   239,   240,   241,   242
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     0,     2,     1,     1,     1,     1,     1,
+       3,     1,     2,     3,     1,     2,     3,     1,     1,     0,
+       2,     1,     1,     1,     1,     1,     1,     1,     3,     0,
+       2,     2,     3,     0,     2,     3,     1,     1,     0,     2,
+       1,     1,     1,     1,     1,     3,     0,     2,     3,     1,
+       1,     0,     2,     1,     1,     1,     1,     1,     1,     1,
+       3,     0,     2,     3,     1,     1,     0,     2,     1,     1,
+       1,     1,     1,     1,     1,     1,     3,     0,     2,     3,
+       1,     1,     0,     2,     1,     1,     1,     1,     1,     1,
+       1,     2,     0,     5,     0,     5,     0,     5,     0,     3,
+       0,     5,     0,     3,     0,     5,     0,     3,     0,     5,
+       0,     5,     0,     3,     0,     5,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     1,     3,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     2,     1,     2,
+       1,     2,     1,     2,     1,     2,     1,     1,     1,     2,
+       1,     1,     3,     1,     1,     3,     1,     3,     5,     1,
+       1,     1,     1,     3,     5,     3,     1,     1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       3,     0,     2,     1,     0,     0,    29,    61,    77,     4,
+       5,     6,     7,     8,     9,     0,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,     0,    11,
+       0,     0,     0,    98,     0,   102,     0,   106,     0,     0,
+     112,     0,    17,     0,    14,    19,     0,     0,     0,   226,
+      91,   223,    10,    12,   236,     0,   231,   232,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      13,    15,     0,    28,    33,    46,    30,    31,    60,    64,
+      62,    66,    76,    80,    78,    82,    92,     0,     0,    94,
+      96,    99,   128,   100,   103,   104,   107,   108,   110,   113,
+     114,    18,   130,   132,   136,   134,   140,   142,   138,    16,
+      20,    21,     0,    22,     0,    24,     0,    23,     0,    25,
+       0,    26,     0,    27,     0,     0,     0,     0,     0,     0,
+     235,     0,   238,   233,     0,     0,     0,     0,     0,     0,
+       0,   220,   129,   217,   218,   131,   221,   133,   135,   137,
+     139,   152,   150,   151,   154,   153,   141,   143,   145,   146,
+     147,   148,   149,    32,    36,    34,    38,    45,    49,    47,
+      51,    65,   188,   190,   192,   194,   196,   198,   200,   202,
+      63,    67,    68,     0,    69,     0,    70,     0,    71,     0,
+      72,     0,    73,     0,    74,     0,    75,     0,    81,   204,
+     206,   208,   210,   214,   212,   216,    79,    83,    84,     0,
+      85,     0,    87,     0,    88,     0,    86,     0,    89,     0,
+      90,     0,    93,     0,    95,    97,   101,   105,   109,   111,
+     115,   219,     0,     0,     0,     0,   187,   189,   191,   193,
+     195,   197,   199,   201,   203,   205,   207,   209,   211,   213,
+     215,   234,   222,   144,    37,   156,   158,   162,   164,   160,
+      35,    39,    40,     0,    41,     0,    44,     0,    42,     0,
+      43,     0,    50,   166,   168,   176,   174,   172,   170,   186,
+      48,    52,    53,     0,    54,     0,    55,     0,    56,     0,
+      57,     0,    58,     0,    59,     0,   155,   157,   159,   229,
+     161,     0,   163,   165,   167,   169,   171,   179,   173,   177,
+     178,   183,   182,   175,   180,   181,   184,   185,   224,     0,
+       0,     0,     0,   230,   227,   225,     0,   228
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,     2,     9,    10,    28,    11,    43,    44,    45,
+     109,    72,   110,    12,    46,    76,   125,   165,   166,   260,
+     234,   261,    77,   126,   169,   170,   280,   235,   281,    13,
+      47,    80,    81,   180,   127,   181,    14,    48,    84,    85,
+     206,   128,   207,    29,   129,   134,   135,    61,   136,    63,
+     137,    65,   138,   139,    68,   140,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    91,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   156,   157,   158,   159,   160,   161,   162,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,   293,   308,   309,   313,   314,   310,   315,   294,   295,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     146,   143,   144,   147,    92,   317,    51,   300,   301,   324,
+      55,    56,    57,    58,   133
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -279
+static const yytype_int16 yypact[] =
+{
+    -279,    19,     5,  -279,    63,     9,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,    21,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,    45,  -279,
+      29,    29,    29,  -279,    29,  -279,    29,  -279,    29,    29,
+    -279,    29,  -279,     0,  -279,  -279,    36,    33,    -4,  -279,
+    -279,  -279,  -279,  -279,    31,    61,    62,  -279,    70,    71,
+      79,    21,    80,    21,    81,    21,    83,    85,    21,    86,
+    -279,  -279,     4,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,    29,    64,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,    84,  -279,    84,  -279,    84,  -279,    29,  -279,
+      29,  -279,    84,  -279,    91,    32,    39,    -5,    24,    21,
+    -279,    90,  -279,  -279,    21,    21,    21,    21,    21,    21,
+      21,  -279,  -279,    84,  -279,  -279,  -279,    92,  -279,  -279,
+      92,  -279,  -279,  -279,  -279,  -279,    93,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,    84,  -279,    84,  -279,    21,  -279,    21,
+    -279,    21,  -279,    21,  -279,    29,  -279,    29,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,    84,
+    -279,    29,  -279,    84,  -279,    84,  -279,    84,  -279,    29,
+    -279,    29,  -279,    64,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,    84,    91,   107,    25,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,    92,    92,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,    84,  -279,    84,  -279,    21,  -279,    97,
+    -279,    97,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,    84,  -279,    84,  -279,    84,  -279,    84,
+    -279,     8,  -279,    18,  -279,    21,    92,    92,  -279,  -279,
+     117,   120,   117,    92,    92,    92,    92,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,   135,  -279,    97,
+     123,    21,   137,  -279,  -279,  -279,   123,  -279
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,    53,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,   116,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,   -32,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,   -77,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,  -279,
+    -108,  -279,    14,  -120,    -6,  -279,  -278,  -113,  -160,  -166,
+     -31,  -279,    74,    75,   -55
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -238
+static const yytype_int16 yytable[] =
+{
+      59,    60,   150,    62,   142,    64,   145,    66,    67,    50,
+      69,    54,    70,    42,     4,   307,     5,   318,   101,     3,
+       6,    54,    42,   171,    49,   312,    82,    83,   172,   173,
+       7,    94,    54,    96,     8,  -237,    99,   102,   103,   104,
+     105,   106,   107,   325,   174,   175,   176,   177,   178,   272,
+     163,   164,    73,    74,   179,    52,   198,    75,   199,    78,
+      79,   167,   168,   108,   273,   274,    86,   132,    87,   275,
+     276,   277,   278,   279,    88,   236,    89,   237,   200,   201,
+     202,   203,   204,   205,    90,    93,    95,   148,    97,   149,
+      98,   100,   141,   246,   223,   247,    71,   222,   232,   233,
+     299,   244,   224,   225,   226,   227,   228,   229,   230,   248,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,   319,   252,   320,   323,   254,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,   321,   326,   296,    53,   297,   255,   256,   257,   258,
+     259,   151,   152,   153,   154,   155,   253,   231,   302,   322,
+     327,   130,   131,   303,   242,   304,   243,   305,   251,   306,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     245,   238,     0,   239,     0,   240,     0,   241,   249,     0,
+     250,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     311,   298,   316
+};
+
+static const yytype_int16 yycheck[] =
+{
+      31,    32,   122,    34,   112,    36,   114,    38,    39,    15,
+      41,     3,    12,    13,     9,     7,    11,   295,    14,     0,
+      15,     3,    13,    28,     3,     7,    30,    31,    33,    34,
+      25,    63,     3,    65,    29,     4,    68,    33,    34,    35,
+      36,    37,    38,   321,    49,    50,    51,    52,    53,    24,
+      18,    19,    16,    17,    59,    10,    32,    21,    34,    26,
+      27,    22,    23,    59,    39,    40,     5,     3,     6,    44,
+      45,    46,    47,    48,     4,   183,     5,   185,    54,    55,
+      56,    57,    58,    59,     5,     5,     5,   118,     5,   120,
+       5,     5,     8,   213,     4,   215,    43,   129,     6,     6,
+       3,   209,   134,   135,   136,   137,   138,   139,   140,   217,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,     6,   232,     5,     3,    20,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,     6,     5,   263,    28,   265,    39,    40,    41,    42,
+      43,    60,    61,    62,    63,    64,   233,   143,   271,   319,
+     326,    87,    87,   283,   195,   285,   197,   287,   223,   289,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     211,   187,    -1,   189,    -1,   191,    -1,   193,   219,    -1,
+     221,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     291,   267,   293
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    79,    80,     0,     9,    11,    15,    25,    29,    81,
+      82,    84,    91,   107,   114,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    83,   121,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,    13,    85,    86,    87,    92,   108,   115,     3,
+     232,   234,    10,   121,     3,   238,   239,   240,   241,   238,
+     238,   125,   238,   127,   238,   129,   238,   238,   132,   238,
+      12,    86,    89,    16,    17,    21,    93,   100,    26,    27,
+     109,   110,    30,    31,   116,   117,     5,     6,     4,     5,
+       5,   146,   232,     5,   146,     5,   146,     5,     5,   146,
+       5,    14,    33,    34,    35,    36,    37,    38,    59,    88,
+      90,   147,   148,   149,   150,   151,   152,   153,   154,   155,
+     156,   157,   158,   159,   160,    94,   101,   112,   119,   122,
+     240,   241,     3,   242,   123,   124,   126,   128,   130,   131,
+     133,     8,   228,   229,   230,   228,   228,   231,   238,   238,
+     231,    60,    61,    62,    63,    64,   161,   162,   163,   164,
+     165,   166,   167,    18,    19,    95,    96,    22,    23,   102,
+     103,    28,    33,    34,    49,    50,    51,    52,    53,    59,
+     111,   113,   198,   199,   200,   201,   202,   203,   204,   205,
+     206,   207,   208,   209,   210,   211,   212,   213,    32,    34,
+      54,    55,    56,    57,    58,    59,   118,   120,   214,   215,
+     216,   217,   218,   219,   220,   221,   222,   223,   224,   225,
+     226,   227,   146,     4,   146,   146,   146,   146,   146,   146,
+     146,   230,     6,     6,    98,   105,   228,   228,   232,   232,
+     232,   232,   238,   238,   228,   238,   231,   231,   228,   238,
+     238,   242,   228,   162,    20,    39,    40,    41,    42,    43,
+      97,    99,   168,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,    24,    39,    40,    44,    45,    46,    47,    48,
+     104,   106,   178,   179,   180,   181,   182,   183,   184,   185,
+     186,   187,   188,   189,   196,   197,   231,   231,   232,     3,
+     235,   236,   235,   231,   231,   231,   231,     7,   190,   191,
+     194,   238,     7,   192,   193,   195,   238,   233,   234,     6,
+       5,     6,   236,     3,   237,   234,     5,   237
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+

+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+

+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss_alloc, yyss);
+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 17:
+
+/* Line 1455 of yacc.c  */
+#line 354 "osm_qos_parser_y.y"
+    {
+                        __parser_port_group_start();
+                    }
+    break;
+
+  case 18:
+
+/* Line 1455 of yacc.c  */
+#line 359 "osm_qos_parser_y.y"
+    {
+                        if ( __parser_port_group_end() )
+                            return 1;
+                    }
+    break;
+
+  case 36:
+
+/* Line 1455 of yacc.c  */
+#line 422 "osm_qos_parser_y.y"
+    {
+                        __parser_vlarb_scope_start();
+                    }
+    break;
+
+  case 37:
+
+/* Line 1455 of yacc.c  */
+#line 427 "osm_qos_parser_y.y"
+    {
+                        if ( __parser_vlarb_scope_end() )
+                            return 1;
+                    }
+    break;
+
+  case 49:
+
+/* Line 1455 of yacc.c  */
+#line 468 "osm_qos_parser_y.y"
+    {
+                        __parser_sl2vl_scope_start();
+                    }
+    break;
+
+  case 50:
+
+/* Line 1455 of yacc.c  */
+#line 473 "osm_qos_parser_y.y"
+    {
+                        if ( __parser_sl2vl_scope_end() )
+                            return 1;
+                    }
+    break;
+
+  case 64:
+
+/* Line 1455 of yacc.c  */
+#line 539 "osm_qos_parser_y.y"
+    {
+                        __parser_qos_level_start();
+                    }
+    break;
+
+  case 65:
+
+/* Line 1455 of yacc.c  */
+#line 544 "osm_qos_parser_y.y"
+    {
+                        if ( __parser_qos_level_end() )
+                            return 1;
+                    }
+    break;
+
+  case 80:
+
+/* Line 1455 of yacc.c  */
+#line 593 "osm_qos_parser_y.y"
+    {
+                        __parser_match_rule_start();
+                    }
+    break;
+
+  case 81:
+
+/* Line 1455 of yacc.c  */
+#line 598 "osm_qos_parser_y.y"
+    {
+                        if ( __parser_match_rule_end() )
+                            return 1;
+                    }
+    break;
+
+  case 91:
+
+/* Line 1455 of yacc.c  */
+#line 636 "osm_qos_parser_y.y"
+    {
+                        /* parsing default ulp rule: "default: num" */
+                        cl_list_iterator_t    list_iterator;
+                        uint64_t            * p_tmp_num;
+
+                        list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                        p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                        if (*p_tmp_num > 15)
+                        {
+                            yyerror("illegal SL value");
+                            return 1;
+                        }
+                        __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num);
+                        __default_simple_qos_level.sl_set = TRUE;
+                        free(p_tmp_num);
+                        cl_list_remove_all(&tmp_parser_struct.num_list);
+                    }
+    break;
+
+  case 92:
+
+/* Line 1455 of yacc.c  */
+#line 654 "osm_qos_parser_y.y"
+    {
+                        /* "any, service-id ... : sl" - one instance of list of ranges */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have service ids");
+                            return 1;
+                        }
+
+                        /* get all the service id ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    }
+    break;
+
+  case 94:
+
+/* Line 1455 of yacc.c  */
+#line 675 "osm_qos_parser_y.y"
+    {
+                        /* "any, pkey ... : sl" - one instance of list of ranges */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have pkeys");
+                            return 1;
+                        }
+
+                        /* get all the pkey ranges */
+                        __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = range_len;
+
+                    }
+    break;
+
+  case 96:
+
+/* Line 1455 of yacc.c  */
+#line 696 "osm_qos_parser_y.y"
+    {
+                        /* any, target-port-guid ... : sl */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have port guids");
+                            return 1;
+                        }
+
+                        /* create a new port group with these ports */
+                        __parser_port_group_start();
+
+                        p_current_port_group->name = strdup("_ULP_Targets_");
+                        p_current_port_group->use = strdup("Generated from ULP rules");
+
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        __parser_add_guid_range_to_port_map(
+                                              &p_current_port_group->port_map,
+                                              range_arr,
+                                              range_len);
+
+                        /* add this port group to the destination
+                           groups of the current match rule */
+                        cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
+                                            p_current_port_group);
+
+                        __parser_port_group_end();
+
+                    }
+    break;
+
+  case 98:
+
+/* Line 1455 of yacc.c  */
+#line 731 "osm_qos_parser_y.y"
+    {
+                        /* "sdp : sl" - default SL for SDP */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                        range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    }
+    break;
+
+  case 100:
+
+/* Line 1455 of yacc.c  */
+#line 744 "osm_qos_parser_y.y"
+    {
+                        /* sdp with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("SDP ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    }
+    break;
+
+  case 102:
+
+/* Line 1455 of yacc.c  */
+#line 777 "osm_qos_parser_y.y"
+    {
+                        /* "rds : sl" - default SL for RDS */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] =
+                           OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + OSM_QOS_POLICY_ULP_RDS_PORT;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    }
+    break;
+
+  case 104:
+
+/* Line 1455 of yacc.c  */
+#line 790 "osm_qos_parser_y.y"
+    {
+                        /* rds with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("RDS ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    }
+    break;
+
+  case 106:
+
+/* Line 1455 of yacc.c  */
+#line 823 "osm_qos_parser_y.y"
+    {
+                        /* "iSER : sl" - default SL for iSER */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] =
+                           OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    }
+    break;
+
+  case 108:
+
+/* Line 1455 of yacc.c  */
+#line 836 "osm_qos_parser_y.y"
+    {
+                        /* iser with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("iSER ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    }
+    break;
+
+  case 110:
+
+/* Line 1455 of yacc.c  */
+#line 869 "osm_qos_parser_y.y"
+    {
+                        /* srp with target guids - this rule is similar
+                           to writing 'any' ulp with target port guids */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("SRP ULP rule doesn't have port guids");
+                            return 1;
+                        }
+
+                        /* create a new port group with these ports */
+                        __parser_port_group_start();
+
+                        p_current_port_group->name = strdup("_SRP_Targets_");
+                        p_current_port_group->use = strdup("Generated from ULP rules");
+
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        __parser_add_guid_range_to_port_map(
+                                              &p_current_port_group->port_map,
+                                              range_arr,
+                                              range_len);
+
+                        /* add this port group to the destination
+                           groups of the current match rule */
+                        cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
+                                            p_current_port_group);
+
+                        __parser_port_group_end();
+
+                    }
+    break;
+
+  case 112:
+
+/* Line 1455 of yacc.c  */
+#line 905 "osm_qos_parser_y.y"
+    {
+                        /* ipoib w/o any pkeys (default pkey) */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] = 0x7fff;
+
+                        /*
+                         * Although we know that the default partition exists,
+                         * we still need to validate it by checking that it has
+                         * at least two full members. Otherwise IPoIB won't work.
+                         */
+                        if (__validate_pkeys(range_arr, 1, TRUE))
+                            return 1;
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = 1;
+
+                    }
+    break;
+
+  case 114:
+
+/* Line 1455 of yacc.c  */
+#line 925 "osm_qos_parser_y.y"
+    {
+                        /* ipoib with pkeys */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("IPoIB ULP rule doesn't have pkeys");
+                            return 1;
+                        }
+
+                        /* get all the pkey ranges */
+                        __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        /*
+                         * Validate pkeys.
+                         * For IPoIB pkeys the validation is strict.
+                         * If some problem would be found, parsing will
+                         * be aborted with a proper error messages.
+                         */
+                        if (__validate_pkeys(range_arr, range_len, TRUE))
+                            return 1;
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = range_len;
+
+                    }
+    break;
+
+  case 116:
+
+/* Line 1455 of yacc.c  */
+#line 957 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 117:
+
+/* Line 1455 of yacc.c  */
+#line 960 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 118:
+
+/* Line 1455 of yacc.c  */
+#line 963 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 119:
+
+/* Line 1455 of yacc.c  */
+#line 966 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 120:
+
+/* Line 1455 of yacc.c  */
+#line 969 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 121:
+
+/* Line 1455 of yacc.c  */
+#line 972 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 122:
+
+/* Line 1455 of yacc.c  */
+#line 975 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 123:
+
+/* Line 1455 of yacc.c  */
+#line 978 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 124:
+
+/* Line 1455 of yacc.c  */
+#line 981 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 125:
+
+/* Line 1455 of yacc.c  */
+#line 984 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 126:
+
+/* Line 1455 of yacc.c  */
+#line 987 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 127:
+
+/* Line 1455 of yacc.c  */
+#line 990 "osm_qos_parser_y.y"
+    { __parser_ulp_match_rule_start(); }
+    break;
+
+  case 128:
+
+/* Line 1455 of yacc.c  */
+#line 993 "osm_qos_parser_y.y"
+    {
+                        /* get the SL for ULP rules */
+                        cl_list_iterator_t  list_iterator;
+                        uint64_t          * p_tmp_num;
+                        uint8_t             sl;
+
+                        list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                        p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                        if (*p_tmp_num > 15)
+                        {
+                            yyerror("illegal SL value");
+                            return 1;
+                        }
+
+                        sl = (uint8_t)(*p_tmp_num);
+                        free(p_tmp_num);
+                        cl_list_remove_all(&tmp_parser_struct.num_list);
+
+                        p_current_qos_match_rule->p_qos_level =
+                                 &osm_qos_policy_simple_qos_levels[sl];
+                        p_current_qos_match_rule->qos_level_name =
+                                 strdup(osm_qos_policy_simple_qos_levels[sl].name);
+
+                        if (__parser_ulp_match_rule_end())
+                            return 1;
+                    }
+    break;
+
+  case 129:
+
+/* Line 1455 of yacc.c  */
+#line 1032 "osm_qos_parser_y.y"
+    {
+                            /* 'name' of 'port-group' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_port_group->name)
+                            {
+                                yyerror("port-group has multiple 'name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_port_group->name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 130:
+
+/* Line 1455 of yacc.c  */
+#line 1055 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 131:
+
+/* Line 1455 of yacc.c  */
+#line 1060 "osm_qos_parser_y.y"
+    {
+                            /* 'use' of 'port-group' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_port_group->use)
+                            {
+                                yyerror("port-group has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_port_group->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 132:
+
+/* Line 1455 of yacc.c  */
+#line 1083 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 133:
+
+/* Line 1455 of yacc.c  */
+#line 1088 "osm_qos_parser_y.y"
+    {
+                            /* 'port-name' in 'port-group' - any num of instances */
+                            cl_list_iterator_t list_iterator;
+                            osm_node_t * p_node;
+                            osm_physp_t * p_physp;
+                            unsigned port_num;
+                            char * tmp_str;
+                            char * port_str;
+
+                            /* parsing port name strings */
+                            for (list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                                 list_iterator != cl_list_end(&tmp_parser_struct.str_list);
+                                 list_iterator = cl_list_next(list_iterator))
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                {
+                                    /* last slash in port name string is a separator
+                                       between node name and port number */
+                                    port_str = strrchr(tmp_str, '/');
+                                    if (!port_str || (strlen(port_str) < 3) ||
+                                        (port_str[1] != 'p' && port_str[1] != 'P')) {
+                                        yyerror("'%s' - illegal port name",
+                                                           tmp_str);
+                                        free(tmp_str);
+                                        cl_list_remove_all(&tmp_parser_struct.str_list);
+                                        return 1;
+                                    }
+
+                                    if (!(port_num = strtoul(&port_str[2],NULL,0))) {
+                                        yyerror(
+                                               "'%s' - illegal port number in port name",
+                                               tmp_str);
+                                        free(tmp_str);
+                                        cl_list_remove_all(&tmp_parser_struct.str_list);
+                                        return 1;
+                                    }
+
+                                    /* separate node name from port number */
+                                    port_str[0] = '\0';
+
+                                    if (st_lookup(p_qos_policy->p_node_hash,
+                                                  (st_data_t)tmp_str,
+                                                  (void *)&p_node))
+                                    {
+                                        /* we found the node, now get the right port */
+                                        p_physp = osm_node_get_physp_ptr(p_node, port_num);
+                                        if (!p_physp) {
+                                            yyerror(
+                                                   "'%s' - port number out of range in port name",
+                                                   tmp_str);
+                                            free(tmp_str);
+                                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                                            return 1;
+                                        }
+                                        /* we found the port, now add it to guid table */
+                                        __parser_add_port_to_port_map(&p_current_port_group->port_map,
+                                                                      p_physp);
+                                    }
+                                    free(tmp_str);
+                                }
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 134:
+
+/* Line 1455 of yacc.c  */
+#line 1154 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 135:
+
+/* Line 1455 of yacc.c  */
+#line 1159 "osm_qos_parser_y.y"
+    {
+                            /* 'port-guid' in 'port-group' - any num of instances */
+                            /* list of guid ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                __parser_add_guid_range_to_port_map(
+                                                      &p_current_port_group->port_map,
+                                                      range_arr,
+                                                      range_len);
+                            }
+                        }
+    break;
+
+  case 136:
+
+/* Line 1455 of yacc.c  */
+#line 1179 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 137:
+
+/* Line 1455 of yacc.c  */
+#line 1184 "osm_qos_parser_y.y"
+    {
+                            /* 'pkey' in 'port-group' - any num of instances */
+                            /* list of pkey ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                __parser_add_pkey_range_to_port_map(
+                                                      &p_current_port_group->port_map,
+                                                      range_arr,
+                                                      range_len);
+                            }
+                        }
+    break;
+
+  case 138:
+
+/* Line 1455 of yacc.c  */
+#line 1204 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 139:
+
+/* Line 1455 of yacc.c  */
+#line 1209 "osm_qos_parser_y.y"
+    {
+                            /* 'partition' in 'port-group' - any num of instances */
+                            __parser_add_partition_list_to_port_map(
+                                               &p_current_port_group->port_map,
+                                               &tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 140:
+
+/* Line 1455 of yacc.c  */
+#line 1217 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 141:
+
+/* Line 1455 of yacc.c  */
+#line 1222 "osm_qos_parser_y.y"
+    {
+                            /* 'node-type' in 'port-group' - any num of instances */
+                        }
+    break;
+
+  case 142:
+
+/* Line 1455 of yacc.c  */
+#line 1227 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 150:
+
+/* Line 1455 of yacc.c  */
+#line 1243 "osm_qos_parser_y.y"
+    {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_CA;
+                        }
+    break;
+
+  case 151:
+
+/* Line 1455 of yacc.c  */
+#line 1249 "osm_qos_parser_y.y"
+    {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_SWITCH;
+                        }
+    break;
+
+  case 152:
+
+/* Line 1455 of yacc.c  */
+#line 1255 "osm_qos_parser_y.y"
+    {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_ROUTER;
+                        }
+    break;
+
+  case 153:
+
+/* Line 1455 of yacc.c  */
+#line 1261 "osm_qos_parser_y.y"
+    {
+                            p_current_port_group->node_types |=
+                               (OSM_QOS_POLICY_NODE_TYPE_CA |
+                                OSM_QOS_POLICY_NODE_TYPE_SWITCH |
+                                OSM_QOS_POLICY_NODE_TYPE_ROUTER);
+                        }
+    break;
+
+  case 154:
+
+/* Line 1455 of yacc.c  */
+#line 1269 "osm_qos_parser_y.y"
+    {
+                            osm_port_t * p_osm_port =
+                                osm_get_port_by_guid(p_qos_policy->p_subn,
+                                     p_qos_policy->p_subn->sm_port_guid);
+                            if (p_osm_port)
+                                __parser_add_port_to_port_map(
+                                   &p_current_port_group->port_map,
+                                   p_osm_port->p_physp);
+                        }
+    break;
+
+  case 155:
+
+/* Line 1455 of yacc.c  */
+#line 1291 "osm_qos_parser_y.y"
+    {
+                            /* 'group' in 'vlarb-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->group_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 156:
+
+/* Line 1455 of yacc.c  */
+#line 1308 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 157:
+
+/* Line 1455 of yacc.c  */
+#line 1313 "osm_qos_parser_y.y"
+    {
+                            /* 'across' in 'vlarb-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->across_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 158:
+
+/* Line 1455 of yacc.c  */
+#line 1330 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 159:
+
+/* Line 1455 of yacc.c  */
+#line 1335 "osm_qos_parser_y.y"
+    {
+                            /* 'vl-high-limit' in 'vlarb-scope' - one instance of one number */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * p_tmp_num;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                            if (p_tmp_num)
+                            {
+                                p_current_vlarb_scope->vl_high_limit = (uint32_t)(*p_tmp_num);
+                                p_current_vlarb_scope->vl_high_limit_set = TRUE;
+                                free(p_tmp_num);
+                            }
+
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 160:
+
+/* Line 1455 of yacc.c  */
+#line 1353 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 161:
+
+/* Line 1455 of yacc.c  */
+#line 1358 "osm_qos_parser_y.y"
+    {
+                            /* 'vlarb-high' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->vlarb_high_list,num_pair);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+    break;
+
+  case 162:
+
+/* Line 1455 of yacc.c  */
+#line 1375 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 163:
+
+/* Line 1455 of yacc.c  */
+#line 1380 "osm_qos_parser_y.y"
+    {
+                            /* 'vlarb-low' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->vlarb_low_list,num_pair);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+    break;
+
+  case 164:
+
+/* Line 1455 of yacc.c  */
+#line 1397 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 165:
+
+/* Line 1455 of yacc.c  */
+#line 1413 "osm_qos_parser_y.y"
+    {
+                            /* 'group' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->group_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 166:
+
+/* Line 1455 of yacc.c  */
+#line 1430 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 167:
+
+/* Line 1455 of yacc.c  */
+#line 1435 "osm_qos_parser_y.y"
+    {
+                            /* 'across' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str) {
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,strdup(tmp_str));
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 168:
+
+/* Line 1455 of yacc.c  */
+#line 1454 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 169:
+
+/* Line 1455 of yacc.c  */
+#line 1459 "osm_qos_parser_y.y"
+    {
+                            /* 'across-from' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 170:
+
+/* Line 1455 of yacc.c  */
+#line 1476 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 171:
+
+/* Line 1455 of yacc.c  */
+#line 1481 "osm_qos_parser_y.y"
+    {
+                            /* 'across-to' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str) {
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,tmp_str);
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 172:
+
+/* Line 1455 of yacc.c  */
+#line 1499 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 173:
+
+/* Line 1455 of yacc.c  */
+#line 1504 "osm_qos_parser_y.y"
+    {
+                            /* 'from' in 'sl2vl-scope' - any num of instances */
+                        }
+    break;
+
+  case 174:
+
+/* Line 1455 of yacc.c  */
+#line 1509 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 175:
+
+/* Line 1455 of yacc.c  */
+#line 1514 "osm_qos_parser_y.y"
+    {
+                            /* 'to' in 'sl2vl-scope' - any num of instances */
+                        }
+    break;
+
+  case 176:
+
+/* Line 1455 of yacc.c  */
+#line 1519 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 179:
+
+/* Line 1455 of yacc.c  */
+#line 1528 "osm_qos_parser_y.y"
+    {
+                            int i;
+                            for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
+                                p_current_sl2vl_scope->from[i] = TRUE;
+                        }
+    break;
+
+  case 182:
+
+/* Line 1455 of yacc.c  */
+#line 1539 "osm_qos_parser_y.y"
+    {
+                            int i;
+                            for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
+                                p_current_sl2vl_scope->to[i] = TRUE;
+                        }
+    break;
+
+  case 183:
+
+/* Line 1455 of yacc.c  */
+#line 1546 "osm_qos_parser_y.y"
+    {
+                            int i;
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+                            uint8_t               num1, num2;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                {
+                                    if ( num_pair[0] < 0 ||
+                                         num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
+                                    {
+                                        yyerror("port number out of range 'from' list");
+                                        free(num_pair);
+                                        cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                                        return 1;
+                                    }
+                                    num1 = (uint8_t)num_pair[0];
+                                    num2 = (uint8_t)num_pair[1];
+                                    free(num_pair);
+                                    for (i = num1; i <= num2; i++)
+                                        p_current_sl2vl_scope->from[i] = TRUE;
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+    break;
+
+  case 184:
+
+/* Line 1455 of yacc.c  */
+#line 1578 "osm_qos_parser_y.y"
+    {
+                            int i;
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+                            uint8_t               num1, num2;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                {
+                                    if ( num_pair[0] < 0 ||
+                                         num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
+                                    {
+                                        yyerror("port number out of range 'to' list");
+                                        free(num_pair);
+                                        cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                                        return 1;
+                                    }
+                                    num1 = (uint8_t)num_pair[0];
+                                    num2 = (uint8_t)num_pair[1];
+                                    free(num_pair);
+                                    for (i = num1; i <= num2; i++)
+                                        p_current_sl2vl_scope->to[i] = TRUE;
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+    break;
+
+  case 185:
+
+/* Line 1455 of yacc.c  */
+#line 1611 "osm_qos_parser_y.y"
+    {
+                            /* 'sl2vl-table' - one instance of exactly
+                               OSM_QOS_POLICY_SL2VL_TABLE_LEN numbers */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t              num;
+                            uint64_t            * p_num;
+                            int                   i = 0;
+
+                            if (p_current_sl2vl_scope->sl2vl_table_set)
+                            {
+                                yyerror("sl2vl-scope has more than one sl2vl-table");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            if (cl_list_count(&tmp_parser_struct.num_list) != OSM_QOS_POLICY_SL2VL_TABLE_LEN)
+                            {
+                                yyerror("wrong number of values in 'sl2vl-table' (should be 16)");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_list) )
+                            {
+                                p_num = (uint64_t*)cl_list_obj(list_iterator);
+                                num = *p_num;
+                                free(p_num);
+                                if (num >= OSM_QOS_POLICY_MAX_VL_NUM)
+                                {
+                                    yyerror("wrong VL value in 'sl2vl-table' (should be 0 to 15)");
+                                    cl_list_remove_all(&tmp_parser_struct.num_list);
+                                    return 1;
+                                }
+
+                                p_current_sl2vl_scope->sl2vl_table[i++] = (uint8_t)num;
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            p_current_sl2vl_scope->sl2vl_table_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 186:
+
+/* Line 1455 of yacc.c  */
+#line 1654 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 187:
+
+/* Line 1455 of yacc.c  */
+#line 1671 "osm_qos_parser_y.y"
+    {
+                            /* 'name' of 'qos-level' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_level->name)
+                            {
+                                yyerror("qos-level has multiple 'name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_level->name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 188:
+
+/* Line 1455 of yacc.c  */
+#line 1694 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 189:
+
+/* Line 1455 of yacc.c  */
+#line 1699 "osm_qos_parser_y.y"
+    {
+                            /* 'use' of 'qos-level' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_level->use)
+                            {
+                                yyerror("qos-level has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_level->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 190:
+
+/* Line 1455 of yacc.c  */
+#line 1722 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 191:
+
+/* Line 1455 of yacc.c  */
+#line 1727 "osm_qos_parser_y.y"
+    {
+                            /* 'sl' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->sl_set)
+                            {
+                                yyerror("'qos-level' has multiple 'sl' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->sl = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->sl_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 192:
+
+/* Line 1455 of yacc.c  */
+#line 1747 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 193:
+
+/* Line 1455 of yacc.c  */
+#line 1752 "osm_qos_parser_y.y"
+    {
+                            /* 'mtu-limit' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->mtu_limit_set)
+                            {
+                                yyerror("'qos-level' has multiple 'mtu-limit' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->mtu_limit = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->mtu_limit_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 194:
+
+/* Line 1455 of yacc.c  */
+#line 1772 "osm_qos_parser_y.y"
+    {
+                            /* 'mtu-limit' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 195:
+
+/* Line 1455 of yacc.c  */
+#line 1778 "osm_qos_parser_y.y"
+    {
+                            /* 'rate-limit' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->rate_limit_set)
+                            {
+                                yyerror("'qos-level' has multiple 'rate-limit' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->rate_limit = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->rate_limit_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 196:
+
+/* Line 1455 of yacc.c  */
+#line 1798 "osm_qos_parser_y.y"
+    {
+                            /* 'rate-limit' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 197:
+
+/* Line 1455 of yacc.c  */
+#line 1804 "osm_qos_parser_y.y"
+    {
+                            /* 'packet-life' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->pkt_life_set)
+                            {
+                                yyerror("'qos-level' has multiple 'packet-life' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->pkt_life = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->pkt_life_set= TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+    break;
+
+  case 198:
+
+/* Line 1455 of yacc.c  */
+#line 1824 "osm_qos_parser_y.y"
+    {
+                            /* 'packet-life' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 199:
+
+/* Line 1455 of yacc.c  */
+#line 1830 "osm_qos_parser_y.y"
+    {
+                            /* 'path-bits' in 'qos-level' - any num of instances */
+                            /* list of path bit ranges */
+
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_level->path_bits_range_len )
+                                {
+                                    p_current_qos_level->path_bits_range_arr = range_arr;
+                                    p_current_qos_level->path_bits_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_level->path_bits_range_arr,
+                                                      p_current_qos_level->path_bits_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_level->path_bits_range_arr = new_range_arr;
+                                    p_current_qos_level->path_bits_range_len = new_range_len;
+                                }
+                            }
+                        }
+    break;
+
+  case 200:
+
+/* Line 1455 of yacc.c  */
+#line 1865 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 201:
+
+/* Line 1455 of yacc.c  */
+#line 1870 "osm_qos_parser_y.y"
+    {
+                            /* 'pkey' in 'qos-level' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_level->pkey_range_len )
+                                {
+                                    p_current_qos_level->pkey_range_arr = range_arr;
+                                    p_current_qos_level->pkey_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_level->pkey_range_arr,
+                                                      p_current_qos_level->pkey_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_level->pkey_range_arr = new_range_arr;
+                                    p_current_qos_level->pkey_range_len = new_range_len;
+                                }
+                            }
+                        }
+    break;
+
+  case 202:
+
+/* Line 1455 of yacc.c  */
+#line 1903 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 203:
+
+/* Line 1455 of yacc.c  */
+#line 1920 "osm_qos_parser_y.y"
+    {
+                            /* 'use' of 'qos-match-rule' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_match_rule->use)
+                            {
+                                yyerror("'qos-match-rule' has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_match_rule->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 204:
+
+/* Line 1455 of yacc.c  */
+#line 1943 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 205:
+
+/* Line 1455 of yacc.c  */
+#line 1948 "osm_qos_parser_y.y"
+    {
+                            /* 'qos-class' in 'qos-match-rule' - num of instances of list of ranges */
+                            /* list of class ranges (QoS Class is 12-bit value) */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->qos_class_range_len )
+                                {
+                                    p_current_qos_match_rule->qos_class_range_arr = range_arr;
+                                    p_current_qos_match_rule->qos_class_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->qos_class_range_arr,
+                                                      p_current_qos_match_rule->qos_class_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->qos_class_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->qos_class_range_len = new_range_len;
+                                }
+                            }
+                        }
+    break;
+
+  case 206:
+
+/* Line 1455 of yacc.c  */
+#line 1982 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 207:
+
+/* Line 1455 of yacc.c  */
+#line 1987 "osm_qos_parser_y.y"
+    {
+                            /* 'source' in 'qos-match-rule' - text */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_qos_match_rule->source_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 208:
+
+/* Line 1455 of yacc.c  */
+#line 2004 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 209:
+
+/* Line 1455 of yacc.c  */
+#line 2009 "osm_qos_parser_y.y"
+    {
+                            /* 'destination' in 'qos-match-rule' - text */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_qos_match_rule->destination_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 210:
+
+/* Line 1455 of yacc.c  */
+#line 2026 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 211:
+
+/* Line 1455 of yacc.c  */
+#line 2031 "osm_qos_parser_y.y"
+    {
+                            /* 'qos-level-name' in 'qos-match-rule' - single string */
+                            cl_list_iterator_t   list_iterator;
+                            char               * tmp_str;
+
+                            if (p_current_qos_match_rule->qos_level_name)
+                            {
+                                yyerror("qos-match-rule has multiple 'qos-level-name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_match_rule->qos_level_name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+    break;
+
+  case 212:
+
+/* Line 1455 of yacc.c  */
+#line 2054 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 213:
+
+/* Line 1455 of yacc.c  */
+#line 2059 "osm_qos_parser_y.y"
+    {
+                            /* 'service-id' in 'qos-match-rule' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->service_id_range_len )
+                                {
+                                    p_current_qos_match_rule->service_id_range_arr = range_arr;
+                                    p_current_qos_match_rule->service_id_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->service_id_range_arr,
+                                                      p_current_qos_match_rule->service_id_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->service_id_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->service_id_range_len = new_range_len;
+                                }
+                            }
+                        }
+    break;
+
+  case 214:
+
+/* Line 1455 of yacc.c  */
+#line 2092 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 215:
+
+/* Line 1455 of yacc.c  */
+#line 2097 "osm_qos_parser_y.y"
+    {
+                            /* 'pkey' in 'qos-match-rule' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->pkey_range_len )
+                                {
+                                    p_current_qos_match_rule->pkey_range_arr = range_arr;
+                                    p_current_qos_match_rule->pkey_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->pkey_range_arr,
+                                                      p_current_qos_match_rule->pkey_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->pkey_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->pkey_range_len = new_range_len;
+                                }
+                            }
+                        }
+    break;
+
+  case 216:
+
+/* Line 1455 of yacc.c  */
+#line 2130 "osm_qos_parser_y.y"
+    {
+                            RESET_BUFFER;
+                        }
+    break;
+
+  case 217:
+
+/* Line 1455 of yacc.c  */
+#line 2141 "osm_qos_parser_y.y"
+    {
+                        cl_list_insert_tail(&tmp_parser_struct.str_list,
+                                            strdup(__parser_strip_white(tmp_parser_struct.str)));
+                        tmp_parser_struct.str[0] = '\0';
+                    }
+    break;
+
+  case 220:
+
+/* Line 1455 of yacc.c  */
+#line 2152 "osm_qos_parser_y.y"
+    {
+                        strcat(tmp_parser_struct.str,(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+  case 226:
+
+/* Line 1455 of yacc.c  */
+#line 2172 "osm_qos_parser_y.y"
+    {
+                        uint64_t * p_num = (uint64_t*)malloc(sizeof(uint64_t));
+                        __parser_str2uint64(p_num,(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                        cl_list_insert_tail(&tmp_parser_struct.num_list, p_num);
+                    }
+    break;
+
+  case 227:
+
+/* Line 1455 of yacc.c  */
+#line 2180 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 228:
+
+/* Line 1455 of yacc.c  */
+#line 2186 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 229:
+
+/* Line 1455 of yacc.c  */
+#line 2194 "osm_qos_parser_y.y"
+    {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+  case 230:
+
+/* Line 1455 of yacc.c  */
+#line 2200 "osm_qos_parser_y.y"
+    {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+  case 232:
+
+/* Line 1455 of yacc.c  */
+#line 2209 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 233:
+
+/* Line 1455 of yacc.c  */
+#line 2215 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
+                            num_pair[0] = tmp_parser_struct.num_pair[0];
+                            num_pair[1] = tmp_parser_struct.num_pair[1];
+                        }
+                        else {
+                            num_pair[1] = tmp_parser_struct.num_pair[0];
+                            num_pair[0] = tmp_parser_struct.num_pair[1];
+                        }
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 234:
+
+/* Line 1455 of yacc.c  */
+#line 2227 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
+                            num_pair[0] = tmp_parser_struct.num_pair[0];
+                            num_pair[1] = tmp_parser_struct.num_pair[1];
+                        }
+                        else {
+                            num_pair[1] = tmp_parser_struct.num_pair[0];
+                            num_pair[0] = tmp_parser_struct.num_pair[1];
+                        }
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 235:
+
+/* Line 1455 of yacc.c  */
+#line 2239 "osm_qos_parser_y.y"
+    {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+    break;
+
+  case 236:
+
+/* Line 1455 of yacc.c  */
+#line 2247 "osm_qos_parser_y.y"
+    {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)]));
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+  case 237:
+
+/* Line 1455 of yacc.c  */
+#line 2254 "osm_qos_parser_y.y"
+    {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+  case 238:
+
+/* Line 1455 of yacc.c  */
+#line 2260 "osm_qos_parser_y.y"
+    {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)]));
+                        free((yyvsp[(1) - (1)]));
+                    }
+    break;
+
+
+
+/* Line 1455 of yacc.c  */
+#line 4167 "osm_qos_parser_y.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c  */
+#line 2266 "osm_qos_parser_y.y"
+
+
+/***************************************************
+ ***************************************************/
+
+int osm_qos_parse_policy_file(IN osm_subn_t * const p_subn)
+{
+    int res = 0;
+    static boolean_t first_time = TRUE;
+    p_qos_parser_osm_log = &p_subn->p_osm->log;
+
+    OSM_LOG_ENTER(p_qos_parser_osm_log);
+
+    osm_qos_policy_destroy(p_subn->p_qos_policy);
+    p_subn->p_qos_policy = NULL;
+
+    yyin = fopen (p_subn->opt.qos_policy_file, "r");
+    if (!yyin)
+    {
+        if (strcmp(p_subn->opt.qos_policy_file,OSM_DEFAULT_QOS_POLICY_FILE)) {
+            OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC01: "
+                    "Failed opening QoS policy file %s - %s\n",
+                    p_subn->opt.qos_policy_file, strerror(errno));
+            res = 1;
+        }
+        else
+            OSM_LOG(p_qos_parser_osm_log, OSM_LOG_VERBOSE,
+                    "QoS policy file not found (%s)\n",
+                    p_subn->opt.qos_policy_file);
+
+        goto Exit;
+    }
+
+    if (first_time)
+    {
+        first_time = FALSE;
+        __setup_simple_qos_levels();
+        __setup_ulp_match_rules();
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_INFO,
+		"Loading QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+    }
+    else
+        /*
+         * ULP match rules list was emptied at the end of
+         * previous parsing iteration.
+         * What's left is to clear simple QoS levels.
+         */
+        __clear_simple_qos_levels();
+
+    column_num = 1;
+    line_num = 1;
+
+    p_subn->p_qos_policy = osm_qos_policy_create(p_subn);
+
+    __parser_tmp_struct_init();
+    p_qos_policy = p_subn->p_qos_policy;
+
+    res = yyparse();
+
+    __parser_tmp_struct_destroy();
+
+    if (res != 0)
+    {
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC03: "
+                "Failed parsing QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        osm_qos_policy_destroy(p_subn->p_qos_policy);
+        p_subn->p_qos_policy = NULL;
+        res = 1;
+        goto Exit;
+    }
+
+    /* add generated ULP match rules to the usual match rules */
+    __process_ulp_match_rules();
+
+    if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log))
+    {
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC04: "
+                "Error(s) in QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        fprintf(stderr, "Error(s) in QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        osm_qos_policy_destroy(p_subn->p_qos_policy);
+        p_subn->p_qos_policy = NULL;
+        res = 1;
+        goto Exit;
+    }
+
+  Exit:
+    if (yyin)
+        fclose(yyin);
+    OSM_LOG_EXIT(p_qos_parser_osm_log);
+    return res;
+}
+
+/***************************************************
+ ***************************************************/
+
+int yywrap()
+{
+    return(1);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void yyerror(const char *format, ...)
+{
+    char s[256];
+    va_list pvar;
+
+    OSM_LOG_ENTER(p_qos_parser_osm_log);
+
+    va_start(pvar, format);
+    vsnprintf(s, sizeof(s), format, pvar);
+    va_end(pvar);
+
+    OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC05: "
+            "Syntax error (line %d:%d): %s\n",
+            line_num, column_num, s);
+    fprintf(stderr, "Error in QoS Policy File (line %d:%d): %s.\n",
+            line_num, column_num, s);
+    OSM_LOG_EXIT(p_qos_parser_osm_log);
+}
+
+/***************************************************
+ ***************************************************/
+
+static char * __parser_strip_white(char * str)
+{
+   int i;
+   for (i = (strlen(str)-1); i >= 0; i--)
+   {
+      if (isspace(str[i]))
+          str[i] = '\0';
+      else
+         break;
+   }
+   for (i = 0; i < strlen(str); i++)
+   {
+      if (!isspace(str[i]))
+         break;
+   }
+   return &(str[i]);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_str2uint64(uint64_t * p_val, char * str)
+{
+   *p_val = strtoull(str, NULL, 0);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_port_group_start()
+{
+    p_current_port_group = osm_qos_policy_port_group_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_port_group_end()
+{
+    if(!p_current_port_group->name)
+    {
+        yyerror("port-group validation failed - no port group name specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->port_groups,
+                        p_current_port_group);
+    p_current_port_group = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_vlarb_scope_start()
+{
+    p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_vlarb_scope_end()
+{
+    if ( !cl_list_count(&p_current_vlarb_scope->group_list) &&
+         !cl_list_count(&p_current_vlarb_scope->across_list) )
+    {
+        yyerror("vlarb-scope validation failed - no port groups specified by 'group' or by 'across'");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->vlarb_tables,
+                        p_current_vlarb_scope);
+    p_current_vlarb_scope = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_sl2vl_scope_start()
+{
+    p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_sl2vl_scope_end()
+{
+    if (!p_current_sl2vl_scope->sl2vl_table_set)
+    {
+        yyerror("sl2vl-scope validation failed - no sl2vl table specified");
+        return -1;
+    }
+    if ( !cl_list_count(&p_current_sl2vl_scope->group_list) &&
+         !cl_list_count(&p_current_sl2vl_scope->across_to_list) &&
+         !cl_list_count(&p_current_sl2vl_scope->across_from_list) )
+    {
+        yyerror("sl2vl-scope validation failed - no port groups specified by 'group', 'across-to' or 'across-from'");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->sl2vl_tables,
+                        p_current_sl2vl_scope);
+    p_current_sl2vl_scope = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_qos_level_start()
+{
+    p_current_qos_level = osm_qos_policy_qos_level_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_qos_level_end()
+{
+    if (!p_current_qos_level->sl_set)
+    {
+        yyerror("qos-level validation failed - no 'sl' specified");
+        return -1;
+    }
+    if (!p_current_qos_level->name)
+    {
+        yyerror("qos-level validation failed - no 'name' specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->qos_levels,
+                        p_current_qos_level);
+    p_current_qos_level = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_match_rule_start()
+{
+    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_match_rule_end()
+{
+    if (!p_current_qos_match_rule->qos_level_name)
+    {
+        yyerror("match-rule validation failed - no 'qos-level-name' specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->qos_match_rules,
+                        p_current_qos_match_rule);
+    p_current_qos_match_rule = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_ulp_match_rule_start()
+{
+    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_ulp_match_rule_end()
+{
+    CL_ASSERT(p_current_qos_match_rule->p_qos_level);
+    cl_list_insert_tail(&__ulp_match_rules,
+                        p_current_qos_match_rule);
+    p_current_qos_match_rule = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_tmp_struct_init()
+{
+    tmp_parser_struct.str[0] = '\0';
+    cl_list_construct(&tmp_parser_struct.str_list);
+    cl_list_init(&tmp_parser_struct.str_list, 10);
+    cl_list_construct(&tmp_parser_struct.num_list);
+    cl_list_init(&tmp_parser_struct.num_list, 10);
+    cl_list_construct(&tmp_parser_struct.num_pair_list);
+    cl_list_init(&tmp_parser_struct.num_pair_list, 10);
+}
+
+/***************************************************
+ ***************************************************/
+
+/*
+ * Do NOT free objects from the temp struct.
+ * Either they are inserted into the parse tree data
+ * structure, or they are already freed when copying
+ * their values to the parse tree data structure.
+ */
+static void __parser_tmp_struct_reset()
+{
+    tmp_parser_struct.str[0] = '\0';
+    cl_list_remove_all(&tmp_parser_struct.str_list);
+    cl_list_remove_all(&tmp_parser_struct.num_list);
+    cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_tmp_struct_destroy()
+{
+    __parser_tmp_struct_reset();
+    cl_list_destroy(&tmp_parser_struct.str_list);
+    cl_list_destroy(&tmp_parser_struct.num_list);
+    cl_list_destroy(&tmp_parser_struct.num_pair_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+#define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL"
+#define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT"
+
+static void __setup_simple_qos_levels()
+{
+    uint8_t i;
+    char tmp_buf[30];
+    memset(osm_qos_policy_simple_qos_levels, 0,
+           sizeof(osm_qos_policy_simple_qos_levels));
+    for (i = 0; i < 16; i++)
+    {
+        osm_qos_policy_simple_qos_levels[i].sl = i;
+        osm_qos_policy_simple_qos_levels[i].sl_set = TRUE;
+        sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i);
+        osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf);
+    }
+
+    memset(&__default_simple_qos_level, 0,
+           sizeof(__default_simple_qos_level));
+    __default_simple_qos_level.name =
+           strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __clear_simple_qos_levels()
+{
+    /*
+     * Simple QoS levels are static.
+     * What's left is to invalidate default simple QoS level.
+     */
+    __default_simple_qos_level.sl_set = FALSE;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __setup_ulp_match_rules()
+{
+    cl_list_construct(&__ulp_match_rules);
+    cl_list_init(&__ulp_match_rules, 10);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __process_ulp_match_rules()
+{
+    cl_list_iterator_t list_iterator;
+    osm_qos_match_rule_t *p_qos_match_rule = NULL;
+
+    list_iterator = cl_list_head(&__ulp_match_rules);
+    while (list_iterator != cl_list_end(&__ulp_match_rules))
+    {
+        p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
+        if (p_qos_match_rule)
+            cl_list_insert_tail(&p_qos_policy->qos_match_rules,
+                                p_qos_match_rule);
+        list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(&__ulp_match_rules);
+}
+
+/***************************************************
+ ***************************************************/
+
+static int OSM_CDECL
+__cmp_num_range(
+    const void * p1,
+    const void * p2)
+{
+    uint64_t * pair1 = *((uint64_t **)p1);
+    uint64_t * pair2 = *((uint64_t **)p2);
+
+    if (pair1[0] < pair2[0])
+        return -1;
+    if (pair1[0] > pair2[0])
+        return 1;
+
+    if (pair1[1] < pair2[1])
+        return -1;
+    if (pair1[1] > pair2[1])
+        return 1;
+
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __sort_reduce_rangearr(
+    uint64_t  **   arr,
+    unsigned       arr_len,
+    uint64_t  ** * p_res_arr,
+    unsigned     * p_res_arr_len )
+{
+    unsigned i = 0;
+    unsigned j = 0;
+    unsigned last_valid_ind = 0;
+    unsigned valid_cnt = 0;
+    uint64_t ** res_arr;
+    boolean_t * is_valid_arr;
+
+    *p_res_arr = NULL;
+    *p_res_arr_len = 0;
+
+    qsort(arr, arr_len, sizeof(uint64_t*), __cmp_num_range);
+
+    is_valid_arr = (boolean_t *)malloc(arr_len * sizeof(boolean_t));
+    is_valid_arr[last_valid_ind] = TRUE;
+    valid_cnt++;
+    for (i = 1; i < arr_len; i++)
+    {
+        if (arr[i][0] <= arr[last_valid_ind][1])
+        {
+            if (arr[i][1] > arr[last_valid_ind][1])
+                arr[last_valid_ind][1] = arr[i][1];
+            free(arr[i]);
+            arr[i] = NULL;
+            is_valid_arr[i] = FALSE;
+        }
+        else if ((arr[i][0] - 1) == arr[last_valid_ind][1])
+        {
+            arr[last_valid_ind][1] = arr[i][1];
+            free(arr[i]);
+            arr[i] = NULL;
+            is_valid_arr[i] = FALSE;
+        }
+        else
+        {
+            is_valid_arr[i] = TRUE;
+            last_valid_ind = i;
+            valid_cnt++;
+        }
+    }
+
+    res_arr = (uint64_t **)malloc(valid_cnt * sizeof(uint64_t *));
+    for (i = 0; i < arr_len; i++)
+    {
+        if (is_valid_arr[i])
+            res_arr[j++] = arr[i];
+    }
+    free(is_valid_arr);
+    free(arr);
+
+    *p_res_arr = res_arr;
+    *p_res_arr_len = valid_cnt;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __pkey_rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len)
+{
+    uint64_t   tmp_pkey;
+    uint64_t * p_pkeys;
+    cl_list_iterator_t list_iterator;
+
+    list_iterator= cl_list_head(p_list);
+    while( list_iterator != cl_list_end(p_list) )
+    {
+       p_pkeys = (uint64_t *)cl_list_obj(list_iterator);
+       p_pkeys[0] &= 0x7fff;
+       p_pkeys[1] &= 0x7fff;
+       if (p_pkeys[0] > p_pkeys[1])
+       {
+           tmp_pkey = p_pkeys[1];
+           p_pkeys[1] = p_pkeys[0];
+           p_pkeys[0] = tmp_pkey;
+       }
+       list_iterator = cl_list_next(list_iterator);
+    }
+
+    __rangelist2rangearr(p_list, p_arr, p_arr_len);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len)
+{
+    cl_list_iterator_t list_iterator;
+    unsigned len = cl_list_count(p_list);
+    unsigned i = 0;
+    uint64_t ** tmp_arr;
+    uint64_t ** res_arr = NULL;
+    unsigned res_arr_len = 0;
+
+    tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
+
+    list_iterator = cl_list_head(p_list);
+    while( list_iterator != cl_list_end(p_list) )
+    {
+       tmp_arr[i++] = (uint64_t *)cl_list_obj(list_iterator);
+       list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(p_list);
+
+    __sort_reduce_rangearr( tmp_arr,
+                            len,
+                            &res_arr,
+                            &res_arr_len );
+    *p_arr = res_arr;
+    *p_arr_len = res_arr_len;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __merge_rangearr(
+    uint64_t  **   range_arr_1,
+    unsigned       range_len_1,
+    uint64_t  **   range_arr_2,
+    unsigned       range_len_2,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len )
+{
+    unsigned i = 0;
+    unsigned j = 0;
+    unsigned len = range_len_1 + range_len_2;
+    uint64_t ** tmp_arr;
+    uint64_t ** res_arr = NULL;
+    unsigned res_arr_len = 0;
+
+    *p_arr = NULL;
+    *p_arr_len = 0;
+
+    tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
+
+    for (i = 0; i < range_len_1; i++)
+       tmp_arr[j++] = range_arr_1[i];
+    for (i = 0; i < range_len_2; i++)
+       tmp_arr[j++] = range_arr_2[i];
+    free(range_arr_1);
+    free(range_arr_2);
+
+    __sort_reduce_rangearr( tmp_arr,
+                            len,
+                            &res_arr,
+                            &res_arr_len );
+    *p_arr = res_arr;
+    *p_arr_len = res_arr_len;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_port_to_port_map(
+    cl_qmap_t   * p_map,
+    osm_physp_t * p_physp)
+{
+    if (cl_qmap_get(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp))) ==
+        cl_qmap_end(p_map))
+    {
+        osm_qos_port_t * p_port = osm_qos_policy_port_create(p_physp);
+        if (p_port)
+            cl_qmap_insert(p_map,
+                           cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+                           &p_port->map_item);
+    }
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_guid_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len)
+{
+    unsigned i;
+    uint64_t guid_ho;
+    osm_port_t * p_osm_port;
+
+    if (!range_arr || !range_len)
+        return;
+
+    for (i = 0; i < range_len; i++) {
+         for (guid_ho = range_arr[i][0]; guid_ho <= range_arr[i][1]; guid_ho++) {
+             p_osm_port =
+                osm_get_port_by_guid(p_qos_policy->p_subn, cl_hton64(guid_ho));
+             if (p_osm_port)
+                 __parser_add_port_to_port_map(p_map, p_osm_port->p_physp);
+         }
+         free(range_arr[i]);
+    }
+    free(range_arr);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_pkey_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len)
+{
+    unsigned i;
+    uint64_t pkey_64;
+    ib_net16_t pkey;
+    osm_prtn_t * p_prtn;
+
+    if (!range_arr || !range_len)
+        return;
+
+    for (i = 0; i < range_len; i++) {
+         for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
+             pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
+             p_prtn = (osm_prtn_t *)
+                 cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
+             if (p_prtn != (osm_prtn_t *)cl_qmap_end(
+                   &p_qos_policy->p_subn->prtn_pkey_tbl)) {
+                 __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
+                 __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
+             }
+         }
+         free(range_arr[i]);
+    }
+    free(range_arr);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_partition_list_to_port_map(
+    cl_qmap_t  * p_map,
+    cl_list_t  * p_list)
+{
+    cl_list_iterator_t    list_iterator;
+    char                * tmp_str;
+    osm_prtn_t          * p_prtn;
+
+    /* extract all the ports from the partition
+       to the port map of this port group */
+    list_iterator = cl_list_head(p_list);
+    while(list_iterator != cl_list_end(p_list)) {
+        tmp_str = (char*)cl_list_obj(list_iterator);
+        if (tmp_str) {
+            p_prtn = osm_prtn_find_by_name(p_qos_policy->p_subn, tmp_str);
+            if (p_prtn) {
+                __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
+                __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
+            }
+            free(tmp_str);
+        }
+        list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(p_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_map_to_port_map(
+    cl_qmap_t * p_dmap,
+    cl_map_t  * p_smap)
+{
+    cl_map_iterator_t map_iterator;
+    osm_physp_t * p_physp;
+
+    if (!p_dmap || !p_smap)
+        return;
+
+    map_iterator = cl_map_head(p_smap);
+    while (map_iterator != cl_map_end(p_smap)) {
+        p_physp = (osm_physp_t*)cl_map_obj(map_iterator);
+        __parser_add_port_to_port_map(p_dmap, p_physp);
+        map_iterator = cl_map_next(map_iterator);
+    }
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __validate_pkeys( uint64_t ** range_arr,
+                             unsigned    range_len,
+                             boolean_t   is_ipoib)
+{
+    unsigned i;
+    uint64_t pkey_64;
+    ib_net16_t pkey;
+    osm_prtn_t * p_prtn;
+
+    if (!range_arr || !range_len)
+        return 0;
+
+    for (i = 0; i < range_len; i++) {
+        for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
+            pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
+            p_prtn = (osm_prtn_t *)
+                cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
+
+            if (p_prtn == (osm_prtn_t *)cl_qmap_end(
+                  &p_qos_policy->p_subn->prtn_pkey_tbl))
+                p_prtn = NULL;
+
+            if (is_ipoib) {
+                /*
+                 * Be very strict for IPoIB partition:
+                 *  - the partition for the pkey have to exist
+                 *  - it has to have at least 2 full members
+                 */
+                if (!p_prtn) {
+                    yyerror("IPoIB partition, pkey 0x%04X - "
+                                       "partition doesn't exist",
+                                       cl_ntoh16(pkey));
+                    return 1;
+                }
+                else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) {
+                    yyerror("IPoIB partition, pkey 0x%04X - "
+                                       "partition has less than two full members",
+                                       cl_ntoh16(pkey));
+                    return 1;
+                }
+            }
+            else if (!p_prtn) {
+                /*
+                 * For non-IPoIB pkey we just want to check that
+                 * the relevant partition exists.
+                 * And even if it doesn't, don't exit - just print
+                 * error message and continue.
+                 */
+                 OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC02: "
+			 "pkey 0x%04X - partition doesn't exist",
+                         cl_ntoh16(pkey));
+            }
+        }
+    }
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
diff --git a/opensm/osm_qos_parser_y.h b/opensm/osm_qos_parser_y.h
new file mode 100644
index 0000000..efe5d7c
--- /dev/null
+++ b/opensm/osm_qos_parser_y.h
@@ -0,0 +1,208 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TK_NUMBER = 258,
+     TK_DASH = 259,
+     TK_DOTDOT = 260,
+     TK_COMMA = 261,
+     TK_ASTERISK = 262,
+     TK_TEXT = 263,
+     TK_QOS_ULPS_START = 264,
+     TK_QOS_ULPS_END = 265,
+     TK_PORT_GROUPS_START = 266,
+     TK_PORT_GROUPS_END = 267,
+     TK_PORT_GROUP_START = 268,
+     TK_PORT_GROUP_END = 269,
+     TK_QOS_SETUP_START = 270,
+     TK_QOS_SETUP_END = 271,
+     TK_VLARB_TABLES_START = 272,
+     TK_VLARB_TABLES_END = 273,
+     TK_VLARB_SCOPE_START = 274,
+     TK_VLARB_SCOPE_END = 275,
+     TK_SL2VL_TABLES_START = 276,
+     TK_SL2VL_TABLES_END = 277,
+     TK_SL2VL_SCOPE_START = 278,
+     TK_SL2VL_SCOPE_END = 279,
+     TK_QOS_LEVELS_START = 280,
+     TK_QOS_LEVELS_END = 281,
+     TK_QOS_LEVEL_START = 282,
+     TK_QOS_LEVEL_END = 283,
+     TK_QOS_MATCH_RULES_START = 284,
+     TK_QOS_MATCH_RULES_END = 285,
+     TK_QOS_MATCH_RULE_START = 286,
+     TK_QOS_MATCH_RULE_END = 287,
+     TK_NAME = 288,
+     TK_USE = 289,
+     TK_PORT_GUID = 290,
+     TK_PORT_NAME = 291,
+     TK_PARTITION = 292,
+     TK_NODE_TYPE = 293,
+     TK_GROUP = 294,
+     TK_ACROSS = 295,
+     TK_VLARB_HIGH = 296,
+     TK_VLARB_LOW = 297,
+     TK_VLARB_HIGH_LIMIT = 298,
+     TK_TO = 299,
+     TK_FROM = 300,
+     TK_ACROSS_TO = 301,
+     TK_ACROSS_FROM = 302,
+     TK_SL2VL_TABLE = 303,
+     TK_SL = 304,
+     TK_MTU_LIMIT = 305,
+     TK_RATE_LIMIT = 306,
+     TK_PACKET_LIFE = 307,
+     TK_PATH_BITS = 308,
+     TK_QOS_CLASS = 309,
+     TK_SOURCE = 310,
+     TK_DESTINATION = 311,
+     TK_SERVICE_ID = 312,
+     TK_QOS_LEVEL_NAME = 313,
+     TK_PKEY = 314,
+     TK_NODE_TYPE_ROUTER = 315,
+     TK_NODE_TYPE_CA = 316,
+     TK_NODE_TYPE_SWITCH = 317,
+     TK_NODE_TYPE_SELF = 318,
+     TK_NODE_TYPE_ALL = 319,
+     TK_ULP_DEFAULT = 320,
+     TK_ULP_ANY_SERVICE_ID = 321,
+     TK_ULP_ANY_PKEY = 322,
+     TK_ULP_ANY_TARGET_PORT_GUID = 323,
+     TK_ULP_SDP_DEFAULT = 324,
+     TK_ULP_SDP_PORT = 325,
+     TK_ULP_RDS_DEFAULT = 326,
+     TK_ULP_RDS_PORT = 327,
+     TK_ULP_ISER_DEFAULT = 328,
+     TK_ULP_ISER_PORT = 329,
+     TK_ULP_SRP_GUID = 330,
+     TK_ULP_IPOIB_DEFAULT = 331,
+     TK_ULP_IPOIB_PKEY = 332
+   };
+#endif
+/* Tokens.  */
+#define TK_NUMBER 258
+#define TK_DASH 259
+#define TK_DOTDOT 260
+#define TK_COMMA 261
+#define TK_ASTERISK 262
+#define TK_TEXT 263
+#define TK_QOS_ULPS_START 264
+#define TK_QOS_ULPS_END 265
+#define TK_PORT_GROUPS_START 266
+#define TK_PORT_GROUPS_END 267
+#define TK_PORT_GROUP_START 268
+#define TK_PORT_GROUP_END 269
+#define TK_QOS_SETUP_START 270
+#define TK_QOS_SETUP_END 271
+#define TK_VLARB_TABLES_START 272
+#define TK_VLARB_TABLES_END 273
+#define TK_VLARB_SCOPE_START 274
+#define TK_VLARB_SCOPE_END 275
+#define TK_SL2VL_TABLES_START 276
+#define TK_SL2VL_TABLES_END 277
+#define TK_SL2VL_SCOPE_START 278
+#define TK_SL2VL_SCOPE_END 279
+#define TK_QOS_LEVELS_START 280
+#define TK_QOS_LEVELS_END 281
+#define TK_QOS_LEVEL_START 282
+#define TK_QOS_LEVEL_END 283
+#define TK_QOS_MATCH_RULES_START 284
+#define TK_QOS_MATCH_RULES_END 285
+#define TK_QOS_MATCH_RULE_START 286
+#define TK_QOS_MATCH_RULE_END 287
+#define TK_NAME 288
+#define TK_USE 289
+#define TK_PORT_GUID 290
+#define TK_PORT_NAME 291
+#define TK_PARTITION 292
+#define TK_NODE_TYPE 293
+#define TK_GROUP 294
+#define TK_ACROSS 295
+#define TK_VLARB_HIGH 296
+#define TK_VLARB_LOW 297
+#define TK_VLARB_HIGH_LIMIT 298
+#define TK_TO 299
+#define TK_FROM 300
+#define TK_ACROSS_TO 301
+#define TK_ACROSS_FROM 302
+#define TK_SL2VL_TABLE 303
+#define TK_SL 304
+#define TK_MTU_LIMIT 305
+#define TK_RATE_LIMIT 306
+#define TK_PACKET_LIFE 307
+#define TK_PATH_BITS 308
+#define TK_QOS_CLASS 309
+#define TK_SOURCE 310
+#define TK_DESTINATION 311
+#define TK_SERVICE_ID 312
+#define TK_QOS_LEVEL_NAME 313
+#define TK_PKEY 314
+#define TK_NODE_TYPE_ROUTER 315
+#define TK_NODE_TYPE_CA 316
+#define TK_NODE_TYPE_SWITCH 317
+#define TK_NODE_TYPE_SELF 318
+#define TK_NODE_TYPE_ALL 319
+#define TK_ULP_DEFAULT 320
+#define TK_ULP_ANY_SERVICE_ID 321
+#define TK_ULP_ANY_PKEY 322
+#define TK_ULP_ANY_TARGET_PORT_GUID 323
+#define TK_ULP_SDP_DEFAULT 324
+#define TK_ULP_SDP_PORT 325
+#define TK_ULP_RDS_DEFAULT 326
+#define TK_ULP_RDS_PORT 327
+#define TK_ULP_ISER_DEFAULT 328
+#define TK_ULP_ISER_PORT 329
+#define TK_ULP_SRP_GUID 330
+#define TK_ULP_IPOIB_DEFAULT 331
+#define TK_ULP_IPOIB_PKEY 332
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE yylval;
+
+
diff --git a/opensm/osm_qos_parser_y.y b/opensm/osm_qos_parser_y.y
new file mode 100644
index 0000000..6b5a9b1
--- /dev/null
+++ b/opensm/osm_qos_parser_y.y
@@ -0,0 +1,3063 @@
+%{
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 HNR Consulting. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Grammar of OSM QoS parser.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_qos_policy.h>
+
+#define OSM_QOS_POLICY_MAX_LINE_LEN         1024*10
+#define OSM_QOS_POLICY_SL2VL_TABLE_LEN      IB_MAX_NUM_VLS
+#define OSM_QOS_POLICY_MAX_VL_NUM           IB_MAX_NUM_VLS
+
+typedef struct tmp_parser_struct_t_ {
+    char       str[OSM_QOS_POLICY_MAX_LINE_LEN];
+    uint64_t   num_pair[2];
+    cl_list_t  str_list;
+    cl_list_t  num_list;
+    cl_list_t  num_pair_list;
+} tmp_parser_struct_t;
+
+static void __parser_tmp_struct_init();
+static void __parser_tmp_struct_reset();
+static void __parser_tmp_struct_destroy();
+
+static char * __parser_strip_white(char * str);
+
+static void __parser_str2uint64(uint64_t * p_val, char * str);
+
+static void __parser_port_group_start();
+static int __parser_port_group_end();
+
+static void __parser_sl2vl_scope_start();
+static int __parser_sl2vl_scope_end();
+
+static void __parser_vlarb_scope_start();
+static int __parser_vlarb_scope_end();
+
+static void __parser_qos_level_start();
+static int __parser_qos_level_end();
+
+static void __parser_match_rule_start();
+static int __parser_match_rule_end();
+
+static void __parser_ulp_match_rule_start();
+static int __parser_ulp_match_rule_end();
+
+static void __pkey_rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len);
+
+static void __rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len);
+
+static void __merge_rangearr(
+    uint64_t  **   range_arr_1,
+    unsigned       range_len_1,
+    uint64_t  **   range_arr_2,
+    unsigned       range_len_2,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len );
+
+static void __parser_add_port_to_port_map(
+    cl_qmap_t   * p_map,
+    osm_physp_t * p_physp);
+
+static void __parser_add_guid_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len);
+
+static void __parser_add_pkey_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len);
+
+static void __parser_add_partition_list_to_port_map(
+    cl_qmap_t  * p_map,
+    cl_list_t  * p_list);
+
+static void __parser_add_map_to_port_map(
+    cl_qmap_t * p_dmap,
+    cl_map_t  * p_smap);
+
+static int __validate_pkeys(
+    uint64_t ** range_arr,
+    unsigned    range_len,
+    boolean_t   is_ipoib);
+
+static void __setup_simple_qos_levels();
+static void __clear_simple_qos_levels();
+static void __setup_ulp_match_rules();
+static void __process_ulp_match_rules();
+static void yyerror(const char *format, ...);
+
+extern char * yytext;
+extern int yylex (void);
+extern FILE * yyin;
+extern int errno;
+int yyparse();
+
+#define RESET_BUFFER  __parser_tmp_struct_reset()
+
+tmp_parser_struct_t tmp_parser_struct;
+
+int column_num;
+int line_num;
+
+osm_qos_policy_t       * p_qos_policy = NULL;
+osm_qos_port_group_t   * p_current_port_group = NULL;
+osm_qos_sl2vl_scope_t  * p_current_sl2vl_scope = NULL;
+osm_qos_vlarb_scope_t  * p_current_vlarb_scope = NULL;
+osm_qos_level_t        * p_current_qos_level = NULL;
+osm_qos_match_rule_t   * p_current_qos_match_rule = NULL;
+osm_log_t              * p_qos_parser_osm_log;
+
+/* 16 Simple QoS Levels - one for each SL */
+static osm_qos_level_t osm_qos_policy_simple_qos_levels[16];
+
+/* Default Simple QoS Level */
+osm_qos_level_t __default_simple_qos_level;
+
+/*
+ * List of match rules that will be generated by the
+ * qos-ulp section. These rules are concatenated to
+ * the end of the usual matching rules list at the
+ * end of parsing.
+ */
+static cl_list_t __ulp_match_rules;
+
+/***************************************************/
+
+%}
+
+%token TK_NUMBER
+%token TK_DASH
+%token TK_DOTDOT
+%token TK_COMMA
+%token TK_ASTERISK
+%token TK_TEXT
+
+%token TK_QOS_ULPS_START
+%token TK_QOS_ULPS_END
+
+%token TK_PORT_GROUPS_START
+%token TK_PORT_GROUPS_END
+%token TK_PORT_GROUP_START
+%token TK_PORT_GROUP_END
+
+%token TK_QOS_SETUP_START
+%token TK_QOS_SETUP_END
+%token TK_VLARB_TABLES_START
+%token TK_VLARB_TABLES_END
+%token TK_VLARB_SCOPE_START
+%token TK_VLARB_SCOPE_END
+
+%token TK_SL2VL_TABLES_START
+%token TK_SL2VL_TABLES_END
+%token TK_SL2VL_SCOPE_START
+%token TK_SL2VL_SCOPE_END
+
+%token TK_QOS_LEVELS_START
+%token TK_QOS_LEVELS_END
+%token TK_QOS_LEVEL_START
+%token TK_QOS_LEVEL_END
+
+%token TK_QOS_MATCH_RULES_START
+%token TK_QOS_MATCH_RULES_END
+%token TK_QOS_MATCH_RULE_START
+%token TK_QOS_MATCH_RULE_END
+
+%token TK_NAME
+%token TK_USE
+%token TK_PORT_GUID
+%token TK_PORT_NAME
+%token TK_PARTITION
+%token TK_NODE_TYPE
+%token TK_GROUP
+%token TK_ACROSS
+%token TK_VLARB_HIGH
+%token TK_VLARB_LOW
+%token TK_VLARB_HIGH_LIMIT
+%token TK_TO
+%token TK_FROM
+%token TK_ACROSS_TO
+%token TK_ACROSS_FROM
+%token TK_SL2VL_TABLE
+%token TK_SL
+%token TK_MTU_LIMIT
+%token TK_RATE_LIMIT
+%token TK_PACKET_LIFE
+%token TK_PATH_BITS
+%token TK_QOS_CLASS
+%token TK_SOURCE
+%token TK_DESTINATION
+%token TK_SERVICE_ID
+%token TK_QOS_LEVEL_NAME
+%token TK_PKEY
+
+%token TK_NODE_TYPE_ROUTER
+%token TK_NODE_TYPE_CA
+%token TK_NODE_TYPE_SWITCH
+%token TK_NODE_TYPE_SELF
+%token TK_NODE_TYPE_ALL
+
+%token TK_ULP_DEFAULT
+%token TK_ULP_ANY_SERVICE_ID
+%token TK_ULP_ANY_PKEY
+%token TK_ULP_ANY_TARGET_PORT_GUID
+%token TK_ULP_SDP_DEFAULT
+%token TK_ULP_SDP_PORT
+%token TK_ULP_RDS_DEFAULT
+%token TK_ULP_RDS_PORT
+%token TK_ULP_ISER_DEFAULT
+%token TK_ULP_ISER_PORT
+%token TK_ULP_SRP_GUID
+%token TK_ULP_IPOIB_DEFAULT
+%token TK_ULP_IPOIB_PKEY
+
+%start head
+
+%%
+
+head:               qos_policy_entries
+                    ;
+
+qos_policy_entries: /* empty */
+                    | qos_policy_entries qos_policy_entry
+                    ;
+
+qos_policy_entry:     qos_ulps_section
+                    | port_groups_section
+                    | qos_setup_section
+                    | qos_levels_section
+                    | qos_match_rules_section
+                    ;
+
+    /*
+     * Parsing qos-ulps:
+     * -------------------
+     *  qos-ulps
+     *      default                       : 0 #default SL
+     *      sdp, port-num 30000           : 1 #SL for SDP when destination port is 30000
+     *      sdp, port-num 10000-20000     : 2
+     *      sdp                           : 0 #default SL for SDP
+     *      srp, target-port-guid 0x1234  : 2
+     *      rds, port-num 25000           : 2 #SL for RDS when destination port is 25000
+     *      rds,                          : 0 #default SL for RDS
+     *      iser, port-num 900            : 5 #SL for iSER where target port is 900
+     *      iser                          : 4 #default SL for iSER
+     *      ipoib, pkey 0x0001            : 5 #SL for IPoIB on partition with pkey 0x0001
+     *      ipoib                         : 6 #default IPoIB partition - pkey=0x7FFF
+     *      any, service-id 0x6234        : 2
+     *      any, pkey 0x0ABC              : 3
+     *      any, target-port-guid 0x0ABC-0xFFFFF : 6
+     *  end-qos-ulps
+     */
+
+qos_ulps_section: TK_QOS_ULPS_START qos_ulps TK_QOS_ULPS_END
+                     ;
+
+qos_ulps:             qos_ulp
+                    | qos_ulps qos_ulp
+                    ;
+
+    /*
+     * Parsing port groups:
+     * -------------------
+     *  port-groups
+     *       port-group
+     *          name: Storage
+     *          use: our SRP storage targets
+     *          port-guid: 0x1000000000000001,0x1000000000000002
+     *          ...
+     *          port-name: vs1 HCA-1/P1
+     *          port-name: node_description/P2
+     *          ...
+     *          pkey: 0x00FF-0x0FFF
+     *          ...
+     *          partition: Part1
+     *          ...
+     *          node-type: ROUTER,CA,SWITCH,SELF,ALL
+     *          ...
+     *      end-port-group
+     *      port-group
+     *          ...
+     *      end-port-group
+     *  end-port-groups
+     */
+
+
+port_groups_section: TK_PORT_GROUPS_START port_groups TK_PORT_GROUPS_END
+                     ;
+
+port_groups:        port_group
+                    | port_groups port_group
+                    ;
+
+port_group:         port_group_start port_group_entries port_group_end
+                    ;
+
+port_group_start:   TK_PORT_GROUP_START {
+                        __parser_port_group_start();
+                    }
+                    ;
+
+port_group_end:     TK_PORT_GROUP_END {
+                        if ( __parser_port_group_end() )
+                            return 1;
+                    }
+                    ;
+
+port_group_entries: /* empty */
+                    | port_group_entries port_group_entry
+                    ;
+
+port_group_entry:     port_group_name
+                    | port_group_use
+                    | port_group_port_guid
+                    | port_group_port_name
+                    | port_group_pkey
+                    | port_group_partition
+                    | port_group_node_type
+                    ;
+
+
+    /*
+     * Parsing qos setup:
+     * -----------------
+     *  qos-setup
+     *      vlarb-tables
+     *          vlarb-scope
+     *              ...
+     *          end-vlarb-scope
+     *          vlarb-scope
+     *              ...
+     *          end-vlarb-scope
+     *     end-vlarb-tables
+     *     sl2vl-tables
+     *          sl2vl-scope
+     *              ...
+     *         end-sl2vl-scope
+     *         sl2vl-scope
+     *              ...
+     *          end-sl2vl-scope
+     *     end-sl2vl-tables
+     *  end-qos-setup
+     */
+
+qos_setup_section:  TK_QOS_SETUP_START qos_setup_items TK_QOS_SETUP_END
+                    ;
+
+qos_setup_items:    /* empty */
+                    | qos_setup_items vlarb_tables
+                    | qos_setup_items sl2vl_tables
+                    ;
+
+    /* Parsing vlarb-tables */
+
+vlarb_tables:       TK_VLARB_TABLES_START vlarb_scope_items TK_VLARB_TABLES_END
+                    ;
+
+vlarb_scope_items:  /* empty */
+                    | vlarb_scope_items vlarb_scope
+                    ;
+
+vlarb_scope:        vlarb_scope_start vlarb_scope_entries vlarb_scope_end
+                    ;
+
+vlarb_scope_start:  TK_VLARB_SCOPE_START {
+                        __parser_vlarb_scope_start();
+                    }
+                    ;
+
+vlarb_scope_end:    TK_VLARB_SCOPE_END {
+                        if ( __parser_vlarb_scope_end() )
+                            return 1;
+                    }
+                    ;
+
+vlarb_scope_entries:/* empty */
+                    | vlarb_scope_entries vlarb_scope_entry
+                    ;
+
+    /*
+     *          vlarb-scope
+     *              group: Storage
+     *              ...
+     *              across: Storage
+     *              ...
+     *              vlarb-high: 0:255,1:127,2:63,3:31,4:15,5:7,6:3,7:1
+     *              vlarb-low: 8:255,9:127,10:63,11:31,12:15,13:7,14:3
+     *              vl-high-limit: 10
+     *          end-vlarb-scope
+     */
+
+vlarb_scope_entry:    vlarb_scope_group
+                    | vlarb_scope_across
+                    | vlarb_scope_vlarb_high
+                    | vlarb_scope_vlarb_low
+                    | vlarb_scope_vlarb_high_limit
+                    ;
+
+    /* Parsing sl2vl-tables */
+
+sl2vl_tables:       TK_SL2VL_TABLES_START sl2vl_scope_items TK_SL2VL_TABLES_END
+                    ;
+
+sl2vl_scope_items:  /* empty */
+                    | sl2vl_scope_items sl2vl_scope
+                    ;
+
+sl2vl_scope:        sl2vl_scope_start sl2vl_scope_entries sl2vl_scope_end
+                    ;
+
+sl2vl_scope_start:  TK_SL2VL_SCOPE_START {
+                        __parser_sl2vl_scope_start();
+                    }
+                    ;
+
+sl2vl_scope_end:    TK_SL2VL_SCOPE_END {
+                        if ( __parser_sl2vl_scope_end() )
+                            return 1;
+                    }
+                    ;
+
+sl2vl_scope_entries:/* empty */
+                    | sl2vl_scope_entries sl2vl_scope_entry
+                    ;
+
+    /*
+     *          sl2vl-scope
+     *              group: Part1
+     *              ...
+     *              from: *
+     *              ...
+     *              to: *
+     *              ...
+     *              across-to: Storage2
+     *              ...
+     *              across-from: Storage1
+     *              ...
+     *              sl2vl-table: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+     *          end-sl2vl-scope
+     */
+
+sl2vl_scope_entry:    sl2vl_scope_group
+                    | sl2vl_scope_across
+                    | sl2vl_scope_across_from
+                    | sl2vl_scope_across_to
+                    | sl2vl_scope_from
+                    | sl2vl_scope_to
+                    | sl2vl_scope_sl2vl_table
+                    ;
+
+    /*
+     * Parsing qos-levels:
+     * ------------------
+     *  qos-levels
+     *      qos-level
+     *          name: qos_level_1
+     *          use: for the lowest priority communication
+     *          sl: 15
+     *          mtu-limit: 1
+     *          rate-limit: 1
+     *          packet-life: 12
+     *          path-bits: 2,4,8-32
+     *          pkey: 0x00FF-0x0FFF
+     *      end-qos-level
+     *          ...
+     *      qos-level
+     *    end-qos-level
+     *  end-qos-levels
+     */
+
+
+qos_levels_section: TK_QOS_LEVELS_START qos_levels TK_QOS_LEVELS_END
+                    ;
+
+qos_levels:         /* empty */
+                    | qos_levels qos_level
+                    ;
+
+qos_level:          qos_level_start qos_level_entries qos_level_end
+                    ;
+
+qos_level_start:    TK_QOS_LEVEL_START {
+                        __parser_qos_level_start();
+                    }
+                    ;
+
+qos_level_end:      TK_QOS_LEVEL_END {
+                        if ( __parser_qos_level_end() )
+                            return 1;
+                    }
+                    ;
+
+qos_level_entries:  /* empty */
+                    | qos_level_entries qos_level_entry
+                    ;
+
+qos_level_entry:      qos_level_name
+                    | qos_level_use
+                    | qos_level_sl
+                    | qos_level_mtu_limit
+                    | qos_level_rate_limit
+                    | qos_level_packet_life
+                    | qos_level_path_bits
+                    | qos_level_pkey
+                    ;
+
+    /*
+     * Parsing qos-match-rules:
+     * -----------------------
+     *  qos-match-rules
+     *      qos-match-rule
+     *          use: low latency by class 7-9 or 11 and bla bla
+     *          qos-class: 7-9,11
+     *          qos-level-name: default
+     *          source: Storage
+     *          destination: Storage
+     *          service-id: 22,4719-5000
+     *          pkey: 0x00FF-0x0FFF
+     *      end-qos-match-rule
+     *      qos-match-rule
+     *          ...
+     *      end-qos-match-rule
+     *  end-qos-match-rules
+     */
+
+qos_match_rules_section: TK_QOS_MATCH_RULES_START qos_match_rules TK_QOS_MATCH_RULES_END
+                    ;
+
+qos_match_rules:    /* empty */
+                    | qos_match_rules qos_match_rule
+                    ;
+
+qos_match_rule:     qos_match_rule_start qos_match_rule_entries qos_match_rule_end
+                    ;
+
+qos_match_rule_start: TK_QOS_MATCH_RULE_START {
+                        __parser_match_rule_start();
+                    }
+                    ;
+
+qos_match_rule_end: TK_QOS_MATCH_RULE_END {
+                        if ( __parser_match_rule_end() )
+                            return 1;
+                    }
+                    ;
+
+qos_match_rule_entries: /* empty */
+                    | qos_match_rule_entries qos_match_rule_entry
+                    ;
+
+qos_match_rule_entry: qos_match_rule_use
+                    | qos_match_rule_qos_class
+                    | qos_match_rule_qos_level_name
+                    | qos_match_rule_source
+                    | qos_match_rule_destination
+                    | qos_match_rule_service_id
+                    | qos_match_rule_pkey
+                    ;
+
+
+    /*
+     * Parsing qos-ulps:
+     * -----------------
+     *   default
+     *   sdp
+     *   sdp with port-num
+     *   rds
+     *   rds with port-num
+     *   srp with port-guid
+     *   iser
+     *   iser with port-num
+     *   ipoib
+     *   ipoib with pkey
+     *   any with service-id
+     *   any with pkey
+     *   any with target-port-guid
+     */
+
+qos_ulp:            TK_ULP_DEFAULT single_number {
+                        /* parsing default ulp rule: "default: num" */
+                        cl_list_iterator_t    list_iterator;
+                        uint64_t            * p_tmp_num;
+
+                        list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                        p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                        if (*p_tmp_num > 15)
+                        {
+                            yyerror("illegal SL value");
+                            return 1;
+                        }
+                        __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num);
+                        __default_simple_qos_level.sl_set = TRUE;
+                        free(p_tmp_num);
+                        cl_list_remove_all(&tmp_parser_struct.num_list);
+                    }
+
+                    | qos_ulp_type_any_service list_of_ranges TK_DOTDOT {
+                        /* "any, service-id ... : sl" - one instance of list of ranges */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have service ids");
+                            return 1;
+                        }
+
+                        /* get all the service id ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_any_pkey list_of_ranges TK_DOTDOT {
+                        /* "any, pkey ... : sl" - one instance of list of ranges */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have pkeys");
+                            return 1;
+                        }
+
+                        /* get all the pkey ranges */
+                        __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = range_len;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_any_target_port_guid list_of_ranges TK_DOTDOT {
+                        /* any, target-port-guid ... : sl */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("ULP rule doesn't have port guids");
+                            return 1;
+                        }
+
+                        /* create a new port group with these ports */
+                        __parser_port_group_start();
+
+                        p_current_port_group->name = strdup("_ULP_Targets_");
+                        p_current_port_group->use = strdup("Generated from ULP rules");
+
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        __parser_add_guid_range_to_port_map(
+                                              &p_current_port_group->port_map,
+                                              range_arr,
+                                              range_len);
+
+                        /* add this port group to the destination
+                           groups of the current match rule */
+                        cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
+                                            p_current_port_group);
+
+                        __parser_port_group_end();
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_sdp_default {
+                        /* "sdp : sl" - default SL for SDP */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                        range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_sdp_port list_of_ranges TK_DOTDOT {
+                        /* sdp with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("SDP ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_rds_default {
+                        /* "rds : sl" - default SL for RDS */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] =
+                           OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + OSM_QOS_POLICY_ULP_RDS_PORT;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_rds_port list_of_ranges TK_DOTDOT {
+                        /* rds with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("RDS ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_iser_default {
+                        /* "iSER : sl" - default SL for iSER */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] =
+                           OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT;
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = 1;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_iser_port list_of_ranges TK_DOTDOT {
+                        /* iser with port numbers */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+                        unsigned    i;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("iSER ULP rule doesn't have port numbers");
+                            return 1;
+                        }
+
+                        /* get all the port ranges */
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+                        /* now translate these port numbers into service ids */
+                        for (i = 0; i < range_len; i++)
+                        {
+                            if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
+                            {
+                                yyerror("SDP port number out of range");
+                                return 1;
+                            }
+                            range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
+                            range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
+                        }
+
+                        p_current_qos_match_rule->service_id_range_arr = range_arr;
+                        p_current_qos_match_rule->service_id_range_len = range_len;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_srp_guid list_of_ranges TK_DOTDOT {
+                        /* srp with target guids - this rule is similar
+                           to writing 'any' ulp with target port guids */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("SRP ULP rule doesn't have port guids");
+                            return 1;
+                        }
+
+                        /* create a new port group with these ports */
+                        __parser_port_group_start();
+
+                        p_current_port_group->name = strdup("_SRP_Targets_");
+                        p_current_port_group->use = strdup("Generated from ULP rules");
+
+                        __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        __parser_add_guid_range_to_port_map(
+                                              &p_current_port_group->port_map,
+                                              range_arr,
+                                              range_len);
+
+                        /* add this port group to the destination
+                           groups of the current match rule */
+                        cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
+                                            p_current_port_group);
+
+                        __parser_port_group_end();
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_ipoib_default {
+                        /* ipoib w/o any pkeys (default pkey) */
+                        uint64_t ** range_arr =
+                               (uint64_t **)malloc(sizeof(uint64_t *));
+                        range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
+                        range_arr[0][0] = range_arr[0][1] = 0x7fff;
+
+                        /*
+                         * Although we know that the default partition exists,
+                         * we still need to validate it by checking that it has
+                         * at least two full members. Otherwise IPoIB won't work.
+                         */
+                        if (__validate_pkeys(range_arr, 1, TRUE))
+                            return 1;
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = 1;
+
+                    } qos_ulp_sl
+
+                    | qos_ulp_type_ipoib_pkey list_of_ranges TK_DOTDOT {
+                        /* ipoib with pkeys */
+                        uint64_t ** range_arr;
+                        unsigned    range_len;
+
+                        if (!cl_list_count(&tmp_parser_struct.num_pair_list))
+                        {
+                            yyerror("IPoIB ULP rule doesn't have pkeys");
+                            return 1;
+                        }
+
+                        /* get all the pkey ranges */
+                        __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                              &range_arr,
+                                              &range_len );
+
+                        /*
+                         * Validate pkeys.
+                         * For IPoIB pkeys the validation is strict.
+                         * If some problem would be found, parsing will
+                         * be aborted with a proper error messages.
+                         */
+                        if (__validate_pkeys(range_arr, range_len, TRUE))
+                            return 1;
+
+                        p_current_qos_match_rule->pkey_range_arr = range_arr;
+                        p_current_qos_match_rule->pkey_range_len = range_len;
+
+                    } qos_ulp_sl
+                    ;
+
+qos_ulp_type_any_service: TK_ULP_ANY_SERVICE_ID
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_any_pkey: TK_ULP_ANY_PKEY
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_any_target_port_guid: TK_ULP_ANY_TARGET_PORT_GUID
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_sdp_default: TK_ULP_SDP_DEFAULT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_sdp_port: TK_ULP_SDP_PORT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_rds_default: TK_ULP_RDS_DEFAULT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_rds_port: TK_ULP_RDS_PORT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_iser_default: TK_ULP_ISER_DEFAULT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_iser_port: TK_ULP_ISER_PORT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_srp_guid: TK_ULP_SRP_GUID
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_ipoib_default: TK_ULP_IPOIB_DEFAULT
+                    { __parser_ulp_match_rule_start(); };
+
+qos_ulp_type_ipoib_pkey: TK_ULP_IPOIB_PKEY
+                    { __parser_ulp_match_rule_start(); };
+
+
+qos_ulp_sl:   single_number {
+                        /* get the SL for ULP rules */
+                        cl_list_iterator_t  list_iterator;
+                        uint64_t          * p_tmp_num;
+                        uint8_t             sl;
+
+                        list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                        p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                        if (*p_tmp_num > 15)
+                        {
+                            yyerror("illegal SL value");
+                            return 1;
+                        }
+
+                        sl = (uint8_t)(*p_tmp_num);
+                        free(p_tmp_num);
+                        cl_list_remove_all(&tmp_parser_struct.num_list);
+
+                        p_current_qos_match_rule->p_qos_level =
+                                 &osm_qos_policy_simple_qos_levels[sl];
+                        p_current_qos_match_rule->qos_level_name =
+                                 strdup(osm_qos_policy_simple_qos_levels[sl].name);
+
+                        if (__parser_ulp_match_rule_end())
+                            return 1;
+                    }
+                    ;
+
+    /*
+     *  port_group_entry values:
+     *      port_group_name
+     *      port_group_use
+     *      port_group_port_guid
+     *      port_group_port_name
+     *      port_group_pkey
+     *      port_group_partition
+     *      port_group_node_type
+     */
+
+port_group_name:        port_group_name_start single_string {
+                            /* 'name' of 'port-group' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_port_group->name)
+                            {
+                                yyerror("port-group has multiple 'name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_port_group->name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+port_group_name_start:  TK_NAME {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_use:         port_group_use_start single_string {
+                            /* 'use' of 'port-group' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_port_group->use)
+                            {
+                                yyerror("port-group has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_port_group->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+port_group_use_start:   TK_USE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_port_name:   port_group_port_name_start string_list {
+                            /* 'port-name' in 'port-group' - any num of instances */
+                            cl_list_iterator_t list_iterator;
+                            osm_node_t * p_node;
+                            osm_physp_t * p_physp;
+                            unsigned port_num;
+                            char * tmp_str;
+                            char * port_str;
+
+                            /* parsing port name strings */
+                            for (list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                                 list_iterator != cl_list_end(&tmp_parser_struct.str_list);
+                                 list_iterator = cl_list_next(list_iterator))
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                {
+                                    /* last slash in port name string is a separator
+                                       between node name and port number */
+                                    port_str = strrchr(tmp_str, '/');
+                                    if (!port_str || (strlen(port_str) < 3) ||
+                                        (port_str[1] != 'p' && port_str[1] != 'P')) {
+                                        yyerror("'%s' - illegal port name",
+                                                           tmp_str);
+                                        free(tmp_str);
+                                        cl_list_remove_all(&tmp_parser_struct.str_list);
+                                        return 1;
+                                    }
+
+                                    if (!(port_num = strtoul(&port_str[2],NULL,0))) {
+                                        yyerror(
+                                               "'%s' - illegal port number in port name",
+                                               tmp_str);
+                                        free(tmp_str);
+                                        cl_list_remove_all(&tmp_parser_struct.str_list);
+                                        return 1;
+                                    }
+
+                                    /* separate node name from port number */
+                                    port_str[0] = '\0';
+
+                                    if (st_lookup(p_qos_policy->p_node_hash,
+                                                  (st_data_t)tmp_str,
+                                                  (void *)&p_node))
+                                    {
+                                        /* we found the node, now get the right port */
+                                        p_physp = osm_node_get_physp_ptr(p_node, port_num);
+                                        if (!p_physp) {
+                                            yyerror(
+                                                   "'%s' - port number out of range in port name",
+                                                   tmp_str);
+                                            free(tmp_str);
+                                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                                            return 1;
+                                        }
+                                        /* we found the port, now add it to guid table */
+                                        __parser_add_port_to_port_map(&p_current_port_group->port_map,
+                                                                      p_physp);
+                                    }
+                                    free(tmp_str);
+                                }
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+port_group_port_name_start: TK_PORT_NAME {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_port_guid:   port_group_port_guid_start list_of_ranges {
+                            /* 'port-guid' in 'port-group' - any num of instances */
+                            /* list of guid ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                __parser_add_guid_range_to_port_map(
+                                                      &p_current_port_group->port_map,
+                                                      range_arr,
+                                                      range_len);
+                            }
+                        }
+                        ;
+
+port_group_port_guid_start: TK_PORT_GUID {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_pkey:        port_group_pkey_start list_of_ranges {
+                            /* 'pkey' in 'port-group' - any num of instances */
+                            /* list of pkey ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                __parser_add_pkey_range_to_port_map(
+                                                      &p_current_port_group->port_map,
+                                                      range_arr,
+                                                      range_len);
+                            }
+                        }
+                        ;
+
+port_group_pkey_start:  TK_PKEY {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_partition:  port_group_partition_start string_list {
+                            /* 'partition' in 'port-group' - any num of instances */
+                            __parser_add_partition_list_to_port_map(
+                                               &p_current_port_group->port_map,
+                                               &tmp_parser_struct.str_list);
+                        }
+                        ;
+
+port_group_partition_start: TK_PARTITION {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_node_type:   port_group_node_type_start port_group_node_type_list {
+                            /* 'node-type' in 'port-group' - any num of instances */
+                        }
+                        ;
+
+port_group_node_type_start: TK_NODE_TYPE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+port_group_node_type_list:  node_type_item
+                        |   port_group_node_type_list TK_COMMA node_type_item
+                        ;
+
+node_type_item:           node_type_ca
+                        | node_type_switch
+                        | node_type_router
+                        | node_type_all
+                        | node_type_self
+                        ;
+
+node_type_ca:           TK_NODE_TYPE_CA {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_CA;
+                        }
+                        ;
+
+node_type_switch:       TK_NODE_TYPE_SWITCH {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_SWITCH;
+                        }
+                        ;
+
+node_type_router:       TK_NODE_TYPE_ROUTER {
+                            p_current_port_group->node_types |=
+                               OSM_QOS_POLICY_NODE_TYPE_ROUTER;
+                        }
+                        ;
+
+node_type_all:          TK_NODE_TYPE_ALL {
+                            p_current_port_group->node_types |=
+                               (OSM_QOS_POLICY_NODE_TYPE_CA |
+                                OSM_QOS_POLICY_NODE_TYPE_SWITCH |
+                                OSM_QOS_POLICY_NODE_TYPE_ROUTER);
+                        }
+                        ;
+
+node_type_self:         TK_NODE_TYPE_SELF {
+                            osm_port_t * p_osm_port =
+                                osm_get_port_by_guid(p_qos_policy->p_subn,
+                                     p_qos_policy->p_subn->sm_port_guid);
+                            if (p_osm_port)
+                                __parser_add_port_to_port_map(
+                                   &p_current_port_group->port_map,
+                                   p_osm_port->p_physp);
+                        }
+                        ;
+
+    /*
+     *  vlarb_scope_entry values:
+     *      vlarb_scope_group
+     *      vlarb_scope_across
+     *      vlarb_scope_vlarb_high
+     *      vlarb_scope_vlarb_low
+     *      vlarb_scope_vlarb_high_limit
+     */
+
+
+
+vlarb_scope_group:      vlarb_scope_group_start string_list {
+                            /* 'group' in 'vlarb-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->group_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+vlarb_scope_group_start: TK_GROUP {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+vlarb_scope_across: vlarb_scope_across_start string_list {
+                            /* 'across' in 'vlarb-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->across_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+vlarb_scope_across_start: TK_ACROSS {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+vlarb_scope_vlarb_high_limit:  vlarb_scope_vlarb_high_limit_start single_number {
+                            /* 'vl-high-limit' in 'vlarb-scope' - one instance of one number */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * p_tmp_num;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
+                            if (p_tmp_num)
+                            {
+                                p_current_vlarb_scope->vl_high_limit = (uint32_t)(*p_tmp_num);
+                                p_current_vlarb_scope->vl_high_limit_set = TRUE;
+                                free(p_tmp_num);
+                            }
+
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+vlarb_scope_vlarb_high_limit_start: TK_VLARB_HIGH_LIMIT {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+vlarb_scope_vlarb_high: vlarb_scope_vlarb_high_start num_list_with_dotdot {
+                            /* 'vlarb-high' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->vlarb_high_list,num_pair);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+                        ;
+
+vlarb_scope_vlarb_high_start: TK_VLARB_HIGH {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+vlarb_scope_vlarb_low:  vlarb_scope_vlarb_low_start num_list_with_dotdot {
+                            /* 'vlarb-low' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                    cl_list_insert_tail(&p_current_vlarb_scope->vlarb_low_list,num_pair);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+                        ;
+
+vlarb_scope_vlarb_low_start: TK_VLARB_LOW {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+    /*
+     *  sl2vl_scope_entry values:
+     *      sl2vl_scope_group
+     *      sl2vl_scope_across
+     *      sl2vl_scope_across_from
+     *      sl2vl_scope_across_to
+     *      sl2vl_scope_from
+     *      sl2vl_scope_to
+     *      sl2vl_scope_sl2vl_table
+     */
+
+sl2vl_scope_group:      sl2vl_scope_group_start string_list {
+                            /* 'group' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->group_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+sl2vl_scope_group_start: TK_GROUP {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_across:     sl2vl_scope_across_start string_list {
+                            /* 'across' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str) {
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,strdup(tmp_str));
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+sl2vl_scope_across_start: TK_ACROSS {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_across_from:  sl2vl_scope_across_from_start string_list {
+                            /* 'across-from' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+sl2vl_scope_across_from_start: TK_ACROSS_FROM {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_across_to:  sl2vl_scope_across_to_start string_list {
+                            /* 'across-to' in 'sl2vl-scope' - any num of instances */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str) {
+                                    cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,tmp_str);
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+sl2vl_scope_across_to_start: TK_ACROSS_TO {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_from:       sl2vl_scope_from_start sl2vl_scope_from_list_or_asterisk {
+                            /* 'from' in 'sl2vl-scope' - any num of instances */
+                        }
+                        ;
+
+sl2vl_scope_from_start: TK_FROM {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_to:         sl2vl_scope_to_start sl2vl_scope_to_list_or_asterisk {
+                            /* 'to' in 'sl2vl-scope' - any num of instances */
+                        }
+                        ;
+
+sl2vl_scope_to_start:   TK_TO {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+sl2vl_scope_from_list_or_asterisk:  sl2vl_scope_from_asterisk
+                                  | sl2vl_scope_from_list_of_ranges
+                                  ;
+
+sl2vl_scope_from_asterisk: TK_ASTERISK {
+                            int i;
+                            for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
+                                p_current_sl2vl_scope->from[i] = TRUE;
+                        }
+                        ;
+
+sl2vl_scope_to_list_or_asterisk:  sl2vl_scope_to_asterisk
+                                | sl2vl_scope_to_list_of_ranges
+                                  ;
+
+sl2vl_scope_to_asterisk: TK_ASTERISK {
+                            int i;
+                            for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
+                                p_current_sl2vl_scope->to[i] = TRUE;
+                        }
+                        ;
+
+sl2vl_scope_from_list_of_ranges: list_of_ranges {
+                            int i;
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+                            uint8_t               num1, num2;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                {
+                                    if ( num_pair[0] < 0 ||
+                                         num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
+                                    {
+                                        yyerror("port number out of range 'from' list");
+                                        free(num_pair);
+                                        cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                                        return 1;
+                                    }
+                                    num1 = (uint8_t)num_pair[0];
+                                    num2 = (uint8_t)num_pair[1];
+                                    free(num_pair);
+                                    for (i = num1; i <= num2; i++)
+                                        p_current_sl2vl_scope->from[i] = TRUE;
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+                        ;
+
+sl2vl_scope_to_list_of_ranges: list_of_ranges {
+                            int i;
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t            * num_pair;
+                            uint8_t               num1, num2;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
+                            {
+                                num_pair = (uint64_t*)cl_list_obj(list_iterator);
+                                if (num_pair)
+                                {
+                                    if ( num_pair[0] < 0 ||
+                                         num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
+                                    {
+                                        yyerror("port number out of range 'to' list");
+                                        free(num_pair);
+                                        cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                                        return 1;
+                                    }
+                                    num1 = (uint8_t)num_pair[0];
+                                    num2 = (uint8_t)num_pair[1];
+                                    free(num_pair);
+                                    for (i = num1; i <= num2; i++)
+                                        p_current_sl2vl_scope->to[i] = TRUE;
+                                }
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+                        }
+                        ;
+
+
+sl2vl_scope_sl2vl_table:  sl2vl_scope_sl2vl_table_start num_list {
+                            /* 'sl2vl-table' - one instance of exactly
+                               OSM_QOS_POLICY_SL2VL_TABLE_LEN numbers */
+                            cl_list_iterator_t    list_iterator;
+                            uint64_t              num;
+                            uint64_t            * p_num;
+                            int                   i = 0;
+
+                            if (p_current_sl2vl_scope->sl2vl_table_set)
+                            {
+                                yyerror("sl2vl-scope has more than one sl2vl-table");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            if (cl_list_count(&tmp_parser_struct.num_list) != OSM_QOS_POLICY_SL2VL_TABLE_LEN)
+                            {
+                                yyerror("wrong number of values in 'sl2vl-table' (should be 16)");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.num_list) )
+                            {
+                                p_num = (uint64_t*)cl_list_obj(list_iterator);
+                                num = *p_num;
+                                free(p_num);
+                                if (num >= OSM_QOS_POLICY_MAX_VL_NUM)
+                                {
+                                    yyerror("wrong VL value in 'sl2vl-table' (should be 0 to 15)");
+                                    cl_list_remove_all(&tmp_parser_struct.num_list);
+                                    return 1;
+                                }
+
+                                p_current_sl2vl_scope->sl2vl_table[i++] = (uint8_t)num;
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            p_current_sl2vl_scope->sl2vl_table_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+sl2vl_scope_sl2vl_table_start: TK_SL2VL_TABLE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+    /*
+     *  qos_level_entry values:
+     *      qos_level_name
+     *      qos_level_use
+     *      qos_level_sl
+     *      qos_level_mtu_limit
+     *      qos_level_rate_limit
+     *      qos_level_packet_life
+     *      qos_level_path_bits
+     *      qos_level_pkey
+     */
+
+qos_level_name:         qos_level_name_start single_string {
+                            /* 'name' of 'qos-level' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_level->name)
+                            {
+                                yyerror("qos-level has multiple 'name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_level->name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_level_name_start:   TK_NAME {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_use:          qos_level_use_start single_string {
+                            /* 'use' of 'qos-level' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_level->use)
+                            {
+                                yyerror("qos-level has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_level->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_level_use_start:    TK_USE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_sl:           qos_level_sl_start single_number {
+                            /* 'sl' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->sl_set)
+                            {
+                                yyerror("'qos-level' has multiple 'sl' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->sl = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->sl_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+qos_level_sl_start:     TK_SL {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_mtu_limit:    qos_level_mtu_limit_start single_number {
+                            /* 'mtu-limit' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->mtu_limit_set)
+                            {
+                                yyerror("'qos-level' has multiple 'mtu-limit' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->mtu_limit = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->mtu_limit_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+qos_level_mtu_limit_start: TK_MTU_LIMIT {
+                            /* 'mtu-limit' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_rate_limit:    qos_level_rate_limit_start single_number {
+                            /* 'rate-limit' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->rate_limit_set)
+                            {
+                                yyerror("'qos-level' has multiple 'rate-limit' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->rate_limit = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->rate_limit_set = TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+qos_level_rate_limit_start: TK_RATE_LIMIT {
+                            /* 'rate-limit' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_packet_life:  qos_level_packet_life_start single_number {
+                            /* 'packet-life' in 'qos-level' - one instance */
+                            cl_list_iterator_t   list_iterator;
+                            uint64_t           * p_num;
+
+                            if (p_current_qos_level->pkt_life_set)
+                            {
+                                yyerror("'qos-level' has multiple 'packet-life' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+                            list_iterator = cl_list_head(&tmp_parser_struct.num_list);
+                            p_num = (uint64_t*)cl_list_obj(list_iterator);
+                            p_current_qos_level->pkt_life = (uint8_t)(*p_num);
+                            free(p_num);
+                            p_current_qos_level->pkt_life_set= TRUE;
+                            cl_list_remove_all(&tmp_parser_struct.num_list);
+                        }
+                        ;
+
+qos_level_packet_life_start: TK_PACKET_LIFE {
+                            /* 'packet-life' in 'qos-level' - one instance */
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_path_bits:    qos_level_path_bits_start list_of_ranges {
+                            /* 'path-bits' in 'qos-level' - any num of instances */
+                            /* list of path bit ranges */
+
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_level->path_bits_range_len )
+                                {
+                                    p_current_qos_level->path_bits_range_arr = range_arr;
+                                    p_current_qos_level->path_bits_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_level->path_bits_range_arr,
+                                                      p_current_qos_level->path_bits_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_level->path_bits_range_arr = new_range_arr;
+                                    p_current_qos_level->path_bits_range_len = new_range_len;
+                                }
+                            }
+                        }
+                        ;
+
+qos_level_path_bits_start: TK_PATH_BITS {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_level_pkey:         qos_level_pkey_start list_of_ranges {
+                            /* 'pkey' in 'qos-level' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_level->pkey_range_len )
+                                {
+                                    p_current_qos_level->pkey_range_arr = range_arr;
+                                    p_current_qos_level->pkey_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_level->pkey_range_arr,
+                                                      p_current_qos_level->pkey_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_level->pkey_range_arr = new_range_arr;
+                                    p_current_qos_level->pkey_range_len = new_range_len;
+                                }
+                            }
+                        }
+                        ;
+
+qos_level_pkey_start:   TK_PKEY {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+    /*
+     *  qos_match_rule_entry values:
+     *      qos_match_rule_use
+     *      qos_match_rule_qos_class
+     *      qos_match_rule_qos_level_name
+     *      qos_match_rule_source
+     *      qos_match_rule_destination
+     *      qos_match_rule_service_id
+     *      qos_match_rule_pkey
+     */
+
+
+qos_match_rule_use:     qos_match_rule_use_start single_string {
+                            /* 'use' of 'qos-match-rule' - one instance */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            if (p_current_qos_match_rule->use)
+                            {
+                                yyerror("'qos-match-rule' has multiple 'use' tags");
+                                cl_list_remove_all(&tmp_parser_struct.str_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_match_rule->use = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_match_rule_use_start: TK_USE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_qos_class: qos_match_rule_qos_class_start list_of_ranges {
+                            /* 'qos-class' in 'qos-match-rule' - num of instances of list of ranges */
+                            /* list of class ranges (QoS Class is 12-bit value) */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->qos_class_range_len )
+                                {
+                                    p_current_qos_match_rule->qos_class_range_arr = range_arr;
+                                    p_current_qos_match_rule->qos_class_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->qos_class_range_arr,
+                                                      p_current_qos_match_rule->qos_class_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->qos_class_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->qos_class_range_len = new_range_len;
+                                }
+                            }
+                        }
+                        ;
+
+qos_match_rule_qos_class_start: TK_QOS_CLASS {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_source:  qos_match_rule_source_start string_list {
+                            /* 'source' in 'qos-match-rule' - text */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_qos_match_rule->source_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_match_rule_source_start: TK_SOURCE {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_destination: qos_match_rule_destination_start string_list {
+                            /* 'destination' in 'qos-match-rule' - text */
+                            cl_list_iterator_t    list_iterator;
+                            char                * tmp_str;
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    cl_list_insert_tail(&p_current_qos_match_rule->destination_list,tmp_str);
+                                list_iterator = cl_list_next(list_iterator);
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_match_rule_destination_start: TK_DESTINATION {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_qos_level_name:  qos_match_rule_qos_level_name_start single_string {
+                            /* 'qos-level-name' in 'qos-match-rule' - single string */
+                            cl_list_iterator_t   list_iterator;
+                            char               * tmp_str;
+
+                            if (p_current_qos_match_rule->qos_level_name)
+                            {
+                                yyerror("qos-match-rule has multiple 'qos-level-name' tags");
+                                cl_list_remove_all(&tmp_parser_struct.num_list);
+                                return 1;
+                            }
+
+                            list_iterator = cl_list_head(&tmp_parser_struct.str_list);
+                            if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
+                            {
+                                tmp_str = (char*)cl_list_obj(list_iterator);
+                                if (tmp_str)
+                                    p_current_qos_match_rule->qos_level_name = tmp_str;
+                            }
+                            cl_list_remove_all(&tmp_parser_struct.str_list);
+                        }
+                        ;
+
+qos_match_rule_qos_level_name_start: TK_QOS_LEVEL_NAME {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_service_id: qos_match_rule_service_id_start list_of_ranges {
+                            /* 'service-id' in 'qos-match-rule' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->service_id_range_len )
+                                {
+                                    p_current_qos_match_rule->service_id_range_arr = range_arr;
+                                    p_current_qos_match_rule->service_id_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->service_id_range_arr,
+                                                      p_current_qos_match_rule->service_id_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->service_id_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->service_id_range_len = new_range_len;
+                                }
+                            }
+                        }
+                        ;
+
+qos_match_rule_service_id_start: TK_SERVICE_ID {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+qos_match_rule_pkey:    qos_match_rule_pkey_start list_of_ranges {
+                            /* 'pkey' in 'qos-match-rule' - num of instances of list of ranges */
+                            if (cl_list_count(&tmp_parser_struct.num_pair_list))
+                            {
+                                uint64_t ** range_arr;
+                                unsigned range_len;
+
+                                __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
+                                                      &range_arr,
+                                                      &range_len );
+
+                                if ( !p_current_qos_match_rule->pkey_range_len )
+                                {
+                                    p_current_qos_match_rule->pkey_range_arr = range_arr;
+                                    p_current_qos_match_rule->pkey_range_len = range_len;
+                                }
+                                else
+                                {
+                                    uint64_t ** new_range_arr;
+                                    unsigned new_range_len;
+                                    __merge_rangearr( p_current_qos_match_rule->pkey_range_arr,
+                                                      p_current_qos_match_rule->pkey_range_len,
+                                                      range_arr,
+                                                      range_len,
+                                                      &new_range_arr,
+                                                      &new_range_len );
+                                    p_current_qos_match_rule->pkey_range_arr = new_range_arr;
+                                    p_current_qos_match_rule->pkey_range_len = new_range_len;
+                                }
+                            }
+                        }
+                        ;
+
+qos_match_rule_pkey_start: TK_PKEY {
+                            RESET_BUFFER;
+                        }
+                        ;
+
+
+    /*
+     * Common part
+     */
+
+
+single_string:      single_string_elems {
+                        cl_list_insert_tail(&tmp_parser_struct.str_list,
+                                            strdup(__parser_strip_white(tmp_parser_struct.str)));
+                        tmp_parser_struct.str[0] = '\0';
+                    }
+                    ;
+
+single_string_elems:  single_string_element
+                    | single_string_elems single_string_element
+                    ;
+
+single_string_element: TK_TEXT {
+                        strcat(tmp_parser_struct.str,$1);
+                        free($1);
+                    }
+                    ;
+
+
+string_list:        single_string
+                    | string_list TK_COMMA single_string
+                    ;
+
+
+
+single_number:      number
+                    ;
+
+num_list:             number
+                    | num_list TK_COMMA number
+                    ;
+
+number:             TK_NUMBER {
+                        uint64_t * p_num = (uint64_t*)malloc(sizeof(uint64_t));
+                        __parser_str2uint64(p_num,$1);
+                        free($1);
+                        cl_list_insert_tail(&tmp_parser_struct.num_list, p_num);
+                    }
+                    ;
+
+num_list_with_dotdot: number_from_pair_1 TK_DOTDOT number_from_pair_2 {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    | num_list_with_dotdot TK_COMMA number_from_pair_1 TK_DOTDOT number_from_pair_2 {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    ;
+
+number_from_pair_1:   TK_NUMBER {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
+                        free($1);
+                    }
+                    ;
+
+number_from_pair_2:   TK_NUMBER {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
+                        free($1);
+                    }
+                    ;
+
+list_of_ranges:     num_list_with_dash
+                    ;
+
+num_list_with_dash:   single_number_from_range {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    | number_from_range_1 TK_DASH number_from_range_2 {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
+                            num_pair[0] = tmp_parser_struct.num_pair[0];
+                            num_pair[1] = tmp_parser_struct.num_pair[1];
+                        }
+                        else {
+                            num_pair[1] = tmp_parser_struct.num_pair[0];
+                            num_pair[0] = tmp_parser_struct.num_pair[1];
+                        }
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    | num_list_with_dash TK_COMMA number_from_range_1 TK_DASH number_from_range_2 {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
+                            num_pair[0] = tmp_parser_struct.num_pair[0];
+                            num_pair[1] = tmp_parser_struct.num_pair[1];
+                        }
+                        else {
+                            num_pair[1] = tmp_parser_struct.num_pair[0];
+                            num_pair[0] = tmp_parser_struct.num_pair[1];
+                        }
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    | num_list_with_dash TK_COMMA single_number_from_range {
+                        uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
+                        num_pair[0] = tmp_parser_struct.num_pair[0];
+                        num_pair[1] = tmp_parser_struct.num_pair[1];
+                        cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
+                    }
+                    ;
+
+single_number_from_range:  TK_NUMBER {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
+                        free($1);
+                    }
+                    ;
+
+number_from_range_1:  TK_NUMBER {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
+                        free($1);
+                    }
+                    ;
+
+number_from_range_2:  TK_NUMBER {
+                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
+                        free($1);
+                    }
+                    ;
+
+%%
+
+/***************************************************
+ ***************************************************/
+
+int osm_qos_parse_policy_file(IN osm_subn_t * const p_subn)
+{
+    int res = 0;
+    static boolean_t first_time = TRUE;
+    p_qos_parser_osm_log = &p_subn->p_osm->log;
+
+    OSM_LOG_ENTER(p_qos_parser_osm_log);
+
+    osm_qos_policy_destroy(p_subn->p_qos_policy);
+    p_subn->p_qos_policy = NULL;
+
+    yyin = fopen (p_subn->opt.qos_policy_file, "r");
+    if (!yyin)
+    {
+        if (strcmp(p_subn->opt.qos_policy_file,OSM_DEFAULT_QOS_POLICY_FILE)) {
+            OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC01: "
+                    "Failed opening QoS policy file %s - %s\n",
+                    p_subn->opt.qos_policy_file, strerror(errno));
+            res = 1;
+        }
+        else
+            OSM_LOG(p_qos_parser_osm_log, OSM_LOG_VERBOSE,
+                    "QoS policy file not found (%s)\n",
+                    p_subn->opt.qos_policy_file);
+
+        goto Exit;
+    }
+
+    if (first_time)
+    {
+        first_time = FALSE;
+        __setup_simple_qos_levels();
+        __setup_ulp_match_rules();
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_INFO,
+		"Loading QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+    }
+    else
+        /*
+         * ULP match rules list was emptied at the end of
+         * previous parsing iteration.
+         * What's left is to clear simple QoS levels.
+         */
+        __clear_simple_qos_levels();
+
+    column_num = 1;
+    line_num = 1;
+
+    p_subn->p_qos_policy = osm_qos_policy_create(p_subn);
+
+    __parser_tmp_struct_init();
+    p_qos_policy = p_subn->p_qos_policy;
+
+    res = yyparse();
+
+    __parser_tmp_struct_destroy();
+
+    if (res != 0)
+    {
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC03: "
+                "Failed parsing QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        osm_qos_policy_destroy(p_subn->p_qos_policy);
+        p_subn->p_qos_policy = NULL;
+        res = 1;
+        goto Exit;
+    }
+
+    /* add generated ULP match rules to the usual match rules */
+    __process_ulp_match_rules();
+
+    if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log))
+    {
+        OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC04: "
+                "Error(s) in QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        fprintf(stderr, "Error(s) in QoS policy file (%s)\n",
+                p_subn->opt.qos_policy_file);
+        osm_qos_policy_destroy(p_subn->p_qos_policy);
+        p_subn->p_qos_policy = NULL;
+        res = 1;
+        goto Exit;
+    }
+
+  Exit:
+    if (yyin)
+        fclose(yyin);
+    OSM_LOG_EXIT(p_qos_parser_osm_log);
+    return res;
+}
+
+/***************************************************
+ ***************************************************/
+
+int yywrap()
+{
+    return(1);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void yyerror(const char *format, ...)
+{
+    char s[256];
+    va_list pvar;
+
+    OSM_LOG_ENTER(p_qos_parser_osm_log);
+
+    va_start(pvar, format);
+    vsnprintf(s, sizeof(s), format, pvar);
+    va_end(pvar);
+
+    OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC05: "
+            "Syntax error (line %d:%d): %s\n",
+            line_num, column_num, s);
+    fprintf(stderr, "Error in QoS Policy File (line %d:%d): %s.\n",
+            line_num, column_num, s);
+    OSM_LOG_EXIT(p_qos_parser_osm_log);
+}
+
+/***************************************************
+ ***************************************************/
+
+static char * __parser_strip_white(char * str)
+{
+   int i;
+   for (i = (strlen(str)-1); i >= 0; i--)
+   {
+      if (isspace(str[i]))
+          str[i] = '\0';
+      else
+         break;
+   }
+   for (i = 0; i < strlen(str); i++)
+   {
+      if (!isspace(str[i]))
+         break;
+   }
+   return &(str[i]);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_str2uint64(uint64_t * p_val, char * str)
+{
+   *p_val = strtoull(str, NULL, 0);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_port_group_start()
+{
+    p_current_port_group = osm_qos_policy_port_group_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_port_group_end()
+{
+    if(!p_current_port_group->name)
+    {
+        yyerror("port-group validation failed - no port group name specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->port_groups,
+                        p_current_port_group);
+    p_current_port_group = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_vlarb_scope_start()
+{
+    p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_vlarb_scope_end()
+{
+    if ( !cl_list_count(&p_current_vlarb_scope->group_list) &&
+         !cl_list_count(&p_current_vlarb_scope->across_list) )
+    {
+        yyerror("vlarb-scope validation failed - no port groups specified by 'group' or by 'across'");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->vlarb_tables,
+                        p_current_vlarb_scope);
+    p_current_vlarb_scope = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_sl2vl_scope_start()
+{
+    p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_sl2vl_scope_end()
+{
+    if (!p_current_sl2vl_scope->sl2vl_table_set)
+    {
+        yyerror("sl2vl-scope validation failed - no sl2vl table specified");
+        return -1;
+    }
+    if ( !cl_list_count(&p_current_sl2vl_scope->group_list) &&
+         !cl_list_count(&p_current_sl2vl_scope->across_to_list) &&
+         !cl_list_count(&p_current_sl2vl_scope->across_from_list) )
+    {
+        yyerror("sl2vl-scope validation failed - no port groups specified by 'group', 'across-to' or 'across-from'");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->sl2vl_tables,
+                        p_current_sl2vl_scope);
+    p_current_sl2vl_scope = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_qos_level_start()
+{
+    p_current_qos_level = osm_qos_policy_qos_level_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_qos_level_end()
+{
+    if (!p_current_qos_level->sl_set)
+    {
+        yyerror("qos-level validation failed - no 'sl' specified");
+        return -1;
+    }
+    if (!p_current_qos_level->name)
+    {
+        yyerror("qos-level validation failed - no 'name' specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->qos_levels,
+                        p_current_qos_level);
+    p_current_qos_level = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_match_rule_start()
+{
+    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_match_rule_end()
+{
+    if (!p_current_qos_match_rule->qos_level_name)
+    {
+        yyerror("match-rule validation failed - no 'qos-level-name' specified");
+        return -1;
+    }
+
+    cl_list_insert_tail(&p_qos_policy->qos_match_rules,
+                        p_current_qos_match_rule);
+    p_current_qos_match_rule = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_ulp_match_rule_start()
+{
+    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __parser_ulp_match_rule_end()
+{
+    CL_ASSERT(p_current_qos_match_rule->p_qos_level);
+    cl_list_insert_tail(&__ulp_match_rules,
+                        p_current_qos_match_rule);
+    p_current_qos_match_rule = NULL;
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_tmp_struct_init()
+{
+    tmp_parser_struct.str[0] = '\0';
+    cl_list_construct(&tmp_parser_struct.str_list);
+    cl_list_init(&tmp_parser_struct.str_list, 10);
+    cl_list_construct(&tmp_parser_struct.num_list);
+    cl_list_init(&tmp_parser_struct.num_list, 10);
+    cl_list_construct(&tmp_parser_struct.num_pair_list);
+    cl_list_init(&tmp_parser_struct.num_pair_list, 10);
+}
+
+/***************************************************
+ ***************************************************/
+
+/*
+ * Do NOT free objects from the temp struct.
+ * Either they are inserted into the parse tree data
+ * structure, or they are already freed when copying
+ * their values to the parse tree data structure.
+ */
+static void __parser_tmp_struct_reset()
+{
+    tmp_parser_struct.str[0] = '\0';
+    cl_list_remove_all(&tmp_parser_struct.str_list);
+    cl_list_remove_all(&tmp_parser_struct.num_list);
+    cl_list_remove_all(&tmp_parser_struct.num_pair_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_tmp_struct_destroy()
+{
+    __parser_tmp_struct_reset();
+    cl_list_destroy(&tmp_parser_struct.str_list);
+    cl_list_destroy(&tmp_parser_struct.num_list);
+    cl_list_destroy(&tmp_parser_struct.num_pair_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+#define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL"
+#define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT"
+
+static void __setup_simple_qos_levels()
+{
+    uint8_t i;
+    char tmp_buf[30];
+    memset(osm_qos_policy_simple_qos_levels, 0,
+           sizeof(osm_qos_policy_simple_qos_levels));
+    for (i = 0; i < 16; i++)
+    {
+        osm_qos_policy_simple_qos_levels[i].sl = i;
+        osm_qos_policy_simple_qos_levels[i].sl_set = TRUE;
+        sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i);
+        osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf);
+    }
+
+    memset(&__default_simple_qos_level, 0,
+           sizeof(__default_simple_qos_level));
+    __default_simple_qos_level.name =
+           strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __clear_simple_qos_levels()
+{
+    /*
+     * Simple QoS levels are static.
+     * What's left is to invalidate default simple QoS level.
+     */
+    __default_simple_qos_level.sl_set = FALSE;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __setup_ulp_match_rules()
+{
+    cl_list_construct(&__ulp_match_rules);
+    cl_list_init(&__ulp_match_rules, 10);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __process_ulp_match_rules()
+{
+    cl_list_iterator_t list_iterator;
+    osm_qos_match_rule_t *p_qos_match_rule = NULL;
+
+    list_iterator = cl_list_head(&__ulp_match_rules);
+    while (list_iterator != cl_list_end(&__ulp_match_rules))
+    {
+        p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
+        if (p_qos_match_rule)
+            cl_list_insert_tail(&p_qos_policy->qos_match_rules,
+                                p_qos_match_rule);
+        list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(&__ulp_match_rules);
+}
+
+/***************************************************
+ ***************************************************/
+
+static int OSM_CDECL
+__cmp_num_range(
+    const void * p1,
+    const void * p2)
+{
+    uint64_t * pair1 = *((uint64_t **)p1);
+    uint64_t * pair2 = *((uint64_t **)p2);
+
+    if (pair1[0] < pair2[0])
+        return -1;
+    if (pair1[0] > pair2[0])
+        return 1;
+
+    if (pair1[1] < pair2[1])
+        return -1;
+    if (pair1[1] > pair2[1])
+        return 1;
+
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __sort_reduce_rangearr(
+    uint64_t  **   arr,
+    unsigned       arr_len,
+    uint64_t  ** * p_res_arr,
+    unsigned     * p_res_arr_len )
+{
+    unsigned i = 0;
+    unsigned j = 0;
+    unsigned last_valid_ind = 0;
+    unsigned valid_cnt = 0;
+    uint64_t ** res_arr;
+    boolean_t * is_valid_arr;
+
+    *p_res_arr = NULL;
+    *p_res_arr_len = 0;
+
+    qsort(arr, arr_len, sizeof(uint64_t*), __cmp_num_range);
+
+    is_valid_arr = (boolean_t *)malloc(arr_len * sizeof(boolean_t));
+    is_valid_arr[last_valid_ind] = TRUE;
+    valid_cnt++;
+    for (i = 1; i < arr_len; i++)
+    {
+        if (arr[i][0] <= arr[last_valid_ind][1])
+        {
+            if (arr[i][1] > arr[last_valid_ind][1])
+                arr[last_valid_ind][1] = arr[i][1];
+            free(arr[i]);
+            arr[i] = NULL;
+            is_valid_arr[i] = FALSE;
+        }
+        else if ((arr[i][0] - 1) == arr[last_valid_ind][1])
+        {
+            arr[last_valid_ind][1] = arr[i][1];
+            free(arr[i]);
+            arr[i] = NULL;
+            is_valid_arr[i] = FALSE;
+        }
+        else
+        {
+            is_valid_arr[i] = TRUE;
+            last_valid_ind = i;
+            valid_cnt++;
+        }
+    }
+
+    res_arr = (uint64_t **)malloc(valid_cnt * sizeof(uint64_t *));
+    for (i = 0; i < arr_len; i++)
+    {
+        if (is_valid_arr[i])
+            res_arr[j++] = arr[i];
+    }
+    free(is_valid_arr);
+    free(arr);
+
+    *p_res_arr = res_arr;
+    *p_res_arr_len = valid_cnt;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __pkey_rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len)
+{
+    uint64_t   tmp_pkey;
+    uint64_t * p_pkeys;
+    cl_list_iterator_t list_iterator;
+
+    list_iterator= cl_list_head(p_list);
+    while( list_iterator != cl_list_end(p_list) )
+    {
+       p_pkeys = (uint64_t *)cl_list_obj(list_iterator);
+       p_pkeys[0] &= 0x7fff;
+       p_pkeys[1] &= 0x7fff;
+       if (p_pkeys[0] > p_pkeys[1])
+       {
+           tmp_pkey = p_pkeys[1];
+           p_pkeys[1] = p_pkeys[0];
+           p_pkeys[0] = tmp_pkey;
+       }
+       list_iterator = cl_list_next(list_iterator);
+    }
+
+    __rangelist2rangearr(p_list, p_arr, p_arr_len);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __rangelist2rangearr(
+    cl_list_t    * p_list,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len)
+{
+    cl_list_iterator_t list_iterator;
+    unsigned len = cl_list_count(p_list);
+    unsigned i = 0;
+    uint64_t ** tmp_arr;
+    uint64_t ** res_arr = NULL;
+    unsigned res_arr_len = 0;
+
+    tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
+
+    list_iterator = cl_list_head(p_list);
+    while( list_iterator != cl_list_end(p_list) )
+    {
+       tmp_arr[i++] = (uint64_t *)cl_list_obj(list_iterator);
+       list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(p_list);
+
+    __sort_reduce_rangearr( tmp_arr,
+                            len,
+                            &res_arr,
+                            &res_arr_len );
+    *p_arr = res_arr;
+    *p_arr_len = res_arr_len;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __merge_rangearr(
+    uint64_t  **   range_arr_1,
+    unsigned       range_len_1,
+    uint64_t  **   range_arr_2,
+    unsigned       range_len_2,
+    uint64_t  ** * p_arr,
+    unsigned     * p_arr_len )
+{
+    unsigned i = 0;
+    unsigned j = 0;
+    unsigned len = range_len_1 + range_len_2;
+    uint64_t ** tmp_arr;
+    uint64_t ** res_arr = NULL;
+    unsigned res_arr_len = 0;
+
+    *p_arr = NULL;
+    *p_arr_len = 0;
+
+    tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
+
+    for (i = 0; i < range_len_1; i++)
+       tmp_arr[j++] = range_arr_1[i];
+    for (i = 0; i < range_len_2; i++)
+       tmp_arr[j++] = range_arr_2[i];
+    free(range_arr_1);
+    free(range_arr_2);
+
+    __sort_reduce_rangearr( tmp_arr,
+                            len,
+                            &res_arr,
+                            &res_arr_len );
+    *p_arr = res_arr;
+    *p_arr_len = res_arr_len;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_port_to_port_map(
+    cl_qmap_t   * p_map,
+    osm_physp_t * p_physp)
+{
+    if (cl_qmap_get(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp))) ==
+        cl_qmap_end(p_map))
+    {
+        osm_qos_port_t * p_port = osm_qos_policy_port_create(p_physp);
+        if (p_port)
+            cl_qmap_insert(p_map,
+                           cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+                           &p_port->map_item);
+    }
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_guid_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len)
+{
+    unsigned i;
+    uint64_t guid_ho;
+    osm_port_t * p_osm_port;
+
+    if (!range_arr || !range_len)
+        return;
+
+    for (i = 0; i < range_len; i++) {
+         for (guid_ho = range_arr[i][0]; guid_ho <= range_arr[i][1]; guid_ho++) {
+             p_osm_port =
+                osm_get_port_by_guid(p_qos_policy->p_subn, cl_hton64(guid_ho));
+             if (p_osm_port)
+                 __parser_add_port_to_port_map(p_map, p_osm_port->p_physp);
+         }
+         free(range_arr[i]);
+    }
+    free(range_arr);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_pkey_range_to_port_map(
+    cl_qmap_t  * p_map,
+    uint64_t  ** range_arr,
+    unsigned     range_len)
+{
+    unsigned i;
+    uint64_t pkey_64;
+    ib_net16_t pkey;
+    osm_prtn_t * p_prtn;
+
+    if (!range_arr || !range_len)
+        return;
+
+    for (i = 0; i < range_len; i++) {
+         for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
+             pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
+             p_prtn = (osm_prtn_t *)
+                 cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
+             if (p_prtn != (osm_prtn_t *)cl_qmap_end(
+                   &p_qos_policy->p_subn->prtn_pkey_tbl)) {
+                 __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
+                 __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
+             }
+         }
+         free(range_arr[i]);
+    }
+    free(range_arr);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_partition_list_to_port_map(
+    cl_qmap_t  * p_map,
+    cl_list_t  * p_list)
+{
+    cl_list_iterator_t    list_iterator;
+    char                * tmp_str;
+    osm_prtn_t          * p_prtn;
+
+    /* extract all the ports from the partition
+       to the port map of this port group */
+    list_iterator = cl_list_head(p_list);
+    while(list_iterator != cl_list_end(p_list)) {
+        tmp_str = (char*)cl_list_obj(list_iterator);
+        if (tmp_str) {
+            p_prtn = osm_prtn_find_by_name(p_qos_policy->p_subn, tmp_str);
+            if (p_prtn) {
+                __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
+                __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
+            }
+            free(tmp_str);
+        }
+        list_iterator = cl_list_next(list_iterator);
+    }
+    cl_list_remove_all(p_list);
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __parser_add_map_to_port_map(
+    cl_qmap_t * p_dmap,
+    cl_map_t  * p_smap)
+{
+    cl_map_iterator_t map_iterator;
+    osm_physp_t * p_physp;
+
+    if (!p_dmap || !p_smap)
+        return;
+
+    map_iterator = cl_map_head(p_smap);
+    while (map_iterator != cl_map_end(p_smap)) {
+        p_physp = (osm_physp_t*)cl_map_obj(map_iterator);
+        __parser_add_port_to_port_map(p_dmap, p_physp);
+        map_iterator = cl_map_next(map_iterator);
+    }
+}
+
+/***************************************************
+ ***************************************************/
+
+static int __validate_pkeys( uint64_t ** range_arr,
+                             unsigned    range_len,
+                             boolean_t   is_ipoib)
+{
+    unsigned i;
+    uint64_t pkey_64;
+    ib_net16_t pkey;
+    osm_prtn_t * p_prtn;
+
+    if (!range_arr || !range_len)
+        return 0;
+
+    for (i = 0; i < range_len; i++) {
+        for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
+            pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
+            p_prtn = (osm_prtn_t *)
+                cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
+
+            if (p_prtn == (osm_prtn_t *)cl_qmap_end(
+                  &p_qos_policy->p_subn->prtn_pkey_tbl))
+                p_prtn = NULL;
+
+            if (is_ipoib) {
+                /*
+                 * Be very strict for IPoIB partition:
+                 *  - the partition for the pkey have to exist
+                 *  - it has to have at least 2 full members
+                 */
+                if (!p_prtn) {
+                    yyerror("IPoIB partition, pkey 0x%04X - "
+                                       "partition doesn't exist",
+                                       cl_ntoh16(pkey));
+                    return 1;
+                }
+                else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) {
+                    yyerror("IPoIB partition, pkey 0x%04X - "
+                                       "partition has less than two full members",
+                                       cl_ntoh16(pkey));
+                    return 1;
+                }
+            }
+            else if (!p_prtn) {
+                /*
+                 * For non-IPoIB pkey we just want to check that
+                 * the relevant partition exists.
+                 * And even if it doesn't, don't exit - just print
+                 * error message and continue.
+                 */
+                 OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC02: "
+			 "pkey 0x%04X - partition doesn't exist",
+                         cl_ntoh16(pkey));
+            }
+        }
+    }
+    return 0;
+}
+
+/***************************************************
+ ***************************************************/
diff --git a/opensm/osm_qos_policy.c b/opensm/osm_qos_policy.c
new file mode 100644
index 0000000..094fef2
--- /dev/null
+++ b/opensm/osm_qos_policy.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    OSM QoS Policy functions.
+ *
+ * Author:
+ *    Yevgeny Kliteynik, Mellanox
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_qos_policy.h>
+
+extern osm_qos_level_t __default_simple_qos_level;
+
+/***************************************************
+ ***************************************************/
+
+static void
+__build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)
+{
+	osm_node_t * p_node;
+	cl_qmap_t  * p_node_guid_tbl = &p_qos_policy->p_subn->node_guid_tbl;
+
+	p_qos_policy->p_node_hash = st_init_strtable();
+	CL_ASSERT(p_qos_policy->p_node_hash);
+
+	if (!p_node_guid_tbl || !cl_qmap_count(p_node_guid_tbl))
+		return;
+
+	for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl);
+	     p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl);
+	     p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) {
+		if (!st_lookup(p_qos_policy->p_node_hash,
+			      (st_data_t)p_node->print_desc, NULL))
+			st_insert(p_qos_policy->p_node_hash,
+				  (st_data_t)p_node->print_desc,
+				  (st_data_t)p_node);
+	}
+}
+
+/***************************************************
+ ***************************************************/
+
+static boolean_t
+__is_num_in_range_arr(uint64_t ** range_arr,
+		  unsigned range_arr_len, uint64_t num)
+{
+	unsigned ind_1 = 0;
+	unsigned ind_2 = range_arr_len - 1;
+	unsigned ind_mid;
+
+	if (!range_arr || !range_arr_len)
+		return FALSE;
+
+	while (ind_1 <= ind_2) {
+	    if (num < range_arr[ind_1][0] || num > range_arr[ind_2][1])
+		return FALSE;
+	    else if (num <= range_arr[ind_1][1] || num >= range_arr[ind_2][0])
+		return TRUE;
+
+	    ind_mid = ind_1 + (ind_2 - ind_1 + 1)/2;
+
+	    if (num < range_arr[ind_mid][0])
+		ind_2 = ind_mid;
+	    else if (num > range_arr[ind_mid][1])
+		ind_1 = ind_mid;
+	    else
+		return TRUE;
+
+	    ind_1++;
+	    ind_2--;
+	}
+
+	return FALSE;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __free_single_element(void *p_element, void *context)
+{
+	if (p_element)
+		free(p_element);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t *p_physp)
+{
+	osm_qos_port_t *p =
+	    (osm_qos_port_t *) malloc(sizeof(osm_qos_port_t));
+	if (!p)
+		return NULL;
+	memset(p, 0, sizeof(osm_qos_port_t));
+
+	p->p_physp = p_physp;
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_port_group_t *osm_qos_policy_port_group_create()
+{
+	osm_qos_port_group_t *p =
+	    (osm_qos_port_group_t *) malloc(sizeof(osm_qos_port_group_t));
+	if (!p)
+		return NULL;
+
+	memset(p, 0, sizeof(osm_qos_port_group_t));
+	cl_qmap_init(&p->port_map);
+
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p)
+{
+	osm_qos_port_t * p_port;
+	osm_qos_port_t * p_old_port;
+
+	if (!p)
+		return;
+
+	if (p->name)
+		free(p->name);
+	if (p->use)
+		free(p->use);
+
+	p_port = (osm_qos_port_t *) cl_qmap_head(&p->port_map);
+	while (p_port != (osm_qos_port_t *) cl_qmap_end(&p->port_map))
+	{
+		p_old_port = p_port;
+		p_port = (osm_qos_port_t *) cl_qmap_next(&p_port->map_item);
+		free(p_old_port);
+	}
+	cl_qmap_remove_all(&p->port_map);
+
+	free(p);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_vlarb_scope_t *osm_qos_policy_vlarb_scope_create()
+{
+	osm_qos_vlarb_scope_t *p =
+	    (osm_qos_vlarb_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t));
+	if (!p)
+		return NULL;
+
+	memset(p, 0, sizeof(osm_qos_vlarb_scope_t));
+
+	cl_list_init(&p->group_list, 10);
+	cl_list_init(&p->across_list, 10);
+	cl_list_init(&p->vlarb_high_list, 10);
+	cl_list_init(&p->vlarb_low_list, 10);
+
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p)
+{
+	if (!p)
+		return;
+
+	cl_list_apply_func(&p->group_list, __free_single_element, NULL);
+	cl_list_apply_func(&p->across_list, __free_single_element, NULL);
+	cl_list_apply_func(&p->vlarb_high_list, __free_single_element, NULL);
+	cl_list_apply_func(&p->vlarb_low_list, __free_single_element, NULL);
+
+	cl_list_remove_all(&p->group_list);
+	cl_list_remove_all(&p->across_list);
+	cl_list_remove_all(&p->vlarb_high_list);
+	cl_list_remove_all(&p->vlarb_low_list);
+
+	cl_list_destroy(&p->group_list);
+	cl_list_destroy(&p->across_list);
+	cl_list_destroy(&p->vlarb_high_list);
+	cl_list_destroy(&p->vlarb_low_list);
+
+	free(p);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_sl2vl_scope_t *osm_qos_policy_sl2vl_scope_create()
+{
+	osm_qos_sl2vl_scope_t *p =
+	    (osm_qos_sl2vl_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t));
+	if (!p)
+		return NULL;
+
+	memset(p, 0, sizeof(osm_qos_sl2vl_scope_t));
+
+	cl_list_init(&p->group_list, 10);
+	cl_list_init(&p->across_from_list, 10);
+	cl_list_init(&p->across_to_list, 10);
+
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p)
+{
+	if (!p)
+		return;
+
+	cl_list_apply_func(&p->group_list, __free_single_element, NULL);
+	cl_list_apply_func(&p->across_from_list, __free_single_element, NULL);
+	cl_list_apply_func(&p->across_to_list, __free_single_element, NULL);
+
+	cl_list_remove_all(&p->group_list);
+	cl_list_remove_all(&p->across_from_list);
+	cl_list_remove_all(&p->across_to_list);
+
+	cl_list_destroy(&p->group_list);
+	cl_list_destroy(&p->across_from_list);
+	cl_list_destroy(&p->across_to_list);
+
+	free(p);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_level_t *osm_qos_policy_qos_level_create()
+{
+	osm_qos_level_t *p =
+	    (osm_qos_level_t *) malloc(sizeof(osm_qos_level_t));
+	if (!p)
+		return NULL;
+	memset(p, 0, sizeof(osm_qos_level_t));
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_qos_level_destroy(osm_qos_level_t * p)
+{
+	unsigned i;
+
+	if (!p)
+		return;
+
+	if (p->name)
+		free(p->name);
+	if (p->use)
+		free(p->use);
+
+	for (i = 0; i < p->path_bits_range_len; i++)
+		free(p->path_bits_range_arr[i]);
+	if (p->path_bits_range_arr)
+		free(p->path_bits_range_arr);
+
+	free(p);
+}
+
+/***************************************************
+ ***************************************************/
+
+boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level,
+				 IN ib_net16_t pkey)
+{
+	if (!p_qos_level || !p_qos_level->pkey_range_len)
+		return FALSE;
+	return __is_num_in_range_arr(p_qos_level->pkey_range_arr,
+				     p_qos_level->pkey_range_len,
+				     cl_ntoh16(pkey));
+}
+
+/***************************************************
+ ***************************************************/
+
+ib_net16_t osm_qos_level_get_shared_pkey(IN const osm_qos_level_t * p_qos_level,
+					 IN const osm_physp_t * p_src_physp,
+					 IN const osm_physp_t * p_dest_physp)
+{
+	unsigned i;
+	uint16_t pkey_ho = 0;
+
+	if (!p_qos_level || !p_qos_level->pkey_range_len)
+		return 0;
+
+	/*
+	 * ToDo: This approach is not optimal.
+	 *       Think how to find shared pkey that also exists
+	 *       in QoS level in less runtime.
+	 */
+
+	for (i = 0; i < p_qos_level->pkey_range_len; i++) {
+		for (pkey_ho = p_qos_level->pkey_range_arr[i][0];
+		     pkey_ho <= p_qos_level->pkey_range_arr[i][1]; pkey_ho++) {
+			if (osm_physp_share_this_pkey
+			    (p_src_physp, p_dest_physp, cl_hton16(pkey_ho)))
+				return cl_hton16(pkey_ho);
+		}
+	}
+
+	return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_match_rule_t *osm_qos_policy_match_rule_create()
+{
+	osm_qos_match_rule_t *p =
+	    (osm_qos_match_rule_t *) malloc(sizeof(osm_qos_match_rule_t));
+	if (!p)
+		return NULL;
+
+	memset(p, 0, sizeof(osm_qos_match_rule_t));
+
+	cl_list_init(&p->source_list, 10);
+	cl_list_init(&p->source_group_list, 10);
+	cl_list_init(&p->destination_list, 10);
+	cl_list_init(&p->destination_group_list, 10);
+
+	return p;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p)
+{
+	unsigned i;
+
+	if (!p)
+		return;
+
+	if (p->qos_level_name)
+		free(p->qos_level_name);
+	if (p->use)
+		free(p->use);
+
+	for (i = 0; i < p->service_id_range_len; i++)
+		free(p->service_id_range_arr[i]);
+	if (p->service_id_range_arr)
+		free(p->service_id_range_arr);
+
+	for (i = 0; i < p->qos_class_range_len; i++)
+		free(p->qos_class_range_arr[i]);
+	if (p->qos_class_range_arr)
+		free(p->qos_class_range_arr);
+
+	for (i = 0; i < p->pkey_range_len; i++)
+		free(p->pkey_range_arr[i]);
+	if (p->pkey_range_arr)
+		free(p->pkey_range_arr);
+
+	cl_list_apply_func(&p->source_list, __free_single_element, NULL);
+	cl_list_remove_all(&p->source_list);
+	cl_list_destroy(&p->source_list);
+
+	cl_list_remove_all(&p->source_group_list);
+	cl_list_destroy(&p->source_group_list);
+
+	cl_list_apply_func(&p->destination_list, __free_single_element, NULL);
+	cl_list_remove_all(&p->destination_list);
+	cl_list_destroy(&p->destination_list);
+
+	cl_list_remove_all(&p->destination_group_list);
+	cl_list_destroy(&p->destination_group_list);
+
+	free(p);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_policy_t * osm_qos_policy_create(osm_subn_t * p_subn)
+{
+	osm_qos_policy_t * p_qos_policy = (osm_qos_policy_t *)malloc(sizeof(osm_qos_policy_t));
+	if (!p_qos_policy)
+		return NULL;
+
+	memset(p_qos_policy, 0, sizeof(osm_qos_policy_t));
+
+	cl_list_construct(&p_qos_policy->port_groups);
+	cl_list_init(&p_qos_policy->port_groups, 10);
+
+	cl_list_construct(&p_qos_policy->vlarb_tables);
+	cl_list_init(&p_qos_policy->vlarb_tables, 10);
+
+	cl_list_construct(&p_qos_policy->sl2vl_tables);
+	cl_list_init(&p_qos_policy->sl2vl_tables, 10);
+
+	cl_list_construct(&p_qos_policy->qos_levels);
+	cl_list_init(&p_qos_policy->qos_levels, 10);
+
+	cl_list_construct(&p_qos_policy->qos_match_rules);
+	cl_list_init(&p_qos_policy->qos_match_rules, 10);
+
+	p_qos_policy->p_subn = p_subn;
+	__build_nodebyname_hash(p_qos_policy);
+
+	return p_qos_policy;
+}
+
+/***************************************************
+ ***************************************************/
+
+void osm_qos_policy_destroy(osm_qos_policy_t * p_qos_policy)
+{
+	cl_list_iterator_t list_iterator;
+	osm_qos_port_group_t *p_port_group = NULL;
+	osm_qos_vlarb_scope_t *p_vlarb_scope = NULL;
+	osm_qos_sl2vl_scope_t *p_sl2vl_scope = NULL;
+	osm_qos_level_t *p_qos_level = NULL;
+	osm_qos_match_rule_t *p_qos_match_rule = NULL;
+
+	if (!p_qos_policy)
+		return;
+
+	list_iterator = cl_list_head(&p_qos_policy->port_groups);
+	while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) {
+		p_port_group =
+		    (osm_qos_port_group_t *) cl_list_obj(list_iterator);
+		if (p_port_group)
+			osm_qos_policy_port_group_destroy(p_port_group);
+		list_iterator = cl_list_next(list_iterator);
+	}
+	cl_list_remove_all(&p_qos_policy->port_groups);
+	cl_list_destroy(&p_qos_policy->port_groups);
+
+	list_iterator = cl_list_head(&p_qos_policy->vlarb_tables);
+	while (list_iterator != cl_list_end(&p_qos_policy->vlarb_tables)) {
+		p_vlarb_scope =
+		    (osm_qos_vlarb_scope_t *) cl_list_obj(list_iterator);
+		if (p_vlarb_scope)
+			osm_qos_policy_vlarb_scope_destroy(p_vlarb_scope);
+		list_iterator = cl_list_next(list_iterator);
+	}
+	cl_list_remove_all(&p_qos_policy->vlarb_tables);
+	cl_list_destroy(&p_qos_policy->vlarb_tables);
+
+	list_iterator = cl_list_head(&p_qos_policy->sl2vl_tables);
+	while (list_iterator != cl_list_end(&p_qos_policy->sl2vl_tables)) {
+		p_sl2vl_scope =
+		    (osm_qos_sl2vl_scope_t *) cl_list_obj(list_iterator);
+		if (p_sl2vl_scope)
+			osm_qos_policy_sl2vl_scope_destroy(p_sl2vl_scope);
+		list_iterator = cl_list_next(list_iterator);
+	}
+	cl_list_remove_all(&p_qos_policy->sl2vl_tables);
+	cl_list_destroy(&p_qos_policy->sl2vl_tables);
+
+	list_iterator = cl_list_head(&p_qos_policy->qos_levels);
+	while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) {
+		p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator);
+		if (p_qos_level)
+			osm_qos_policy_qos_level_destroy(p_qos_level);
+		list_iterator = cl_list_next(list_iterator);
+	}
+	cl_list_remove_all(&p_qos_policy->qos_levels);
+	cl_list_destroy(&p_qos_policy->qos_levels);
+
+	list_iterator = cl_list_head(&p_qos_policy->qos_match_rules);
+	while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) {
+		p_qos_match_rule =
+		    (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
+		if (p_qos_match_rule)
+			osm_qos_policy_match_rule_destroy(p_qos_match_rule);
+		list_iterator = cl_list_next(list_iterator);
+	}
+	cl_list_remove_all(&p_qos_policy->qos_match_rules);
+	cl_list_destroy(&p_qos_policy->qos_match_rules);
+
+	if (p_qos_policy->p_node_hash)
+		st_free_table(p_qos_policy->p_node_hash);
+
+	free(p_qos_policy);
+
+	p_qos_policy = NULL;
+}
+
+/***************************************************
+ ***************************************************/
+
+static boolean_t
+__qos_policy_is_port_in_group(osm_subn_t * p_subn,
+			      const osm_physp_t * p_physp,
+			      osm_qos_port_group_t * p_port_group)
+{
+	osm_node_t *p_node = osm_physp_get_node_ptr(p_physp);
+	ib_net64_t port_guid = osm_physp_get_port_guid(p_physp);
+	uint64_t port_guid_ho = cl_ntoh64(port_guid);
+
+	/* check whether this port's type matches any of group's types */
+
+	if ( p_port_group->node_types &
+	     (((uint8_t)1)<<osm_node_get_type(p_node)) )
+		return TRUE;
+
+	/* check whether this port's guid is in group's port map */
+
+	if (cl_qmap_get(&p_port_group->port_map, port_guid_ho) !=
+	    cl_qmap_end(&p_port_group->port_map))
+		return TRUE;
+
+	return FALSE;
+}				/* __qos_policy_is_port_in_group() */
+
+/***************************************************
+ ***************************************************/
+
+static boolean_t
+__qos_policy_is_port_in_group_list(const osm_qos_policy_t * p_qos_policy,
+				   const osm_physp_t * p_physp,
+				   cl_list_t * p_port_group_list)
+{
+	osm_qos_port_group_t *p_port_group;
+	cl_list_iterator_t list_iterator;
+
+	list_iterator = cl_list_head(p_port_group_list);
+	while (list_iterator != cl_list_end(p_port_group_list)) {
+		p_port_group =
+		    (osm_qos_port_group_t *) cl_list_obj(list_iterator);
+		if (p_port_group) {
+			if (__qos_policy_is_port_in_group
+			    (p_qos_policy->p_subn, p_physp, p_port_group))
+				return TRUE;
+		}
+		list_iterator = cl_list_next(list_iterator);
+	}
+	return FALSE;
+}
+
+/***************************************************
+ ***************************************************/
+
+static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params(
+			 const osm_qos_policy_t * p_qos_policy,
+			 uint64_t service_id,
+			 uint16_t qos_class,
+			 uint16_t pkey,
+			 const osm_physp_t * p_src_physp,
+			 const osm_physp_t * p_dest_physp,
+			 ib_net64_t comp_mask)
+{
+	osm_qos_match_rule_t *p_qos_match_rule = NULL;
+	cl_list_iterator_t list_iterator;
+	osm_log_t * p_log = &p_qos_policy->p_subn->p_osm->log;
+
+	boolean_t matched_by_sguid = FALSE,
+		  matched_by_dguid = FALSE,
+		  matched_by_class = FALSE,
+		  matched_by_sid = FALSE,
+		  matched_by_pkey = FALSE;
+
+	if (!cl_list_count(&p_qos_policy->qos_match_rules))
+		return NULL;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* Go over all QoS match rules and find the one that matches the request */
+
+	list_iterator = cl_list_head(&p_qos_policy->qos_match_rules);
+	while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) {
+		p_qos_match_rule =
+		    (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
+		if (!p_qos_match_rule) {
+			list_iterator = cl_list_next(list_iterator);
+			continue;
+		}
+
+		/* If a match rule has Source groups, PR request source has to be in this list */
+
+		if (cl_list_count(&p_qos_match_rule->source_group_list)) {
+			if (!__qos_policy_is_port_in_group_list(p_qos_policy,
+								p_src_physp,
+								&p_qos_match_rule->
+								source_group_list))
+			{
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+			matched_by_sguid = TRUE;
+		}
+
+		/* If a match rule has Destination groups, PR request dest. has to be in this list */
+
+		if (cl_list_count(&p_qos_match_rule->destination_group_list)) {
+			if (!__qos_policy_is_port_in_group_list(p_qos_policy,
+								p_dest_physp,
+								&p_qos_match_rule->
+								destination_group_list))
+			{
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+			matched_by_dguid = TRUE;
+		}
+
+		/* If a match rule has QoS classes, PR request HAS
+		   to have a matching QoS class to match the rule */
+
+		if (p_qos_match_rule->qos_class_range_len) {
+			if (!(comp_mask & IB_PR_COMPMASK_QOS_CLASS)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+
+			if (!__is_num_in_range_arr
+			    (p_qos_match_rule->qos_class_range_arr,
+			     p_qos_match_rule->qos_class_range_len,
+			     qos_class)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+			matched_by_class = TRUE;
+		}
+
+		/* If a match rule has Service IDs, PR request HAS
+		   to have a matching Service ID to match the rule */
+
+		if (p_qos_match_rule->service_id_range_len) {
+			if (!(comp_mask & IB_PR_COMPMASK_SERVICEID_MSB) ||
+			    !(comp_mask & IB_PR_COMPMASK_SERVICEID_LSB)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+
+			if (!__is_num_in_range_arr
+			    (p_qos_match_rule->service_id_range_arr,
+			     p_qos_match_rule->service_id_range_len,
+			     service_id)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+			matched_by_sid = TRUE;
+		}
+
+		/* If a match rule has PKeys, PR request HAS
+		   to have a matching PKey to match the rule */
+
+		if (p_qos_match_rule->pkey_range_len) {
+			if (!(comp_mask & IB_PR_COMPMASK_PKEY)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+
+			if (!__is_num_in_range_arr
+			    (p_qos_match_rule->pkey_range_arr,
+			     p_qos_match_rule->pkey_range_len,
+			     pkey & 0x7FFF)) {
+				list_iterator = cl_list_next(list_iterator);
+				continue;
+			}
+			matched_by_pkey = TRUE;
+		}
+
+		/* if we got here, then this match-rule matched this PR request */
+		break;
+	}
+
+	if (list_iterator == cl_list_end(&p_qos_policy->qos_match_rules))
+		p_qos_match_rule = NULL;
+
+	if (p_qos_match_rule)
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"request matched rule (%s) by:%s%s%s%s%s\n",
+			(p_qos_match_rule->use) ?
+				p_qos_match_rule->use : "no description",
+			(matched_by_sguid) ? " SGUID" : "",
+			(matched_by_dguid) ? " DGUID" : "",
+			(matched_by_class) ? " QoS_Class" : "",
+			(matched_by_sid)   ? " ServiceID" : "",
+			(matched_by_pkey)  ? " PKey" : "");
+	else
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"request not matched any rule\n");
+
+	OSM_LOG_EXIT(p_log);
+	return p_qos_match_rule;
+}				/* __qos_policy_get_match_rule_by_params() */
+
+/***************************************************
+ ***************************************************/
+
+static osm_qos_level_t *__qos_policy_get_qos_level_by_name(
+		const osm_qos_policy_t * p_qos_policy,
+		char *name)
+{
+	osm_qos_level_t *p_qos_level = NULL;
+	cl_list_iterator_t list_iterator;
+
+	list_iterator = cl_list_head(&p_qos_policy->qos_levels);
+	while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) {
+		p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator);
+		if (!p_qos_level)
+			continue;
+
+		/* names are case INsensitive */
+		if (strcasecmp(name, p_qos_level->name) == 0)
+			return p_qos_level;
+
+		list_iterator = cl_list_next(list_iterator);
+	}
+
+	return NULL;
+}
+
+/***************************************************
+ ***************************************************/
+
+static osm_qos_port_group_t *__qos_policy_get_port_group_by_name(
+		const osm_qos_policy_t * p_qos_policy,
+		const char *const name)
+{
+	osm_qos_port_group_t *p_port_group = NULL;
+	cl_list_iterator_t list_iterator;
+
+	list_iterator = cl_list_head(&p_qos_policy->port_groups);
+	while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) {
+		p_port_group =
+		    (osm_qos_port_group_t *) cl_list_obj(list_iterator);
+		if (!p_port_group)
+			continue;
+
+		/* names are case INsensitive */
+		if (strcasecmp(name, p_port_group->name) == 0)
+			return p_port_group;
+
+		list_iterator = cl_list_next(list_iterator);
+	}
+
+	return NULL;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __qos_policy_validate_pkey(
+			osm_qos_policy_t * p_qos_policy,
+			osm_qos_match_rule_t * p_qos_match_rule,
+			osm_prtn_t * p_prtn)
+{
+	uint8_t sl;
+	uint32_t flow;
+	uint8_t hop;
+	osm_mgrp_t * p_mgrp;
+
+	if (!p_qos_policy || !p_qos_match_rule || !p_prtn)
+		return;
+
+	if (!p_qos_match_rule->p_qos_level->sl_set ||
+	    p_prtn->sl == p_qos_match_rule->p_qos_level->sl)
+		return;
+
+	/* overriding partition's SL */
+	OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR,
+		"ERR AC15: pkey 0x%04X in match rule - "
+		"overriding partition SL (%u) with QoS Level SL (%u)\n",
+		cl_ntoh16(p_prtn->pkey), p_prtn->sl,
+		p_qos_match_rule->p_qos_level->sl);
+	p_prtn->sl = p_qos_match_rule->p_qos_level->sl;
+
+
+	/* If this partition is an IPoIB partition, there should
+	   be a matching MCast group. Fix this group's SL too */
+
+	if (!p_prtn->mlid)
+		return;
+
+	p_mgrp = osm_get_mgrp_by_mlid(p_qos_policy->p_subn, p_prtn->mlid);
+	if (!p_mgrp) {
+		OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR,
+			"ERR AC16: MCast group for partition with "
+			"pkey 0x%04X not found\n",
+			cl_ntoh16(p_prtn->pkey));
+		return;
+	}
+
+	CL_ASSERT((cl_ntoh16(p_mgrp->mcmember_rec.pkey) & 0x7fff) ==
+		  (cl_ntoh16(p_prtn->pkey) & 0x7fff));
+
+	ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+				  &sl, &flow, &hop);
+	if (sl != p_prtn->sl) {
+		OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_DEBUG,
+			"Updating MCGroup (MLID 0x%04x) SL to "
+			"match partition SL (%u)\n",
+			cl_hton16(p_mgrp->mcmember_rec.mlid),
+			p_prtn->sl);
+		p_mgrp->mcmember_rec.sl_flow_hop =
+			ib_member_set_sl_flow_hop(p_prtn->sl, flow, hop);
+	}
+}
+
+/***************************************************
+ ***************************************************/
+
+int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
+			    osm_log_t *p_log)
+{
+	cl_list_iterator_t match_rules_list_iterator;
+	cl_list_iterator_t list_iterator;
+	osm_qos_port_group_t *p_port_group = NULL;
+	osm_qos_match_rule_t *p_qos_match_rule = NULL;
+	char *str;
+	unsigned i, j;
+	int res = 0;
+	uint64_t pkey_64;
+	ib_net16_t pkey;
+	osm_prtn_t * p_prtn;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* set default qos level */
+
+	p_qos_policy->p_default_qos_level =
+	    __qos_policy_get_qos_level_by_name(p_qos_policy, OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
+	if (!p_qos_policy->p_default_qos_level) {
+		/* There's no default QoS level in the usual qos-level section.
+		   Check whether the 'simple' default QoS level that can be
+		   defined in the qos-ulp section exists */
+		if (__default_simple_qos_level.sl_set) {
+			p_qos_policy->p_default_qos_level = &__default_simple_qos_level;
+		}
+		else {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC10: "
+				"Default qos-level (%s) not defined.\n",
+				OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
+			res = 1;
+			goto Exit;
+		}
+	}
+
+	/* scan all the match rules, and fill the lists of pointers to
+	   relevant qos levels and port groups to speed up PR matching */
+
+	i = 1;
+	match_rules_list_iterator =
+	    cl_list_head(&p_qos_policy->qos_match_rules);
+	while (match_rules_list_iterator !=
+	       cl_list_end(&p_qos_policy->qos_match_rules)) {
+		p_qos_match_rule =
+		    (osm_qos_match_rule_t *)
+		    cl_list_obj(match_rules_list_iterator);
+		CL_ASSERT(p_qos_match_rule);
+
+		/* find the matching qos-level for each match-rule */
+
+		if (!p_qos_match_rule->p_qos_level)
+			p_qos_match_rule->p_qos_level =
+				__qos_policy_get_qos_level_by_name(p_qos_policy,
+					       p_qos_match_rule->qos_level_name);
+
+		if (!p_qos_match_rule->p_qos_level) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC11: "
+				"qos-match-rule num %u: qos-level '%s' not found\n",
+				i, p_qos_match_rule->qos_level_name);
+			res = 1;
+			goto Exit;
+		}
+
+		/* find the matching port-group for element of source_list */
+
+		if (cl_list_count(&p_qos_match_rule->source_list)) {
+			list_iterator =
+			    cl_list_head(&p_qos_match_rule->source_list);
+			while (list_iterator !=
+			       cl_list_end(&p_qos_match_rule->source_list)) {
+				str = (char *)cl_list_obj(list_iterator);
+				CL_ASSERT(str);
+
+				p_port_group =
+				    __qos_policy_get_port_group_by_name(p_qos_policy, str);
+				if (!p_port_group) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC12: "
+						"qos-match-rule num %u: source port-group '%s' not found\n",
+						i, str);
+					res = 1;
+					goto Exit;
+				}
+
+				cl_list_insert_tail(&p_qos_match_rule->
+						    source_group_list,
+						    p_port_group);
+
+				list_iterator = cl_list_next(list_iterator);
+			}
+		}
+
+		/* find the matching port-group for element of destination_list */
+
+		if (cl_list_count(&p_qos_match_rule->destination_list)) {
+			list_iterator =
+			    cl_list_head(&p_qos_match_rule->destination_list);
+			while (list_iterator !=
+			       cl_list_end(&p_qos_match_rule->
+					   destination_list)) {
+				str = (char *)cl_list_obj(list_iterator);
+				CL_ASSERT(str);
+
+				p_port_group =
+				    __qos_policy_get_port_group_by_name(p_qos_policy,str);
+				if (!p_port_group) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC13: "
+						"qos-match-rule num %u: destination port-group '%s' not found\n",
+						i, str);
+					res = 1;
+					goto Exit;
+				}
+
+				cl_list_insert_tail(&p_qos_match_rule->
+						    destination_group_list,
+						    p_port_group);
+
+				list_iterator = cl_list_next(list_iterator);
+			}
+		}
+
+		/*
+		 * Scan all the pkeys in matching rule, and if the
+		 * partition for these pkeys exists, set the SL
+		 * according to the QoS Level.
+		 * Warn if there's mismatch between QoS level SL
+		 * and Partition SL.
+		 */
+
+		for (j = 0; j < p_qos_match_rule->pkey_range_len; j++) {
+			for ( pkey_64 = p_qos_match_rule->pkey_range_arr[j][0];
+			      pkey_64 <= p_qos_match_rule->pkey_range_arr[j][1];
+			      pkey_64++) {
+                                pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
+				p_prtn = (osm_prtn_t *)cl_qmap_get(
+					&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
+
+				if (p_prtn == (osm_prtn_t *)cl_qmap_end(
+					&p_qos_policy->p_subn->prtn_pkey_tbl))
+					/* partition for this pkey not found */
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC14: "
+						"pkey 0x%04X in match rule - "
+						"partition doesn't exist\n",
+						cl_ntoh16(pkey));
+				else
+					__qos_policy_validate_pkey(p_qos_policy,
+							p_qos_match_rule,
+							p_prtn);
+			}
+		}
+
+		/* done with the current match-rule */
+
+		match_rules_list_iterator =
+		    cl_list_next(match_rules_list_iterator);
+		i++;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return res;
+}				/* osm_qos_policy_validate() */
+
+/***************************************************
+ ***************************************************/
+
+static osm_qos_level_t * __qos_policy_get_qos_level_by_params(
+	IN const osm_qos_policy_t * p_qos_policy,
+	IN const osm_physp_t * p_src_physp,
+	IN const osm_physp_t * p_dest_physp,
+	IN uint64_t service_id,
+	IN uint16_t qos_class,
+	IN uint16_t pkey,
+	IN ib_net64_t comp_mask)
+{
+	osm_qos_match_rule_t *p_qos_match_rule = NULL;
+
+	if (!p_qos_policy)
+		return NULL;
+
+	p_qos_match_rule = __qos_policy_get_match_rule_by_params(
+		p_qos_policy, service_id, qos_class, pkey,
+		p_src_physp, p_dest_physp, comp_mask);
+
+	return p_qos_match_rule ? p_qos_match_rule->p_qos_level :
+		p_qos_policy->p_default_qos_level;
+}				/* __qos_policy_get_qos_level_by_params() */
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_level_t * osm_qos_policy_get_qos_level_by_pr(
+	IN const osm_qos_policy_t * p_qos_policy,
+	IN const ib_path_rec_t * p_pr,
+	IN const osm_physp_t * p_src_physp,
+	IN const osm_physp_t * p_dest_physp,
+	IN ib_net64_t comp_mask)
+{
+	return __qos_policy_get_qos_level_by_params(
+		p_qos_policy, p_src_physp, p_dest_physp,
+		cl_ntoh64(p_pr->service_id), ib_path_rec_qos_class(p_pr),
+		cl_ntoh16(p_pr->pkey), comp_mask);
+}
+
+/***************************************************
+ ***************************************************/
+
+osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr(
+	IN const osm_qos_policy_t * p_qos_policy,
+	IN const ib_multipath_rec_t * p_mpr,
+	IN const osm_physp_t * p_src_physp,
+	IN const osm_physp_t * p_dest_physp,
+	IN ib_net64_t comp_mask)
+{
+	ib_net64_t pr_comp_mask = 0;
+
+	if (!p_qos_policy)
+		return NULL;
+
+	/*
+	 * Converting MultiPathRecord compmask to the PathRecord
+	 * compmask. Note that only relevant bits are set.
+	 */
+	pr_comp_mask =
+		((comp_mask & IB_MPR_COMPMASK_QOS_CLASS) ?
+		 IB_PR_COMPMASK_QOS_CLASS : 0) |
+		((comp_mask & IB_MPR_COMPMASK_PKEY) ?
+		 IB_PR_COMPMASK_PKEY : 0) |
+		((comp_mask & IB_MPR_COMPMASK_SERVICEID_MSB) ?
+		 IB_PR_COMPMASK_SERVICEID_MSB : 0) |
+		((comp_mask & IB_MPR_COMPMASK_SERVICEID_LSB) ?
+		 IB_PR_COMPMASK_SERVICEID_LSB : 0);
+
+	return __qos_policy_get_qos_level_by_params(
+		p_qos_policy, p_src_physp, p_dest_physp,
+		cl_ntoh64(ib_multipath_rec_service_id(p_mpr)),
+		ib_multipath_rec_qos_class(p_mpr),
+		cl_ntoh16(p_mpr->pkey), pr_comp_mask);
+}
+
+/***************************************************
+ ***************************************************/
diff --git a/opensm/osm_remote_sm.c b/opensm/osm_remote_sm.c
new file mode 100644
index 0000000..96bfd78
--- /dev/null
+++ b/opensm/osm_remote_sm.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_t.
+ * This object represents the remote SM object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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;
+}
diff --git a/opensm/osm_req.c b/opensm/osm_req.c
new file mode 100644
index 0000000..0865ce5
--- /dev/null
+++ b/opensm/osm_req.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_req_t.
+ * This object represents the generic attribute requester.
+ * This object is part of the opensm family of objects.
+ */
+
+#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_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>
+
+/**********************************************************************
+  The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_get(IN osm_sm_t * sm,
+	    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(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_path);
+	CL_ASSERT(attr_id);
+
+	/* do nothing if we are exiting ... */
+	if (osm_exit_flag)
+		goto Exit;
+
+	/* p_context may be NULL. */
+
+	p_madw = osm_mad_pool_get(sm->p_mad_pool,
+				  p_path->h_bind, MAD_BLOCK_SIZE, NULL);
+
+	if (p_madw == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 1101: Unable to acquire MAD\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id));
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"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,
+			sm->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(sm->p_vl15, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+  The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_set(IN osm_sm_t * sm,
+	    IN const osm_dr_path_t * 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(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_path);
+	CL_ASSERT(attr_id);
+	CL_ASSERT(p_payload);
+
+	/* do nothing if we are exiting ... */
+	if (osm_exit_flag)
+		goto Exit;
+
+	/* p_context may be NULL. */
+
+	p_madw = osm_mad_pool_get(sm->p_mad_pool,
+				  p_path->h_bind, MAD_BLOCK_SIZE, NULL);
+
+	if (p_madw == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 1102: Unable to acquire MAD\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id));
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"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,
+			sm->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(sm->p_vl15, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+int osm_send_trap144(osm_sm_t *sm, ib_net16_t local)
+{
+	osm_madw_t *madw;
+	ib_smp_t *smp;
+	ib_mad_notice_attr_t *ntc;
+	osm_port_t *port;
+	ib_port_info_t *pi;
+
+	port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);
+	if (!port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n",
+			cl_ntoh64(sm->p_subn->sm_port_guid));
+		return -1;
+	}
+
+	pi = &port->p_physp->port_info;
+
+	/* don't bother with sending trap when SMA supports this */
+	if (!local &&
+	    pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC))
+		return 0;
+
+	madw = osm_mad_pool_get(sm->p_mad_pool,
+				osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl),
+				MAD_BLOCK_SIZE, NULL);
+	if (madw == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 1105: Unable to acquire MAD\n");
+		return -1;
+	}
+
+	madw->mad_addr.dest_lid = pi->master_sm_base_lid;
+	madw->mad_addr.addr_type.smi.source_lid = pi->base_lid;
+	madw->fail_msg = CL_DISP_MSGID_NONE;
+
+	smp = osm_madw_get_smp_ptr(madw);
+	memset(smp, 0, sizeof(*smp));
+
+	smp->base_ver = 1;
+	smp->mgmt_class = IB_MCLASS_SUBN_LID;
+	smp->class_ver = 1;
+	smp->method = IB_MAD_METHOD_TRAP;
+	smp->trans_id = cl_hton64((uint64_t)cl_atomic_inc(&sm->sm_trans_id));
+	smp->attr_id = IB_MAD_ATTR_NOTICE;
+	smp->m_key = sm->p_subn->opt.m_key;
+
+	ntc = (ib_mad_notice_attr_t *)smp->data;
+
+	ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
+	ib_notice_set_prod_type_ho(ntc, IB_NODE_TYPE_CA);
+	ntc->g_or_v.generic.trap_num = cl_hton16(144);
+	ntc->issuer_lid = pi->base_lid;
+	ntc->data_details.ntc_144.lid = pi->base_lid;
+	ntc->data_details.ntc_144.local_changes = local ?
+		TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0;
+	ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask;
+	ntc->data_details.ntc_144.change_flgs = local;
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n",
+		cl_ntoh64(smp->trans_id), cl_ntoh16(pi->master_sm_base_lid));
+
+	osm_vl15_post(sm->p_vl15, madw);
+
+	return 0;
+}
diff --git a/opensm/osm_resp.c b/opensm/osm_resp.c
new file mode 100644
index 0000000..9cd44f5
--- /dev/null
+++ b/opensm/osm_resp.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_resp_t.
+ * This object represents the generic attribute responder.
+ * This object is part of the opensm family of objects.
+ */
+
+#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_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>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_resp_make_resp_smp(IN osm_sm_t * sm,
+		       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(sm->p_log);
+
+	CL_ASSERT(p_dest_smp);
+	CL_ASSERT(p_src_smp);
+	CL_ASSERT(!ib_smp_is_response(p_src_smp));
+
+	*p_dest_smp = *p_src_smp;
+	if (p_src_smp->method == IB_MAD_METHOD_GET ||
+	    p_src_smp->method == IB_MAD_METHOD_SET) {
+		p_dest_smp->method = IB_MAD_METHOD_GET_RESP;
+		p_dest_smp->status = status;
+	} else if (p_src_smp->method == IB_MAD_METHOD_TRAP) {
+		p_dest_smp->method = IB_MAD_METHOD_TRAP_REPRESS;
+		p_dest_smp->status = 0;
+	} else {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1302: "
+			"src smp method unsupported 0x%X\n", p_src_smp->method);
+		goto Exit;
+	}
+
+	if (p_src_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+		p_dest_smp->status |= IB_SMP_DIRECTION;
+
+	p_dest_smp->dr_dlid = p_dest_smp->dr_slid;
+	p_dest_smp->dr_slid = p_dest_smp->dr_dlid;
+	memcpy(&p_dest_smp->data, p_payload, IB_SMP_DATA_SIZE);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_send(IN osm_sm_t * sm,
+	      IN const osm_madw_t * 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(sm->p_log);
+
+	CL_ASSERT(p_req_madw);
+	CL_ASSERT(p_payload);
+
+	/* do nothing if we are exiting ... */
+	if (osm_exit_flag)
+		goto Exit;
+
+	p_madw = osm_mad_pool_get(sm->p_mad_pool,
+				  osm_madw_get_bind_handle(p_req_madw),
+				  MAD_BLOCK_SIZE, NULL);
+
+	if (p_madw == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 1301: Unable to acquire MAD\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	/*
+	   Copy the request smp to the response smp, then just
+	   update the necessary fields.
+	 */
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_req_smp = osm_madw_get_smp_ptr(p_req_madw);
+	osm_resp_make_resp_smp(sm, p_req_smp, mad_status, p_payload, p_smp);
+	p_madw->mad_addr.dest_lid =
+	    p_req_madw->mad_addr.addr_type.smi.source_lid;
+	p_madw->mad_addr.addr_type.smi.source_lid =
+	    p_req_madw->mad_addr.dest_lid;
+
+	p_madw->resp_expected = FALSE;
+	p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to %s (0x%X)"
+		"\n\t\t\t\tattribute modifier 0x%X, TID 0x%" PRIx64 "\n",
+		ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh16(p_smp->attr_id),
+		cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->trans_id));
+
+	osm_vl15_post(sm->p_vl15, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
diff --git a/opensm/osm_router.c b/opensm/osm_router.c
new file mode 100644
index 0000000..cb5a236
--- /dev/null
+++ b/opensm/osm_router.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_router_t.
+ * This object represents an Infiniband router.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_router.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_router_delete(IN OUT osm_router_t ** const pp_rtr)
+{
+	free(*pp_rtr);
+	*pp_rtr = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_router_t *osm_router_new(IN osm_port_t * const p_port)
+{
+	osm_router_t *p_rtr;
+
+	CL_ASSERT(p_port);
+
+	p_rtr = (osm_router_t *) malloc(sizeof(*p_rtr));
+	if (p_rtr) {
+		memset(p_rtr, 0, sizeof(*p_rtr));
+		p_rtr->p_port = p_port;
+	}
+
+	return (p_rtr);
+}
diff --git a/opensm/osm_sa.c b/opensm/osm_sa.c
new file mode 100644
index 0000000..185557f
--- /dev/null
+++ b/opensm/osm_sa.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_t.
+ * This object represents the Subnet Administration object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.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_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>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+#define  OSM_SA_INITIAL_TID_VALUE 0xabc
+
+extern void osm_cpi_rcv_process(IN void *context, IN void *data);
+extern void osm_gir_rcv_process(IN void *context, IN void *data);
+extern void osm_infr_rcv_process(IN void *context, IN void *data);
+extern void osm_infir_rcv_process(IN void *context, IN void *data);
+extern void osm_lftr_rcv_process(IN void *context, IN void *data);
+extern void osm_lr_rcv_process(IN void *context, IN void *data);
+extern void osm_mcmr_rcv_process(IN void *context, IN void *data);
+extern void osm_mftr_rcv_process(IN void *context, IN void *data);
+extern void osm_mpr_rcv_process(IN void *context, IN void *data);
+extern void osm_nr_rcv_process(IN void *context, IN void *data);
+extern void osm_pr_rcv_process(IN void *context, IN void *data);
+extern void osm_pkey_rec_rcv_process(IN void *context, IN void *data);
+extern void osm_pir_rcv_process(IN void *context, IN void *data);
+extern void osm_sr_rcv_process(IN void *context, IN void *data);
+extern void osm_slvl_rec_rcv_process(IN void *context, IN void *data);
+extern void osm_smir_rcv_process(IN void *context, IN void *data);
+extern void osm_sir_rcv_process(IN void *context, IN void *data);
+extern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data);
+extern void osm_sr_rcv_lease_cb(IN void *context);
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sa_construct(IN osm_sa_t * 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;
+
+	cl_timer_construct(&p_sa->sr_timer);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sa_shutdown(IN osm_sa_t * const p_sa)
+{
+	ib_api_status_t status;
+	OSM_LOG_ENTER(p_sa->p_log);
+
+	cl_timer_stop(&p_sa->sr_timer);
+
+	/* unbind from the mad service */
+	status = osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl);
+
+	/* remove any registered dispatcher message */
+	cl_disp_unregister(p_sa->nr_disp_h);
+	cl_disp_unregister(p_sa->pir_disp_h);
+	cl_disp_unregister(p_sa->gir_disp_h);
+	cl_disp_unregister(p_sa->lr_disp_h);
+	cl_disp_unregister(p_sa->pr_disp_h);
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	cl_disp_unregister(p_sa->mpr_disp_h);
+#endif
+	cl_disp_unregister(p_sa->smir_disp_h);
+	cl_disp_unregister(p_sa->mcmr_disp_h);
+	cl_disp_unregister(p_sa->sr_disp_h);
+	cl_disp_unregister(p_sa->infr_disp_h);
+	cl_disp_unregister(p_sa->infir_disp_h);
+	cl_disp_unregister(p_sa->vlarb_disp_h);
+	cl_disp_unregister(p_sa->slvl_disp_h);
+	cl_disp_unregister(p_sa->pkey_disp_h);
+	cl_disp_unregister(p_sa->lft_disp_h);
+	cl_disp_unregister(p_sa->sir_disp_h);
+	cl_disp_unregister(p_sa->mft_disp_h);
+	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);
+
+	p_sa->state = OSM_SA_STATE_INIT;
+
+	cl_timer_destroy(&p_sa->sr_timer);
+
+	OSM_LOG_EXIT(p_sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_init(IN osm_sm_t * 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);
+
+	p_sa->sm = p_sm;
+	p_sa->p_subn = p_subn;
+	p_sa->p_vendor = p_vendor;
+	p_sa->p_mad_pool = p_mad_pool;
+	p_sa->p_log = p_log;
+	p_sa->p_disp = p_disp;
+	p_sa->p_lock = p_lock;
+
+	p_sa->state = OSM_SA_STATE_READY;
+
+	status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl,
+				      p_sa,
+				      p_sa->p_mad_pool,
+				      p_sa->p_vendor,
+				      p_subn, p_log, p_stats, p_disp);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO,
+					    osm_cpi_rcv_process, p_sa);
+	if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD,
+					   osm_nr_rcv_process, p_sa);
+	if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD,
+					    osm_pir_rcv_process, p_sa);
+	if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD,
+					    osm_gir_rcv_process, p_sa);
+	if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD,
+					   osm_lr_rcv_process, p_sa);
+	if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD,
+					   osm_pr_rcv_process, p_sa);
+	if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	p_sa->mpr_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD,
+			     osm_mpr_rcv_process, p_sa);
+	if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+#endif
+
+	p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD,
+					     osm_smir_rcv_process, p_sa);
+	if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->mcmr_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD,
+			     osm_mcmr_rcv_process, p_sa);
+	if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD,
+					   osm_sr_rcv_process, p_sa);
+	if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO,
+					     osm_infr_rcv_process, p_sa);
+	if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->infir_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD,
+			     osm_infir_rcv_process, p_sa);
+	if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD,
+					      osm_vlarb_rec_rcv_process, p_sa);
+	if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->slvl_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD,
+			     osm_slvl_rec_rcv_process, p_sa);
+	if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->pkey_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD,
+			     osm_pkey_rec_rcv_process, p_sa);
+	if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD,
+					    osm_lftr_rcv_process, p_sa);
+	if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->sir_disp_h =
+	    cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD,
+			     osm_sir_rcv_process, p_sa);
+	if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD,
+					    osm_mftr_rcv_process, p_sa);
+	if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+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);
+
+	status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: "
+			"SA MAD Controller bind failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_sa->p_log);
+	return (status);
+}
+
+ib_api_status_t osm_sa_send(osm_sa_t *sa,
+			    IN osm_madw_t * const p_madw,
+			    IN boolean_t const resp_expected)
+{
+	ib_api_status_t status;
+
+	cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent);
+	status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected);
+	if (status != IB_SUCCESS) {
+		cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent);
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: "
+			"osm_vendor_send failed, status = %s\n",
+			ib_get_err_str(status));
+	}
+	return status;
+}
+
+void
+osm_sa_send_error(IN osm_sa_t * sa,
+		  IN const osm_madw_t * 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;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/* avoid races - if we are exiting - exit */
+	if (osm_exit_flag) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Ignoring requested send after exit\n");
+		goto Exit;
+	}
+
+	p_resp_madw = osm_mad_pool_get(sa->p_mad_pool,
+				       p_madw->h_bind, MAD_BLOCK_SIZE,
+				       &p_madw->mad_addr);
+
+	if (p_resp_madw == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: "
+			"Unable to acquire response MAD\n");
+		goto Exit;
+	}
+
+	p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	/*  Copy the MAD header back into the response mad */
+	*p_resp_sa_mad = *p_sa_mad;
+	p_resp_sa_mad->status = sa_status;
+
+	if (p_resp_sa_mad->method == IB_MAD_METHOD_SET)
+		p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+	else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE)
+		p_resp_sa_mad->attr_offset = 0;
+
+	p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+
+	/*
+	 * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
+	 */
+	p_resp_sa_mad->sm_key = 0;
+
+	/*
+	 * o15-0.2.7 - The PathRecord Attribute ID shall be used in
+	 * the response (to a SubnAdmGetMulti(MultiPathRecord)
+	 */
+	if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD)
+		p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES))
+		osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES);
+
+	osm_sa_send(sa, p_resp_madw, FALSE);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
+		    cl_qlist_t *list)
+{
+	struct item_data {
+		cl_list_item_t list;
+		char data[0];
+	};
+	cl_list_item_t *item;
+	osm_madw_t *resp_madw;
+	ib_sa_mad_t *sa_mad, *resp_sa_mad;
+	unsigned num_rec, i;
+#ifndef VENDOR_RMPP_SUPPORT
+	unsigned trim_num_rec;
+#endif
+	void *p;
+
+	sa_mad = osm_madw_get_sa_mad_ptr(madw);
+	num_rec = cl_qlist_count(list);
+
+	/*
+	 * C15-0.1.30:
+	 * If we do a SubnAdmGet and got more than one record it is an error!
+	 */
+	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
+			"Got more than one record for SubnAdmGet (%u)\n",
+			num_rec);
+		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+		goto Exit;
+	}
+
+#ifndef VENDOR_RMPP_SUPPORT
+	trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
+	if (trim_num_rec < num_rec) {
+		OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+			"Number of records:%u trimmed to:%u to fit in one MAD\n",
+			num_rec, trim_num_rec);
+		num_rec = trim_num_rec;
+	}
+#endif
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec);
+
+	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) {
+		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS);
+		goto Exit;
+	}
+
+	/*
+	 * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+	 */
+	resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind,
+				     num_rec * attr_size + IB_SA_MAD_HDR_SIZE,
+				     &madw->mad_addr);
+	if (!resp_madw) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: "
+			"osm_mad_pool_get failed\n");
+		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES);
+		goto Exit;
+	}
+
+	resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw);
+
+	/*
+	   Copy the MAD header back into the response mad.
+	   Set the 'R' bit and the payload length,
+	   Then copy all records from the list into the response payload.
+	 */
+
+	memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE);
+	if (resp_sa_mad->method == IB_MAD_METHOD_SET)
+		resp_sa_mad->method = IB_MAD_METHOD_GET;
+	resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+	/* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+	resp_sa_mad->sm_key = 0;
+
+	/* Fill in the offset (paylen will be done by the rmpp SAR) */
+	resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0;
+
+	p = ib_sa_mad_get_payload_ptr(resp_sa_mad);
+
+#ifndef VENDOR_RMPP_SUPPORT
+	/* we support only one packet RMPP - so we will set the first and
+	   last flags for gettable */
+	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) {
+		resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+		resp_sa_mad->rmpp_flags =
+		    IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST |
+		    IB_RMPP_FLAG_ACTIVE;
+	}
+#else
+	/* forcefully define the packet as RMPP one */
+	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+		resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+	for (i = 0; i < num_rec; i++) {
+		item = cl_qlist_remove_head(list);
+		memcpy(p, ((struct item_data *)item)->data, attr_size);
+		p += attr_size;
+		free(item);
+	}
+
+	osm_sa_send(sa, resp_madw, FALSE);
+
+	osm_dump_sa_mad(sa->p_log, resp_sa_mad, OSM_LOG_FRAMES);
+Exit:
+	/* need to set the mem free ... */
+	item = cl_qlist_remove_head(list);
+	while (item != cl_qlist_end(list)) {
+		free(item);
+		item = cl_qlist_remove_head(list);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ *  SA DB Dumper
+ *
+ */
+
+struct opensm_dump_context {
+	osm_opensm_t *p_osm;
+	FILE *file;
+};
+
+static int
+opensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name,
+		    void (*dump_func) (osm_opensm_t * p_osm, FILE * file))
+{
+	char path[1024];
+	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, "ERR 4C01: "
+			"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(osm_mgrp_t *p_mgrp, void *cxt)
+{
+	struct opensm_dump_context dump_context;
+	osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
+	FILE *file = ((struct opensm_dump_context *)cxt)->file;
+
+	fprintf(file, "MC Group 0x%04x %s:"
+		" mgid=0x%016" PRIx64 ":0x%016" PRIx64
+		" port_gid=0x%016" PRIx64 ":0x%016" PRIx64
+		" qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
+		" pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
+		" scope_state=0x%02x proxy_join=0x%x" "\n\n",
+		cl_ntoh16(p_mgrp->mlid),
+		p_mgrp->well_known ? " (well known)" : "",
+		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
+		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
+		cl_ntoh32(p_mgrp->mcmember_rec.qkey),
+		cl_ntoh16(p_mgrp->mcmember_rec.mlid),
+		p_mgrp->mcmember_rec.mtu,
+		p_mgrp->mcmember_rec.tclass,
+		cl_ntoh16(p_mgrp->mcmember_rec.pkey),
+		p_mgrp->mcmember_rec.rate,
+		p_mgrp->mcmember_rec.pkt_life,
+		cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
+		p_mgrp->mcmember_rec.scope_state,
+		p_mgrp->mcmember_rec.proxy_join);
+
+	dump_context.p_osm = p_osm;
+	dump_context.file = file;
+
+	cl_qmap_apply_func(&p_mgrp->mcm_port_tbl,
+			   mcast_mgr_dump_one_port, &dump_context);
+}
+
+static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt)
+{
+	FILE *file = ((struct opensm_dump_context *)cxt)->file;
+	osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
+	ib_inform_info_record_t *p_iir = &p_infr->inform_record;
+
+	fprintf(file, "InformInfo Record:"
+		" subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
+		" subscriber_enum=0x%x"
+		" InformInfo:"
+		" gid=0x%016" PRIx64 ":0x%016" PRIx64
+		" lid_range_begin=0x%x"
+		" lid_range_end=0x%x"
+		" is_generic=0x%x"
+		" subscribe=0x%x"
+		" trap_type=0x%x"
+		" trap_num=0x%x"
+		" qpn_resp_time_val=0x%x"
+		" node_type=0x%06x"
+		" rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
+		" remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x"
+		"\n\n",
+		cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
+		cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
+		cl_ntoh16(p_iir->subscriber_enum),
+		cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
+		cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
+		cl_ntoh16(p_iir->inform_info.lid_range_begin),
+		cl_ntoh16(p_iir->inform_info.lid_range_end),
+		p_iir->inform_info.is_generic,
+		p_iir->inform_info.subscribe,
+		cl_ntoh16(p_iir->inform_info.trap_type),
+		cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
+		cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
+		cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)),
+		cl_ntoh16(p_infr->report_addr.dest_lid),
+		p_infr->report_addr.path_bits,
+		p_infr->report_addr.static_rate,
+		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
+		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
+		p_infr->report_addr.addr_type.gsi.pkey_ix,
+		p_infr->report_addr.addr_type.gsi.service_level);
+}
+
+static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt)
+{
+	FILE *file = ((struct opensm_dump_context *)cxt)->file;
+	osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item;
+	ib_service_record_t *p_sr = &p_svcr->service_record;
+
+	fprintf(file, "Service Record: id=0x%016" PRIx64
+		" gid=0x%016" PRIx64 ":0x%016" PRIx64
+		" pkey=0x%x"
+		" lease=0x%x"
+		" key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
+		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
+		" name=\'%s\'"
+		" data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
+		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
+		" data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
+		" data32=0x%08x%08x:0x%08x%08x"
+		" data64=0x%016" PRIx64 ":0x%016" PRIx64
+		" modified_time=0x%x lease_period=0x%x\n\n",
+		cl_ntoh64(p_sr->service_id),
+		cl_ntoh64(p_sr->service_gid.unicast.prefix),
+		cl_ntoh64(p_sr->service_gid.unicast.interface_id),
+		cl_ntoh16(p_sr->service_pkey),
+		cl_ntoh32(p_sr->service_lease),
+		p_sr->service_key[0], p_sr->service_key[1],
+		p_sr->service_key[2], p_sr->service_key[3],
+		p_sr->service_key[4], p_sr->service_key[5],
+		p_sr->service_key[6], p_sr->service_key[7],
+		p_sr->service_key[8], p_sr->service_key[9],
+		p_sr->service_key[10], p_sr->service_key[11],
+		p_sr->service_key[12], p_sr->service_key[13],
+		p_sr->service_key[14], p_sr->service_key[15],
+		p_sr->service_name,
+		p_sr->service_data8[0], p_sr->service_data8[1],
+		p_sr->service_data8[2], p_sr->service_data8[3],
+		p_sr->service_data8[4], p_sr->service_data8[5],
+		p_sr->service_data8[6], p_sr->service_data8[7],
+		p_sr->service_data8[8], p_sr->service_data8[9],
+		p_sr->service_data8[10], p_sr->service_data8[11],
+		p_sr->service_data8[12], p_sr->service_data8[13],
+		p_sr->service_data8[14], p_sr->service_data8[15],
+		cl_ntoh16(p_sr->service_data16[0]),
+		cl_ntoh16(p_sr->service_data16[1]),
+		cl_ntoh16(p_sr->service_data16[2]),
+		cl_ntoh16(p_sr->service_data16[3]),
+		cl_ntoh16(p_sr->service_data16[4]),
+		cl_ntoh16(p_sr->service_data16[5]),
+		cl_ntoh16(p_sr->service_data16[6]),
+		cl_ntoh16(p_sr->service_data16[7]),
+		cl_ntoh32(p_sr->service_data32[0]),
+		cl_ntoh32(p_sr->service_data32[1]),
+		cl_ntoh32(p_sr->service_data32[2]),
+		cl_ntoh32(p_sr->service_data32[3]),
+		cl_ntoh64(p_sr->service_data64[0]),
+		cl_ntoh64(p_sr->service_data64[1]),
+		p_svcr->modified_time, p_svcr->lease_period);
+}
+
+static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
+{
+	struct opensm_dump_context dump_context;
+	osm_mgrp_t *p_mgrp;
+	int i;
+
+	dump_context.p_osm = p_osm;
+	dump_context.file = file;
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast:\n");
+	cl_plock_acquire(&p_osm->lock);
+	for (i = 0; i <= p_osm->subn.max_mcast_lid_ho - IB_LID_MCAST_START_HO;
+	     i++) {
+		p_mgrp = p_osm->subn.mgroups[i];
+		if (p_mgrp)
+			sa_dump_one_mgrp(p_mgrp, &dump_context);
+	}
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform:\n");
+	cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
+			    sa_dump_one_inform, &dump_context);
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services:\n");
+	cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
+			    sa_dump_one_service, &dump_context);
+	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
+ */
+static 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;
+	osm_mgrp_t *p_mgrp;
+
+	cl_plock_excl_acquire(&p_osm->lock);
+
+	p_mgrp = osm_get_mgrp_by_mlid(&p_osm->subn, mlid);
+	if (p_mgrp) {
+		if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
+			    sizeof(ib_gid_t))) {
+			OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+				"mgrp %04x is already here.", cl_ntoh16(mlid));
+			goto _out;
+		}
+		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+			"mlid %04x is already used by another MC group. Will "
+			"request clients reregistration.\n", cl_ntoh16(mlid));
+		p_mgrp = NULL;
+		goto _out;
+	}
+
+	comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
+	    | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
+	if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa,
+						 comp_mask, p_mcm_rec,
+						 &p_mgrp) != IB_SUCCESS ||
+	    !p_mgrp || p_mgrp->mlid != mlid) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
+			"cannot create MC group with mlid 0x%04x and mgid "
+			"0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid),
+			cl_ntoh64(p_mcm_rec->mgid.unicast.prefix),
+			cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id));
+		p_mgrp = NULL;
+	} 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,
+			"ServiceRecord already exists\n");
+		goto _out;
+	}
+
+	if (!(p_svcr = osm_svcr_new(sr))) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
+			"cannot allocate new service struct\n");
+		ret = -1;
+		goto _out;
+	}
+
+	p_svcr->modified_time = modified_time;
+	p_svcr->lease_period = lease_period;
+
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n");
+
+	osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr);
+
+	if (lease_period != 0xffffffff)
+		cl_timer_trim(&p_osm->sa.sr_timer, 1000);
+
+_out:
+	cl_plock_release(&p_osm->lock);
+
+	return ret;
+}
+
+static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir,
+		     osm_mad_addr_t * addr)
+{
+	osm_infr_t infr, *p_infr;
+	int ret = 0;
+
+	infr.h_bind = p_osm->sa.mad_ctrl.h_bind;
+	infr.sa = &p_osm->sa;
+	/* other possible way to restore mad_addr partially is
+	   to extract qpn from InformInfo and to find lid by gid */
+	infr.report_addr = *addr;
+	infr.inform_record = *iir;
+
+	cl_plock_excl_acquire(&p_osm->lock);
+	if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) {
+		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+			"InformInfo Record already exists\n");
+		goto _out;
+	}
+
+	if (!(p_infr = osm_infr_new(&infr))) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
+			"cannot allocate new infr struct\n");
+		ret = -1;
+		goto _out;
+	}
+
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n");
+
+	osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr);
+
+_out:
+	cl_plock_release(&p_osm->lock);
+
+	return ret;
+}
+
+#define UNPACK_FUNC(name,x) \
+static int unpack_##name##x(char *p, uint##x##_t *val_ptr) \
+{ \
+	char *q; \
+	unsigned long long num; \
+	num = strtoull(p, &q, 16); \
+	if (num > ~((uint##x##_t)0x0) \
+	    || q == p || (!isspace(*q) && *q != ':')) { \
+		*val_ptr = 0; \
+		return -1; \
+	} \
+	*val_ptr = cl_hton##x((uint##x##_t)num); \
+	return (int)(q - p); \
+}
+
+#define cl_hton8(x) (x)
+
+UNPACK_FUNC(net, 8);
+UNPACK_FUNC(net, 16);
+UNPACK_FUNC(net, 32);
+UNPACK_FUNC(net, 64);
+
+static int unpack_string(char *p, uint8_t * buf, unsigned len)
+{
+	char *q = p;
+	char delim = ' ';
+
+	if (*q == '\'' || *q == '\"')
+		delim = *q++;
+	while (--len && *q && *q != delim)
+		*buf++ = *q++;
+	*buf = '\0';
+	if (*q == delim && delim != ' ')
+		q++;
+	return (int)(q - p);
+}
+
+static int unpack_string64(char *p, uint8_t * buf)
+{
+	return unpack_string(p, buf, 64);
+}
+
+#define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \
+	p = strstr(p, name); \
+	if (!p) { \
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
+			"PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \
+			file_name, lineno, (name)); \
+		ret = -2; \
+		goto _error; \
+	} \
+	p += strlen(name); \
+	_ret = unpack_##x(p, (val_ptr)); \
+	if (_ret < 0) { \
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
+			"PARSE ERROR: %s:%u: cannot parse "#x" value " \
+			"after \"%s\"\n", file_name, lineno, (name)); \
+		ret = _ret; \
+		goto _error; \
+	} \
+	p += _ret; \
+}
+
+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,
+			"sa db file name is not specifed. Skip restore\n");
+		return 0;
+	}
+
+	file = fopen(file_name, "r");
+	if (!file) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: "
+			"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_osm->subn, &p_osm->log,
+						  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;
+			ib_net16_t val16;
+
+			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_ix=0x", &val16);
+			rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16);
+			PARSE_AHEAD(p, net8, " sl=0x",
+				    &rep_addr.addr_type.gsi.service_level);
+
+			if (load_infr(p_osm, &i_rec, &rep_addr))
+				rereg_clients = 1;
+		}
+	}
+
+	if (!rereg_clients)
+		p_osm->subn.opt.no_clients_rereg = TRUE;
+
+_error:
+	fclose(file);
+	return ret;
+}
diff --git a/opensm/osm_sa_class_port_info.c b/opensm/osm_sa_class_port_info.c
new file mode 100644
index 0000000..a3a2782
--- /dev/null
+++ b/opensm/osm_sa_class_port_info.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.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) */
+const static uint32_t __msecs_to_rtv_table[MAX_MSECS_TO_RTV] = {
+	1, 2, 4, 8,
+	16, 33, 67, 134,
+	268, 536, 1073, 2147,
+	4294, 8589, 17179, 34359,
+	68719, 137438, 274877, 549755,
+	1099511, 2199023, 4398046, 8796093
+};
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_cpi_rcv_respond(IN osm_sa_t * sa,
+		      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_gid_t zero_gid;
+	uint8_t rtv;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	memset(&zero_gid, 0, sizeof(ib_gid_t));
+
+	/*
+	   Get a MAD to reply. Address of Mad is in the received mad_wrapper
+	 */
+	p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, p_madw->h_bind,
+				       MAD_BLOCK_SIZE, &p_madw->mad_addr);
+	if (!p_resp_madw) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1408: "
+			"Unable to allocate MAD\n");
+		goto Exit;
+	}
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
+
+	memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE);
+	p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+	/* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+	p_resp_sa_mad->sm_key = 0;
+
+	p_resp_cpi =
+	    (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_mad);
+
+	/* finally do it (the job) man ! */
+	p_resp_cpi->base_ver = 1;
+	p_resp_cpi->class_ver = 2;
+	/* Calculate encoded response time value */
+	/* transaction timeout is in msec */
+	if (sa->p_subn->opt.transaction_timeout >
+	    __msecs_to_rtv_table[MAX_MSECS_TO_RTV - 1])
+		rtv = MAX_MSECS_TO_RTV - 1;
+	else {
+		for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) {
+			if (sa->p_subn->opt.transaction_timeout <=
+			    __msecs_to_rtv_table[rtv])
+				break;
+		}
+	}
+	rtv += 8;
+	ib_class_set_resp_time_val(p_resp_cpi, rtv);
+	p_resp_cpi->redir_gid = zero_gid;
+	p_resp_cpi->redir_tc_sl_fl = 0;
+	p_resp_cpi->redir_lid = 0;
+	p_resp_cpi->redir_pkey = 0;
+	p_resp_cpi->redir_qp = CL_NTOH32(1);
+	p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+	p_resp_cpi->trap_gid = zero_gid;
+	p_resp_cpi->trap_tc_sl_fl = 0;
+	p_resp_cpi->trap_lid = 0;
+	p_resp_cpi->trap_pkey = 0;
+	p_resp_cpi->trap_hop_qp = 0;
+	p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+
+	/* set specific capability mask bits */
+	/* we do not support the following options/optional records:
+	   OSM_CAP_IS_SUBN_OPT_RECS_SUP :
+	   RandomForwardingTableRecord,
+	   ServiceAssociationRecord
+	   other optional records supported "under the table"
+
+	   OSM_CAP_IS_MULTIPATH_SUP:
+	   TraceRecord
+
+	   OSM_CAP_IS_REINIT_SUP:
+	   For reinitialization functionality.
+
+	   So not sending traps, but supporting Get(Notice) and Set(Notice).
+	 */
+
+	/* Note host notation replaced later */
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
+	    OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED |
+	    OSM_CAP_IS_MULTIPATH_SUP;
+#else
+	p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
+	    OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED;
+#endif
+	if (sa->p_subn->opt.qos)
+		ib_class_set_cap_mask2(p_resp_cpi, OSM_CAP2_IS_QOS_SUPPORTED);
+
+	if (!sa->p_subn->opt.disable_multicast)
+		p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP;
+	p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask);
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES))
+		osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES);
+
+	osm_sa_send(sa, p_resp_madw, FALSE);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ * This code actually handles the call
+ **********************************************************************/
+void osm_cpi_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_sa_mad;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	/* we only support GET */
+	if (p_sa_mad->method != IB_MAD_METHOD_GET) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1403: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO);
+
+	/*
+	   CLASS PORT INFO does not really look on the SMDB - no lock required.
+	 */
+
+	__osm_cpi_rcv_respond(sa, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_guidinfo_record.c b/opensm/osm_sa_guidinfo_record.c
new file mode 100644
index 0000000..39dae72
--- /dev/null
+++ b/opensm/osm_sa_guidinfo_record.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_gir_rcv_t.
+ * This object represents the GUIDInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_gir_item {
+	cl_list_item_t list_item;
+	ib_guidinfo_record_t rec;
+} osm_gir_item_t;
+
+typedef struct osm_gir_search_ctxt {
+	const ib_guidinfo_record_t *p_rcvd_rec;
+	ib_net64_t comp_mask;
+	cl_qlist_t *p_list;
+	osm_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_gir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_gir_rcv_new_gir(IN osm_sa_t * sa,
+		      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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5102: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New GUIDInfoRecord: lid %u, block num %d\n",
+		cl_ntoh16(match_lid), block_num);
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_gir_create_gir(IN osm_sa_t * sa,
+			IN 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;
+	uint8_t block_num, start_block_num, end_block_num, num_blocks;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Looking for GUIDRecord with LID: %u GUID:0x%016"
+		PRIx64 "\n", cl_ntoh16(match_lid), cl_ntoh64(match_port_guid));
+
+	/*
+	   For switches, do not return the GUIDInfo record(s)
+	   for each port on the switch, just for port 0.
+	 */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
+		num_ports = 1;
+	else
+		num_ports = osm_node_get_num_physp(p_node);
+
+	for (port_num = 0; port_num < num_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		if (!p_physp)
+			continue;
+
+		/* Check to see if the found p_physp and the requester physp
+		   share a pkey. If not, continue */
+		if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp))
+			continue;
+
+		port_guid = osm_physp_get_port_guid(p_physp);
+
+		if (match_port_guid && (port_guid != match_port_guid))
+			continue;
+
+		/*
+		   Note: the following check is a temporary workaround
+		   Since 1. GUIDCap should never be 0 on ports where this applies
+		   and   2. GUIDCap should not be used on ports where it doesn't apply
+		   So this should really be a check for whether the port is a
+		   switch external port or not!
+		 */
+		if (p_physp->port_info.guid_cap == 0)
+			continue;
+
+		num_blocks = p_physp->port_info.guid_cap / 8;
+		if (p_physp->port_info.guid_cap % 8)
+			num_blocks++;
+		if (match_block_num == 255) {
+			start_block_num = 0;
+			end_block_num = num_blocks - 1;
+		} else {
+			if (match_block_num >= num_blocks)
+				continue;
+			end_block_num = start_block_num = match_block_num;
+		}
+
+		base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp));
+		match_lid_ho = cl_ntoh16(match_lid);
+		if (match_lid_ho) {
+			lmc = osm_physp_get_lmc(p_physp);
+			max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1);
+
+			/*
+			   We validate that the lid belongs to this node.
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Comparing LID: %u <= %u <= %u\n",
+				base_lid_ho, match_lid_ho, max_lid_ho);
+
+			if (match_lid_ho < base_lid_ho
+			    || match_lid_ho > max_lid_ho)
+				continue;
+		}
+
+		for (block_num = start_block_num; block_num <= end_block_num;
+		     block_num++)
+			__osm_gir_rcv_new_gir(sa, p_node, p_list, port_guid,
+					      cl_ntoh16(base_lid_ho), p_physp,
+					      block_num);
+
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__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;
+	osm_node_t *const p_node = (osm_node_t *) p_map_item;
+	const ib_guidinfo_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
+	osm_sa_t *sa = p_ctxt->sa;
+	const ib_guid_info_t *p_comp_gi;
+	ib_net64_t const comp_mask = p_ctxt->comp_mask;
+	ib_net64_t match_port_guid = 0;
+	ib_net16_t match_lid = 0;
+	uint8_t match_block_num = 255;
+
+	OSM_LOG_ENTER(p_ctxt->sa->p_log);
+
+	if (comp_mask & IB_GIR_COMPMASK_LID)
+		match_lid = p_rcvd_rec->lid;
+
+	if (comp_mask & IB_GIR_COMPMASK_BLOCKNUM)
+		match_block_num = p_rcvd_rec->block_num;
+
+	p_comp_gi = &p_rcvd_rec->guid_info;
+	/* Different rule for block 0 v. other blocks */
+	if (comp_mask & IB_GIR_COMPMASK_GID0) {
+		if (!p_rcvd_rec->block_num)
+			match_port_guid = osm_physp_get_port_guid(p_req_physp);
+		if (p_comp_gi->guid[0] != match_port_guid)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID1) {
+		if (p_comp_gi->guid[1] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID2) {
+		if (p_comp_gi->guid[2] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID3) {
+		if (p_comp_gi->guid[3] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID4) {
+		if (p_comp_gi->guid[4] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID5) {
+		if (p_comp_gi->guid[5] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID6) {
+		if (p_comp_gi->guid[6] != 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_GIR_COMPMASK_GID7) {
+		if (p_comp_gi->guid[7] != 0)
+			goto Exit;
+	}
+
+	__osm_sa_gir_create_gir(sa, p_node, p_ctxt->p_list,
+				match_port_guid, match_lid, p_req_physp,
+				match_block_num);
+
+Exit:
+	OSM_LOG_EXIT(p_ctxt->sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_gir_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_guidinfo_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_gir_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_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(sa->p_log, OSM_LOG_ERROR, "ERR 5105: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5104: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_guidinfo_record(sa->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.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	cl_qmap_apply_func(&sa->p_subn->node_guid_tbl,
+			   __osm_sa_gir_by_comp_mask_cb, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_guidinfo_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_informinfo.c b/opensm/osm_sa_informinfo.c
new file mode 100644
index 0000000..5863753
--- /dev/null
+++ b/opensm/osm_sa_informinfo.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_infr_rcv_t.
+ * This object represents the InformInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <arpa/inet.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_pkey.h>
+
+typedef struct osm_iir_item {
+	cl_list_item_t list_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_sa_t *sa;
+	osm_physp_t *p_req_physp;
+} osm_iir_search_ctxt_t;
+
+/**********************************************************************
+o13-14.1.1: Except for Set(InformInfo) requests with Inform-
+Info:LIDRangeBegin=0xFFFF, managers that support event forwarding
+shall, upon receiving a Set(InformInfo), verify that the requester
+originating the Set(InformInfo) and a Trap() source identified by Inform-
+can access each other - can use path record to verify that.
+**********************************************************************/
+static boolean_t
+__validate_ports_access_rights(IN osm_sa_t * sa,
+			       IN osm_infr_t * p_infr_rec)
+{
+	boolean_t valid = TRUE;
+	osm_physp_t *p_requester_physp;
+	osm_port_t *p_port;
+	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(sa->p_log);
+
+	/* get the requester physp from the request address */
+	p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						      &p_infr_rec->report_addr);
+
+	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(sa->p_subn, portguid);
+
+		if (p_port == NULL) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: "
+				"Invalid port guid: 0x%016" PRIx64 "\n",
+				cl_ntoh64(portguid));
+			valid = FALSE;
+			goto Exit;
+		}
+
+		/* get the destination InformInfo physical port */
+		p_physp = p_port->p_physp;
+
+		/* make sure that the requester and destination port can access each other
+		   according to the current partitioning. */
+		if (!osm_physp_share_pkey
+		    (sa->p_log, p_physp, p_requester_physp)) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"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 = &sa->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(sa->p_log, OSM_LOG_ERROR, "ERR 4302: "
+					"Given LID (%u) is out of range:%u\n",
+					lid, cl_ptr_vector_get_size(p_tbl));
+				valid = FALSE;
+				goto Exit;
+			}
+			if (p_port == NULL)
+				continue;
+
+			p_physp = p_port->p_physp;
+			/* make sure that the requester and destination port can access
+			   each other according to the current partitioning. */
+			if (!osm_physp_share_pkey
+			    (sa->p_log, p_physp, p_requester_physp)) {
+				OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+					"port and requester don't share pkey\n");
+				valid = FALSE;
+				goto Exit;
+			}
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__validate_infr(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec)
+{
+	boolean_t valid = TRUE;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	valid = __validate_ports_access_rights(sa, p_infr_rec);
+	if (!valid) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Invalid Access for InformInfo\n");
+		valid = FALSE;
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+	return valid;
+}
+
+/**********************************************************************
+o13-12.1.1: Confirm a valid request for event subscription by responding
+with an InformInfo attribute that is a copy of the data in the
+Set(InformInfo) request.
+**********************************************************************/
+static void
+__osm_infr_rcv_respond(IN osm_sa_t * sa,
+		       IN osm_madw_t * const p_madw)
+{
+	cl_qlist_t rec_list;
+	osm_iir_item_t *item;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Generating successful InformInfo response\n");
+
+	item = malloc(sizeof(*item));
+	if (!item) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4303: "
+			"rec_item alloc failed\n");
+		goto Exit;
+	}
+
+	memcpy(&item->rec,
+	       ib_sa_mad_get_payload_ptr(osm_madw_get_sa_mad_ptr(p_madw)),
+	       sizeof(item->rec));
+
+	cl_qlist_init(&rec_list);
+	cl_qlist_insert_tail(&rec_list, &item->list_item);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa,
+				      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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	p_req_physp = p_ctxt->p_req_physp;
+
+	if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID &&
+	    memcmp(&p_infr->inform_record.subscriber_gid,
+	    	   &p_ctxt->subscriber_gid,
+		   sizeof(p_infr->inform_record.subscriber_gid)))
+		goto Exit;
+
+	if (comp_mask & IB_IIR_COMPMASK_ENUM &&
+	    p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum)
+		goto Exit;
+
+	/* Implement any other needed search cases */
+
+	/* Ensure pkey is shared before returning any records */
+	portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id;
+	p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid);
+	if (p_subscriber_port == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: "
+			"Invalid subscriber port guid: 0x%016" PRIx64 "\n",
+			cl_ntoh64(portguid));
+		goto Exit;
+	}
+
+	/* get the subscriber InformInfo physical port */
+	p_subscriber_physp = p_subscriber_port->p_physp;
+	/* make sure that the requester and subscriber port can access each other
+	   according to the current partitioning. */
+	if (!osm_physp_share_pkey
+	    (sa->p_log, p_req_physp, p_subscriber_physp)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"requester and subscriber ports don't share pkey\n");
+		goto Exit;
+	}
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: "
+			"rec_item alloc 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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->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->sa, p_infr, p_ctxt);
+}
+
+/**********************************************************************
+Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_get_method(IN osm_sa_t * sa,
+				IN osm_madw_t * const p_madw)
+{
+	char gid_str[INET6_ADDRSTRLEN];
+	ib_sa_mad_t *p_rcvd_mad;
+	const ib_inform_info_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_iir_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+	osm_iir_item_t *item;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_inform_info_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4309: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_inform_info_record(sa->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.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Query Subscriber GID:%s(%02X) Enum:0x%X(%02X)\n",
+		inet_ntop(AF_INET6, p_rcvd_rec->subscriber_gid.raw,
+			gid_str, sizeof gid_str),
+		(p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0,
+		cl_ntoh16(p_rcvd_rec->subscriber_enum),
+		(p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0);
+
+	cl_plock_acquire(sa->p_lock);
+
+	cl_qlist_apply_func(&sa->p_subn->sa_infr_list,
+			    __osm_sa_inform_info_rec_by_comp_mask_cb, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	/* clear reserved and pad fields in InformInfoRecord */
+	for (item = (osm_iir_item_t *) cl_qlist_head(&rec_list);
+	     item != (osm_iir_item_t *) cl_qlist_end(&rec_list);
+	     item = (osm_iir_item_t *)cl_qlist_next(&item->list_item)) {
+		memset(item->rec.reserved, 0, sizeof(item->rec.reserved));
+		memset(item->rec.pad, 0, sizeof(item->rec.pad));
+	}
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/*********************************************************************
+Received a Set(InformInfo) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_set_method(IN osm_sa_t * sa,
+				IN 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(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_inform_info =
+	    (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+#if 0
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_inform_info(sa->p_log, p_recvd_inform_info,
+				     OSM_LOG_DEBUG);
+#endif
+
+	/* Grab the lock */
+	cl_plock_excl_acquire(sa->p_lock);
+
+	/* define the inform record */
+	inform_info_rec.inform_record.inform_info = *p_recvd_inform_info;
+
+	/* following C13-32.1.2 Tbl 120: we only copy the source address vector */
+	inform_info_rec.report_addr = p_madw->mad_addr;
+
+	/* we will need to know the mad srvc to send back through */
+	inform_info_rec.h_bind = p_madw->h_bind;
+	inform_info_rec.sa = sa;
+
+	/* update the subscriber GID according to mad address */
+	res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr,
+				      &inform_info_rec.inform_record.
+				      subscriber_gid);
+	if (res != IB_SUCCESS) {
+		cl_plock_release(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
+			"Subscribe Request from unknown LID: %u\n",
+			cl_ntoh16(p_madw->mad_addr.dest_lid));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* HACK: enum is always 0 (currently) */
+	inform_info_rec.inform_record.subscriber_enum = 0;
+
+	/* Subscribe values above 1 are undefined */
+	if (p_recvd_inform_info->subscribe > 1) {
+		cl_plock_release(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
+			"Invalid subscribe: %d\n",
+			p_recvd_inform_info->subscribe);
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/*
+	 * MODIFICATIONS DONE ON INCOMING REQUEST:
+	 *
+	 * QPN:
+	 * Internally we keep the QPN field of the InformInfo updated
+	 * so we can simply compare it in the record - when finding such.
+	 */
+	if (p_recvd_inform_info->subscribe) {
+		ib_inform_info_set_qpn(&inform_info_rec.inform_record.
+				       inform_info,
+				       inform_info_rec.report_addr.addr_type.
+				       gsi.remote_qp);
+
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Subscribe Request with QPN: 0x%06X\n",
+			cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.
+				  remote_qp));
+	} else {
+		ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v.
+						 generic.qpn_resp_time_val,
+						 &qpn, &resp_time_val);
+
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"UnSubscribe Request with QPN: 0x%06X\n",
+			cl_ntoh32(qpn));
+	}
+
+	/* If record exists with matching InformInfo */
+	p_infr =
+	    osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec);
+
+	/* check to see if the request was for subscribe */
+	if (p_recvd_inform_info->subscribe) {
+		/* validate the request for a new or update InformInfo */
+		if (__validate_infr(sa, &inform_info_rec) != TRUE) {
+			cl_plock_release(sa->p_lock);
+
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: "
+				"Failed to validate a new inform object\n");
+
+			/* o13-13.1.1: we need to set the subscribe bit to 0 */
+			p_recvd_inform_info->subscribe = 0;
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+
+		/* ok - we can try and create a new entry */
+		if (p_infr == NULL) {
+			/* Create the instance of the osm_infr_t object */
+			p_infr = osm_infr_new(&inform_info_rec);
+			if (p_infr == NULL) {
+				cl_plock_release(sa->p_lock);
+
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: "
+					"Failed to create a new inform object\n");
+
+				/* o13-13.1.1: we need to set the subscribe bit to 0 */
+				p_recvd_inform_info->subscribe = 0;
+				osm_sa_send_error(sa, p_madw,
+						  IB_SA_MAD_STATUS_NO_RESOURCES);
+				goto Exit;
+			}
+
+			/* Add this new osm_infr_t object to subnet object */
+			osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr);
+		} else
+			/* Update the old instance of the osm_infr_t object */
+			p_infr->inform_record = inform_info_rec.inform_record;
+	/* We got an UnSubscribe request */
+	} else if (p_infr == NULL) {
+		cl_plock_release(sa->p_lock);
+
+		/* No Such Item - So Error */
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: "
+			"Failed to UnSubscribe to non existing inform object\n");
+
+		/* o13-13.1.1: we need to set the subscribe bit to 0 */
+		p_recvd_inform_info->subscribe = 0;
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	} else
+		/* Delete this object from the subnet list of informs */
+		osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr);
+
+	cl_plock_release(sa->p_lock);
+
+	/* send the success response */
+	__osm_infr_rcv_respond(sa, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/*********************************************************************
+**********************************************************************/
+void osm_infr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	ib_sa_mad_t *p_sa_mad;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO);
+
+	if (p_sa_mad->method != IB_MAD_METHOD_SET) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	osm_infr_rcv_process_set_method(sa, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/*********************************************************************
+**********************************************************************/
+void osm_infir_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	ib_sa_mad_t *p_sa_mad;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD);
+
+	if (p_sa_mad->method != IB_MAD_METHOD_GET &&
+	    p_sa_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	osm_infr_rcv_process_get_method(sa, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_lft_record.c b/opensm/osm_sa_lft_record.c
new file mode 100644
index 0000000..d84a6a5
--- /dev/null
+++ b/opensm/osm_sa_lft_record.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_lftr_rcv_t.
+ *   This object represents the LinearForwardingTable Receiver object.
+ *   This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_lftr_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_lftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_lftr_rcv_new_lftr(IN osm_sa_t * sa,
+			IN const osm_switch_t * const p_sw,
+			IN cl_qlist_t * const p_list,
+			IN ib_net16_t const lid, IN uint16_t const block)
+{
+	osm_lftr_item_t *p_rec_item;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4402: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New LinearForwardingTable: sw 0x%016" PRIx64
+		"\n\t\t\t\tblock 0x%02X lid %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)),
+		block, cl_ntoh16(lid));
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	p_rec_item->rec.lid = lid;
+	p_rec_item->rec.block_num = cl_hton16(block);
+
+	/* copy the lft block */
+	osm_switch_get_lft_block(p_sw, block, p_rec_item->rec.lft);
+
+	cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_sa_t *sa = p_ctxt->sa;
+	ib_net64_t const comp_mask = p_ctxt->comp_mask;
+	const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
+	osm_port_t *p_port;
+	uint16_t min_lid_ho, max_lid_ho;
+	uint16_t min_block, max_block, block;
+	const osm_physp_t *p_physp;
+
+	/* In switches, the port guid is the node guid. */
+	p_port = osm_get_port_by_guid(sa->p_subn,
+				      p_sw->p_node->node_info.port_guid);
+	if (!p_port) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4405: "
+			"Failed to find Port by Node Guid:0x%016" PRIx64
+			"\n", cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		return;
+	}
+
+	/* check that the requester physp and the current physp are under
+	   the same partition. */
+	p_physp = p_port->p_physp;
+	if (!p_physp) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4406: "
+			"Failed to find default physical Port by Node Guid:0x%016"
+			PRIx64 "\n",
+			cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		return;
+	}
+	if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp))
+		return;
+
+	/* get the port 0 of the switch */
+	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+	/* compare the lids - if required */
+	if (comp_mask & IB_LFTR_COMPMASK_LID) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Comparing lid:%u to port lid range: %u .. %u\n",
+			cl_ntoh16(p_rcvd_rec->lid), min_lid_ho, max_lid_ho);
+		/* ok we are ready for range check */
+		if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) ||
+		    max_lid_ho < cl_ntoh16(p_rcvd_rec->lid))
+			return;
+	}
+
+	/* now we need to decide which blocks to output */
+	max_block = osm_switch_get_max_block_id_in_use(p_sw);
+	if (comp_mask & IB_LFTR_COMPMASK_BLOCK) {
+		min_block = cl_ntoh16(p_rcvd_rec->block_num);
+		if (min_block > max_block)
+			return;
+		max_block = min_block;
+	} else			/* use as many blocks as "in use" */
+		min_block = 0;
+
+	/* so we can add these blocks one by one ... */
+	for (block = min_block; block <= max_block; block++)
+		__osm_lftr_rcv_new_lftr(sa, p_sw, p_ctxt->p_list,
+					osm_port_get_base_lid(p_port), block);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_lftr_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_lft_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_lftr_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec = (ib_lft_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_LFT_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4408: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 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.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	/* Go over all switches */
+	cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl,
+			   __osm_lftr_rcv_by_comp_mask, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_lft_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_link_record.c b/opensm/osm_sa_link_record.c
new file mode 100644
index 0000000..b92845e
--- /dev/null
+++ b/opensm/osm_sa_link_record.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_lr_rcv_t.
+ * This object represents the LinkRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_lr_item {
+	cl_list_item_t list_item;
+	ib_link_record_t link_rec;
+} osm_lr_item_t;
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_build_physp_link(IN osm_sa_t * sa,
+			      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 = malloc(sizeof(*p_lr_item));
+	if (p_lr_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1801: "
+			"Unable to acquire link record\n"
+			"\t\t\t\tFrom port %u\n"
+			"\t\t\t\tTo port   %u\n"
+			"\t\t\t\tFrom lid  %u\n"
+			"\t\t\t\tTo lid    %u\n",
+			from_port, to_port,
+			cl_ntoh16(from_lid), cl_ntoh16(to_lid));
+		return;
+	}
+	memset(p_lr_item, 0, sizeof(*p_lr_item));
+
+	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, &p_lr_item->list_item);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_base_lid(IN const osm_physp_t * p_physp, OUT ib_net16_t * p_base_lid)
+{
+	if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+		*p_base_lid = osm_physp_get_base_lid
+			      (osm_node_get_physp_ptr(p_physp->p_node, 0));
+	else
+		*p_base_lid = osm_physp_get_base_lid(p_physp);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_physp_link(IN osm_sa_t * sa,
+			    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;
+	ib_net16_t to_base_lid;
+	ib_net16_t lmc_mask;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/*
+	   If only one end of the link is specified, determine
+	   the other side.
+	 */
+	if (p_src_physp) {
+		if (p_dest_physp) {
+			/*
+			   Ensure the two physp's are actually connected.
+			   If not, bail out.
+			 */
+			if (osm_physp_get_remote(p_src_physp) != p_dest_physp)
+				goto Exit;
+		} else {
+			p_dest_physp = osm_physp_get_remote(p_src_physp);
+			if (p_dest_physp == NULL)
+				goto Exit;
+		}
+	} else {
+		if (p_dest_physp) {
+			p_src_physp = osm_physp_get_remote(p_dest_physp);
+			if (p_src_physp == NULL)
+				goto Exit;
+		} else
+			goto Exit;	/* no physp's, so nothing to do */
+	}
+
+	/* Check that the p_src_physp, p_dest_physp and p_req_physp
+	   all share a pkey (doesn't have to be the same p_key). */
+	if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_dest_physp)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Source and Dest PhysPorts do not share PKey\n");
+		goto Exit;
+	}
+	if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_req_physp)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Source and Requester PhysPorts do not share PKey\n");
+		goto Exit;
+	}
+	if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_dest_physp)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Requester and Dest PhysPorts do not share PKey\n");
+		goto Exit;
+	}
+
+	src_port_num = osm_physp_get_port_num(p_src_physp);
+	dest_port_num = osm_physp_get_port_num(p_dest_physp);
+
+	if (comp_mask & IB_LR_COMPMASK_FROM_PORT)
+		if (src_port_num != p_lr->from_port_num)
+			goto Exit;
+
+	if (comp_mask & IB_LR_COMPMASK_TO_PORT)
+		if (dest_port_num != p_lr->to_port_num)
+			goto Exit;
+
+	__get_base_lid(p_src_physp, &from_base_lid);
+	__get_base_lid(p_dest_physp, &to_base_lid);
+
+	lmc_mask = ~((1 << sa->p_subn->opt.lmc) - 1);
+	lmc_mask = cl_hton16(lmc_mask);
+
+	if (comp_mask & IB_LR_COMPMASK_FROM_LID)
+		if (from_base_lid != (p_lr->from_lid & lmc_mask))
+			goto Exit;
+
+	if (comp_mask & IB_LR_COMPMASK_TO_LID)
+		if (to_base_lid != (p_lr->to_lid & lmc_mask))
+			goto Exit;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Acquiring link record\n"
+		"\t\t\t\tsrc port 0x%" PRIx64 " (port %u)"
+		", dest port 0x%" PRIx64 " (port %u)\n",
+		cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), src_port_num,
+		cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)),
+		dest_port_num);
+
+
+	__osm_lr_rcv_build_physp_link(sa, from_base_lid, to_base_lid,
+				      src_port_num, dest_port_num, p_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_port_links(IN osm_sa_t * sa,
+			    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_node_tbl;
+	osm_node_t * p_node;
+	uint8_t port_num;
+	uint8_t num_ports;
+	uint8_t dest_num_ports;
+	uint8_t dest_port_num;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	if (p_src_port) {
+		if (p_dest_port) {
+			/*
+			   Build an LR for every link connected between both ports.
+			   The inner function will discard physp combinations
+			   that do not actually connect.  Don't bother screening
+			   for that here.
+			 */
+			num_ports = osm_node_get_num_physp(p_src_port->p_node);
+			dest_num_ports =
+			    osm_node_get_num_physp(p_dest_port->p_node);
+			for (port_num = 1; port_num < num_ports; port_num++) {
+				p_src_physp =
+				    osm_node_get_physp_ptr(p_src_port->p_node,
+							   port_num);
+				for (dest_port_num = 1;
+				     dest_port_num < dest_num_ports;
+				     dest_port_num++) {
+					p_dest_physp =
+					    osm_node_get_physp_ptr(p_dest_port->
+								   p_node,
+								   dest_port_num);
+					/* both physical ports should be with data */
+					if (p_src_physp && p_dest_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, p_src_physp,
+						     p_dest_physp, comp_mask,
+						     p_list, p_req_physp);
+				}
+			}
+		} else {
+			/*
+			   Build an LR for every link connected from the source port.
+			 */
+			if (comp_mask & IB_LR_COMPMASK_FROM_PORT) {
+				port_num = p_lr->from_port_num;
+				/* If the port number is out of the range of the p_src_port, then
+				   this couldn't be a relevant record. */
+				if (port_num <
+				    p_src_port->p_node->physp_tbl_size) {
+					p_src_physp =
+					    osm_node_get_physp_ptr(p_src_port->
+								   p_node,
+								   port_num);
+					if (p_src_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, p_src_physp,
+						     NULL, comp_mask, p_list,
+						     p_req_physp);
+				}
+			} else {
+				num_ports =
+				    osm_node_get_num_physp(p_src_port->p_node);
+				for (port_num = 1; port_num < num_ports;
+				     port_num++) {
+					p_src_physp =
+					    osm_node_get_physp_ptr(p_src_port->
+								   p_node,
+								   port_num);
+					if (p_src_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, p_src_physp,
+						     NULL, comp_mask, p_list,
+						     p_req_physp);
+				}
+			}
+		}
+	} else {
+		if (p_dest_port) {
+			/*
+			   Build an LR for every link connected to the dest port.
+			 */
+			if (comp_mask & IB_LR_COMPMASK_TO_PORT) {
+				port_num = p_lr->to_port_num;
+				/* If the port number is out of the range of the p_dest_port, then
+				   this couldn't be a relevant record. */
+				if (port_num <
+				    p_dest_port->p_node->physp_tbl_size) {
+					p_dest_physp =
+					    osm_node_get_physp_ptr(p_dest_port->
+								   p_node,
+								   port_num);
+					if (p_dest_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, NULL,
+						     p_dest_physp, comp_mask,
+						     p_list, p_req_physp);
+				}
+			} else {
+				num_ports =
+				    osm_node_get_num_physp(p_dest_port->p_node);
+				for (port_num = 1; port_num < num_ports;
+				     port_num++) {
+					p_dest_physp =
+					    osm_node_get_physp_ptr(p_dest_port->
+								   p_node,
+								   port_num);
+					if (p_dest_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, NULL,
+						     p_dest_physp, comp_mask,
+						     p_list, p_req_physp);
+				}
+			}
+		} else {
+			/*
+			   Process the world (recurse once back into this function).
+			 */
+			p_node_tbl = &sa->p_subn->node_guid_tbl;
+			p_node = (osm_node_t *)cl_qmap_head(p_node_tbl);
+
+			while (p_node != (osm_node_t *)cl_qmap_end(p_node_tbl)) {
+				num_ports = osm_node_get_num_physp(p_node);
+				for (port_num = 1; port_num < num_ports;
+				     port_num++) {
+					p_src_physp =
+					    osm_node_get_physp_ptr(p_node,
+								   port_num);
+					if (p_src_physp)
+						__osm_lr_rcv_get_physp_link
+						    (sa, p_lr, p_src_physp,
+						     NULL, comp_mask, p_list,
+						     p_req_physp);
+				}
+				p_node = (osm_node_t *) cl_qmap_next(&p_node->
+								     map_item);
+			}
+		}
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ Returns the SA status to return to the client.
+ **********************************************************************/
+static ib_net16_t
+__osm_lr_rcv_get_end_points(IN osm_sa_t * sa,
+			    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(sa->p_log);
+
+	/*
+	   Determine what fields are valid and then get a pointer
+	   to the source and destination port objects, if possible.
+	 */
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_lr = (ib_link_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+	*pp_src_port = NULL;
+	*pp_dest_port = NULL;
+
+	if (p_sa_mad->comp_mask & IB_LR_COMPMASK_FROM_LID) {
+		status = osm_get_port_by_base_lid(sa->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(sa->p_log, OSM_LOG_VERBOSE,
+				"No source port with LID %u\n",
+				cl_ntoh16(p_lr->from_lid));
+
+			sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+			goto Exit;
+		}
+	}
+
+	if (p_sa_mad->comp_mask & IB_LR_COMPMASK_TO_LID) {
+		status = osm_get_port_by_base_lid(sa->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(sa->p_log, OSM_LOG_VERBOSE,
+				"No dest port with LID %u\n",
+				cl_ntoh16(p_lr->to_lid));
+
+			sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+			goto Exit;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (sa_status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_lr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	const ib_link_record_t *p_lr;
+	const ib_sa_mad_t *p_sa_mad;
+	const osm_port_t *p_src_port;
+	const osm_port_t *p_dest_port;
+	cl_qlist_t lr_list;
+	ib_net16_t sa_status;
+	osm_physp_t *p_req_physp;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_lr = (ib_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(sa->p_log, OSM_LOG_ERROR, "ERR 1804: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1805: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_link_record(sa->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(sa->p_lock);
+
+	sa_status = __osm_lr_rcv_get_end_points(sa, p_madw,
+						&p_src_port, &p_dest_port);
+
+	if (sa_status == IB_SA_MAD_STATUS_SUCCESS)
+		__osm_lr_rcv_get_port_links(sa, p_lr, p_src_port,
+					    p_dest_port, p_sa_mad->comp_mask,
+					    &lr_list, p_req_physp);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_link_record_t), &lr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_mad_ctrl.c b/opensm/osm_sa_mad_ctrl.c
new file mode 100644
index 0000000..49309f9
--- /dev/null
+++ b/opensm/osm_sa_mad_ctrl.c
@@ -0,0 +1,592 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_mad_ctrl_t.
+ * This object is part of the SA object.
+ */
+
+#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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.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);
+
+	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);
+
+	/*
+	   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,
+			/*             "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, "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,
+			"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, "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.
+		 */
+		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__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);
+
+	CL_ASSERT(p_madw);
+
+	/*
+	   A MAD was received from the wire, possibly in response to a request.
+	 */
+	cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd);
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+		"%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd);
+
+	/*
+	 * C15-0.1.3 requires not responding to any MAD if the SM is
+	 * not in active state!
+	 * We will not respond if the sm_state is not MASTER, or if the
+	 * first_time_master_sweep flag (of the subnet) is TRUE - this
+	 * flag indicates that the master still didn't finish its first
+	 * sweep, so the subnet is not up and stable yet.
+	 */
+	if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
+		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
+			"Received SA MAD while SM not MASTER. MAD ignored\n");
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+		goto Exit;
+	}
+	if (p_ctrl->p_subn->first_time_master_sweep == TRUE) {
+		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
+			"Received SA MAD while SM in first sweep. MAD ignored\n");
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+		goto Exit;
+	}
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	if (osm_log_is_active(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.sa_key)) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "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.sa_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,
+			"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:
+		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: "
+			"Unsupported method = 0x%X\n", p_sa_mad->method);
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__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
+ */
+static 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_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "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) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+			"Posting Dispatcher message %s\n",
+			osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
+
+		status = cl_disp_post(p_ctrl->h_disp,
+				      osm_madw_get_err_msg(p_madw),
+				      p_madw,
+				      __osm_sa_mad_ctrl_disp_done_callback,
+				      p_ctrl);
+		if (status != CL_SUCCESS) {
+			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: "
+				"Dispatcher post message failed (%s)\n",
+				CL_STATUS_MSG(status));
+		}
+	} else {
+		/*
+		   No error message was provided, just retire the MAD.
+		 */
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+	}
+
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * 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_t * sa,
+		     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_construct(p_ctrl);
+
+	p_ctrl->sa = sa;
+	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->h_disp = cl_disp_register(p_disp,
+					  CL_DISP_MSGID_NONE, NULL, p_ctrl);
+
+	if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: "
+			"Dispatcher registration failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+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);
+
+	if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A09: "
+			"Multiple binds not allowed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	bind_info.class_version = 2;
+	bind_info.is_responder = TRUE;
+	bind_info.is_report_processor = FALSE;
+	bind_info.is_trap_processor = FALSE;
+	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+	bind_info.port_guid = port_guid;
+	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
+	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
+		"Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor,
+					 &bind_info,
+					 p_ctrl->p_mad_pool,
+					 __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, "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);
+
+	if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A11: "
+			"No previous bind\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	osm_vendor_unbind(p_ctrl->h_bind);
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+	return (status);
+}
diff --git a/opensm/osm_sa_mcmember_record.c b/opensm/osm_sa_mcmember_record.c
new file mode 100644
index 0000000..99aee1b
--- /dev/null
+++ b/opensm/osm_sa_mcmember_record.c
@@ -0,0 +1,1739 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcmr_recv_t.
+ * This object represents the MCMemberRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.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 <vendor/osm_vendor_api.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_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_sa.h>
+
+#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)
+
+typedef struct osm_mcmr_item {
+	cl_list_item_t list_item;
+	ib_member_rec_t rec;
+} osm_mcmr_item_t;
+
+/*********************************************************************
+ 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 mlid to the pool of free mlids.
+ But this implementation is not a pool - it simply scans through
+ the MGRP database for unused mlids...
+*********************************************************************/
+static void __free_mlid(IN osm_sa_t * sa, IN uint16_t mlid)
+{
+	UNUSED_PARAM(sa);
+	UNUSED_PARAM(mlid);
+}
+
+/*********************************************************************
+ Get a new unused mlid by scanning all the used ones in the subnet.
+**********************************************************************/
+static ib_net16_t __get_new_mlid(osm_sa_t *sa, ib_net16_t requested_mlid)
+{
+	osm_subn_t *p_subn = sa->p_subn;
+	unsigned i, max;
+
+	if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO
+	    && cl_ntoh16(requested_mlid) <= p_subn->max_mcast_lid_ho
+	    && !osm_get_mgrp_by_mlid(p_subn, requested_mlid))
+		return requested_mlid;
+
+	max = p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO + 1;
+	for (i = 0; i < max; i++) {
+		osm_mgrp_t *p_mgrp = sa->p_subn->mgroups[i];
+		if (!p_mgrp || p_mgrp->to_be_deleted)
+			return cl_hton16(i + IB_LID_MCAST_START_HO);
+	}
+
+	return 0;
+}
+
+/*********************************************************************
+ 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_sa_t * sa, IN ib_net16_t const mlid)
+{
+	osm_mgrp_t *p_mgrp = osm_get_mgrp_by_mlid(sa->p_subn, mlid);
+
+	/* Remove MGRP only if osm_mcm_port_t count is 0 and
+	   not a well known group */
+	if (p_mgrp && cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) &&
+	    p_mgrp->well_known == FALSE) {
+		sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = NULL;
+		osm_mgrp_delete(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_sa_t * sa,
+		    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(sa->p_log, sa->p_subn,
+				      p_mad_addr, &requester_gid);
+	if (res != IB_SUCCESS) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "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(sa->p_log, OSM_LOG_DEBUG,
+			"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(sa->p_log, OSM_LOG_DEBUG,
+			"Create new port with proxy_join TRUE\n");
+	}
+
+	*pp_mcmr_port = osm_mgrp_add_port(sa->p_subn, sa->p_log, p_mgrp,
+					  &p_recvd_mcmember_rec->port_gid,
+					  p_recvd_mcmember_rec->scope_state,
+					  proxy_join);
+	if (*pp_mcmr_port == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "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 osm_sa_t * sa,
+		       IN osm_madw_t * const p_madw,
+		       IN ib_member_rec_t * p_mcmember_rec)
+{
+	cl_qlist_t rec_list;
+	osm_mcmr_item_t *item;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	item = malloc(sizeof(*item));
+	if (!item) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B16: "
+			"rec_item alloc failed\n");
+		goto Exit;
+	}
+
+	item->rec = *p_mcmember_rec;
+
+	/* Fill in the mtu, rate, and packet lifetime selectors */
+	item->rec.mtu &= 0x3f;
+	item->rec.mtu |= 2 << 6;	/* exactly */
+	item->rec.rate &= 0x3f;
+	item->rec.rate |= 2 << 6;	/* exactly */
+	item->rec.pkt_life &= 0x3f;
+	item->rec.pkt_life |= 2 << 6;	/* exactly */
+
+	cl_qlist_init(&rec_list);
+	cl_qlist_insert_tail(&rec_list, &item->list_item);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_member_rec_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/*********************************************************************
+ In joining an existing group, or when querying the mc groups,
+ we make sure the following components provided match: MTU and RATE
+ HACK: Currently we ignore the PKT_LIFETIME field.
+**********************************************************************/
+static boolean_t
+__validate_more_comp_fields(osm_log_t * p_log,
+			    const osm_mgrp_t * p_mgrp,
+			    const ib_member_rec_t * p_recvd_mcmember_rec,
+			    ib_net64_t comp_mask)
+{
+	uint8_t mtu_sel;
+	uint8_t mtu_required;
+	uint8_t mtu_mgrp;
+	uint8_t rate_sel;
+	uint8_t rate_required;
+	uint8_t rate_mgrp;
+
+	if (comp_mask & IB_MCR_COMPMASK_MTU_SEL) {
+		mtu_sel = (uint8_t) (p_recvd_mcmember_rec->mtu >> 6);
+		/* Clearing last 2 bits */
+		mtu_required = (uint8_t) (p_recvd_mcmember_rec->mtu & 0x3F);
+		mtu_mgrp = (uint8_t) (p_mgrp->mcmember_rec.mtu & 0x3F);
+		switch (mtu_sel) {
+		case 0:	/* Greater than MTU specified */
+			if (mtu_mgrp <= mtu_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has MTU %x, "
+					"which is not greater than %x\n",
+					mtu_mgrp, mtu_required);
+				return FALSE;
+			}
+			break;
+		case 1:	/* Less than MTU specified */
+			if (mtu_mgrp >= mtu_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has MTU %x, "
+					"which is not less than %x\n",
+					mtu_mgrp, mtu_required);
+				return FALSE;
+			}
+			break;
+		case 2:	/* Exactly MTU specified */
+			if (mtu_mgrp != mtu_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has MTU %x, "
+					"which is not equal to %x\n",
+					mtu_mgrp, mtu_required);
+				return FALSE;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* what about rate ? */
+	if (comp_mask & IB_MCR_COMPMASK_RATE_SEL) {
+		rate_sel = (uint8_t) (p_recvd_mcmember_rec->rate >> 6);
+		/* Clearing last 2 bits */
+		rate_required = (uint8_t) (p_recvd_mcmember_rec->rate & 0x3F);
+		rate_mgrp = (uint8_t) (p_mgrp->mcmember_rec.rate & 0x3F);
+		switch (rate_sel) {
+		case 0:	/* Greater than RATE specified */
+			if (rate_mgrp <= rate_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has RATE %x, "
+					"which is not greater than %x\n",
+					rate_mgrp, rate_required);
+				return FALSE;
+			}
+			break;
+		case 1:	/* Less than RATE specified */
+			if (rate_mgrp >= rate_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has RATE %x, "
+					"which is not less than %x\n",
+					rate_mgrp, rate_required);
+				return FALSE;
+			}
+			break;
+		case 2:	/* Exactly RATE specified */
+			if (rate_mgrp != rate_required) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested mcast group has RATE %x, "
+					"which is not equal to %x\n",
+					rate_mgrp, rate_required);
+				return FALSE;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return TRUE;
+}
+
+/*********************************************************************
+ In joining an existing group, we make sure the following components
+ are physically realizable: MTU and RATE
+**********************************************************************/
+static boolean_t
+__validate_port_caps(osm_log_t * const p_log,
+		     const osm_mgrp_t * p_mgrp, const osm_physp_t * p_physp)
+{
+	uint8_t mtu_required;
+	uint8_t mtu_mgrp;
+	uint8_t rate_required;
+	uint8_t rate_mgrp;
+
+	mtu_required = ib_port_info_get_mtu_cap(&p_physp->port_info);
+	mtu_mgrp = (uint8_t) (p_mgrp->mcmember_rec.mtu & 0x3F);
+	if (mtu_required < mtu_mgrp) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Port's MTU %x is less than %x\n",
+			mtu_required, mtu_mgrp);
+		return FALSE;
+	}
+
+	rate_required = ib_port_info_compute_rate(&p_physp->port_info);
+	rate_mgrp = (uint8_t) (p_mgrp->mcmember_rec.rate & 0x3F);
+	if (rate_required < rate_mgrp) {
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Port's RATE %x is less than %x\n",
+			rate_required, rate_mgrp);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**********************************************************************
+ * o15-0.2.1: If SA supports UD multicast, then if SA receives a SubnAdmSet()
+ * or SubnAdmDelete() method that would modify an existing
+ * MCMemberRecord, SA shall not modify that MCMemberRecord and shall
+ * return an error status of ERR_REQ_INVALID in response in the
+ * following cases:
+ * 1. Saved MCMemberRecord.ProxyJoin is not set and the request is
+ * issued by a requester with a GID other than the Port-GID.
+ * 2. Saved MCMemberRecord.ProxyJoin is set and the requester is not
+ * part of the partition for that MCMemberRecord.
+ **********************************************************************/
+static boolean_t
+__validate_modify(IN osm_sa_t * sa,
+		  IN osm_mgrp_t * p_mgrp,
+		  IN osm_mad_addr_t * p_mad_addr,
+		  IN ib_member_rec_t * p_recvd_mcmember_rec,
+		  OUT osm_mcm_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(sa->p_log, OSM_LOG_DEBUG,
+			"This is a new port in the MC group\n");
+		return TRUE;
+	}
+
+	/* We validate the request according the the proxy_join.
+	   Check if the proxy_join is set or not */
+	if ((*pp_mcm_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(sa->p_log,
+					      sa->p_subn,
+					      p_mad_addr, &request_gid);
+
+		if (res != IB_SUCCESS) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Could not find port for requested address\n");
+			return FALSE;
+		}
+
+		if (memcmp(&((*pp_mcm_port)->port_gid), &request_gid,
+			   sizeof(ib_gid_t))) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"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(sa->p_log,
+							    sa->p_subn,
+							    p_mad_addr);
+		if (p_request_physp == NULL)
+			return FALSE;
+
+		if (!osm_physp_has_pkey(sa->p_log, p_mgrp->mcmember_rec.pkey,
+					p_request_physp)) {
+			/* the request port is not part of the partition for this mgrp */
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"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_sa_t * sa,
+		  IN osm_mgrp_t * p_mgrp,
+		  IN osm_mad_addr_t * p_mad_addr,
+		  IN ib_member_rec_t * p_recvd_mcmember_rec,
+		  OUT osm_mcm_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(sa->p_log, OSM_LOG_DEBUG,
+			"Failed to find the port in the MC group\n");
+		return FALSE;
+	}
+
+	/* 2 */
+	if (!(p_recvd_mcmember_rec->scope_state & 0x0F &
+	      (*pp_mcm_port)->scope_state)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Could not find any matching bits in the stored "
+			"and requested JoinStates\n");
+		return FALSE;
+	}
+
+	/* 3 */
+	if (((p_recvd_mcmember_rec->scope_state & 0x0F) |
+	     (0x0F & (*pp_mcm_port)->scope_state)) !=
+	    (0x0F & (*pp_mcm_port)->scope_state)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Some bits in the request JoinState (0x%X) are not "
+			"set in the stored port (0x%X)\n",
+			(p_recvd_mcmember_rec->scope_state & 0x0F),
+			(0x0F & (*pp_mcm_port)->scope_state));
+		return FALSE;
+	}
+
+	/* 4 */
+	/* Validate according the the proxy_join (o15-0.1.2) */
+	if (__validate_modify(sa, p_mgrp, p_mad_addr, p_recvd_mcmember_rec,
+			      pp_mcm_port) == FALSE) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"proxy_join validation failure\n");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Check legality of the requested MGID (note this does not hold for SA
+ * created MGIDs)
+ *
+ * Implementing o15-0.1.5:
+ * A multicast GID is considered to be invalid if:
+ * 1. It does not comply with the rules as specified in 4.1.1 "GID Usage and
+ *    Properties" on page 145:
+ *
+ * 14) The multicast GID format is (bytes are comma sep):
+ *     0xff,<Fl><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)
+ */
+static ib_api_status_t
+__validate_requested_mgid(IN osm_sa_t * sa,
+			  IN const ib_member_rec_t * p_mcm_rec)
+{
+	uint16_t signature;
+	boolean_t valid = TRUE;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/* 14-a: mcast GID must start with 0xFF */
+	if (p_mcm_rec->mgid.multicast.header[0] != 0xFF) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B01: "
+			"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(sa->p_log, OSM_LOG_DEBUG,
+		"MGID Signed as 0x%04X\n", signature);
+
+	/*
+	 * We skip any checks for MGIDs that follow IPoIB
+	 * GID structure as defined by the IETF ipoib-link-multicast.
+	 *
+	 * For IPv4 over IB, the signature will be "0x401B".
+	 *
+	 * |   8    |  4 |  4 |     16 bits     | 16 bits | 48 bits  | 32 bits |
+	 * +--------+----+----+-----------------+---------+----------+---------+
+	 * |11111111|0001|scop|<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(sa->p_log, OSM_LOG_DEBUG,
+			"Skipping MGID Validation for IPoIB Signed (0x%04X) MGIDs\n",
+			signature);
+		goto Exit;
+	}
+
+	/* 14-b: the 3 upper bits in the "flags" should be zero: */
+	if (p_mcm_rec->mgid.multicast.header[1] & 0xE0) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B28: "
+			"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) ==
+	     IB_MC_SCOPE_LINK_LOCAL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "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(sa->p_log);
+	return (valid);
+}
+
+/**********************************************************************
+ Check if the requested new MC group parameters are realizable.
+ Also set the default MTU and Rate if not provided by the user.
+**********************************************************************/
+static boolean_t
+__mgrp_request_is_realizable(IN osm_sa_t * sa,
+			     IN ib_net64_t comp_mask,
+			     IN ib_member_rec_t * p_mcm_rec,
+			     IN const osm_physp_t * 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 = sa->p_log;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/*
+	 * End of o15-0.2.3 specifies:
+	 * ....
+	 * The entity may also supply the other components such as HopLimit,
+	 * MTU, etc. during group creation time. If these components are not
+	 * provided during group creation time, SA will provide them for the
+	 * group. The values chosen are vendor-dependent and beyond the scope
+	 * of the specification.
+	 *
+	 * so we might also need to assign RATE/MTU if they are not comp
+	 * masked in.
+	 */
+
+	port_mtu = p_physp ? ib_port_info_get_mtu_cap(&p_physp->port_info) : 0;
+	if (!(comp_mask & IB_MCR_COMPMASK_MTU) ||
+	    !(comp_mask & IB_MCR_COMPMASK_MTU_SEL) ||
+	    (mtu_sel = (p_mcm_rec->mtu >> 6)) == 3)
+		mtu = port_mtu ? port_mtu : sa->p_subn->min_ca_mtu;
+	else {
+		mtu_required = (uint8_t) (p_mcm_rec->mtu & 0x3F);
+		mtu = mtu_required;
+		switch (mtu_sel) {
+		case 0:	/* Greater than MTU specified */
+			if (port_mtu && mtu_required >= port_mtu) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Requested MTU %x >= the port\'s mtu:%x\n",
+					mtu_required, port_mtu);
+				return FALSE;
+			}
+			/* we provide the largest MTU possible if we can */
+			if (port_mtu)
+				mtu = port_mtu;
+			else if (mtu_required < sa->p_subn->min_ca_mtu)
+				mtu = sa->p_subn->min_ca_mtu;
+			else
+				mtu++;
+			break;
+		case 1:	/* Less than MTU specified */
+			/* use the smaller of the two:
+			   a. one lower then the required
+			   b. the mtu of the requesting port (if exists) */
+			if (port_mtu && mtu_required > port_mtu)
+				mtu = port_mtu;
+			else
+				mtu--;
+			break;
+		case 2:	/* Exactly MTU specified */
+		default:
+			break;
+		}
+		/* make sure it still be in the range */
+		if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU) {
+			OSM_LOG(p_log, OSM_LOG_DEBUG,
+				"Calculated MTU %x is out of range\n", mtu);
+			return FALSE;
+		}
+	}
+	p_mcm_rec->mtu = (mtu_sel << 6) | mtu;
+
+	port_rate =
+	    p_physp ? ib_port_info_compute_rate(&p_physp->port_info) : 0;
+	if (!(comp_mask & IB_MCR_COMPMASK_RATE)
+	    || !(comp_mask & IB_MCR_COMPMASK_RATE_SEL)
+	    || (rate_sel = (p_mcm_rec->rate >> 6)) == 3)
+		rate = port_rate ? port_rate : sa->p_subn->min_ca_rate;
+	else {
+		rate_required = (uint8_t) (p_mcm_rec->rate & 0x3F);
+		rate = rate_required;
+		switch (rate_sel) {
+		case 0:	/* Greater than RATE specified */
+			if (port_rate && rate_required >= port_rate) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"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 < sa->p_subn->min_ca_rate)
+				rate = sa->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,
+				"Calculated RATE %x is out of range\n", rate);
+			return FALSE;
+		}
+	}
+	p_mcm_rec->rate = (rate_sel << 6) | rate;
+
+	OSM_LOG_EXIT(sa->p_log);
+	return TRUE;
+}
+
+/**********************************************************************
+ Call this function to create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa,
+			     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;
+	unsigned zero_mgid, i;
+	uint8_t scope;
+	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(sa->p_log);
+
+	/* 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(sa, mcm_rec.mlid);
+	if (mlid == 0) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B19: "
+			"__get_new_mlid failed request mlid 0x%04x\n", cl_ntoh16(mcm_rec.mlid));
+		status = IB_SA_MAD_STATUS_NO_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Obtained new mlid 0x%X\n", cl_ntoh16(mlid));
+
+	/* we need to create the new MGID if it was not defined */
+	if (zero_mgid) {
+		/* create a new MGID */
+		char gid_str[INET6_ADDRSTRLEN];
+
+		/* 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 = IB_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]),
+		       &sa->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(sa->p_log, OSM_LOG_DEBUG, "Allocated new MGID:%s\n",
+			inet_ntop(AF_INET6, p_mgid->raw, gid_str,
+				  sizeof gid_str));
+	} else if (!__validate_requested_mgid(sa, &mcm_rec)) {
+		/* a specific MGID was requested so validate the resulting MGID */
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B22: "
+			"Invalid requested MGID\n");
+		__free_mlid(sa, mlid);
+		status = IB_SA_MAD_STATUS_REQ_INVALID;
+		goto Exit;
+	}
+
+	/* check the requested parameters are realizable */
+	if (__mgrp_request_is_realizable(sa, comp_mask, &mcm_rec, p_physp) ==
+	    FALSE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B26: "
+			"Requested MGRP parameters are not realizable\n");
+		__free_mlid(sa, 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(sa->p_log, OSM_LOG_ERROR, "ERR 1B08: "
+			"osm_mgrp_new failed\n");
+		__free_mlid(sa, mlid);
+		status = IB_SA_MAD_STATUS_NO_RESOURCES;
+		goto Exit;
+	}
+
+	/* 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_get_mgrp_by_mlid(sa->p_subn, mlid);
+	if (p_prev_mgrp) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Found previous group for mlid:0x%04x - "
+			"Destroying it first\n",
+			cl_ntoh16(mlid));
+		sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = NULL;
+		osm_mgrp_delete(p_prev_mgrp);
+	}
+
+	sa->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = *pp_mgrp;
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+static unsigned match_mgrp_by_mgid(IN osm_mgrp_t * const p_mgrp, ib_gid_t *mgid)
+{
+	/* ignore groups marked for deletion */
+	if (p_mgrp->to_be_deleted ||
+	    memcmp(&p_mgrp->mcmember_rec.mgid, mgid, sizeof(ib_gid_t)))
+		return 0;
+	else
+		return 1;
+}
+
+/**********************************************************************
+ **********************************************************************/
+#define PREFIX_MASK CL_HTON64(0xff10ffff0000ffffULL)
+#define PREFIX_SIGNATURE CL_HTON64(0xff10601b00000000ULL)
+#define INT_ID_MASK CL_HTON64(0xfffffff1ff000000ULL)
+#define INT_ID_SIGNATURE CL_HTON64(0x00000001ff000000ULL)
+
+/* Special Case IPv6 Solicited Node Multicast (SNM) addresses */
+/* 0xff1Z601bXXXX0000 : 0x00000001ffYYYYYY */
+/* Where Z is the scope, XXXX is the P_Key, and
+ * YYYYYY is the last 24 bits of the port guid */
+static unsigned match_and_update_ipv6_snm_mgid(ib_gid_t *mgid)
+{
+	if ((mgid->unicast.prefix & PREFIX_MASK) == PREFIX_SIGNATURE &&
+	    (mgid->unicast.interface_id & INT_ID_MASK) == INT_ID_SIGNATURE) {
+		mgid->unicast.prefix &= PREFIX_MASK;
+		mgid->unicast.interface_id &= INT_ID_MASK;
+		return 1;
+	}
+	return 0;
+}
+
+osm_mgrp_t *osm_get_mgrp_by_mgid(IN osm_sa_t *sa, IN ib_gid_t *p_mgid)
+{
+	int i;
+
+	if (sa->p_subn->opt.consolidate_ipv6_snm_req &&
+	    match_and_update_ipv6_snm_mgid(p_mgid)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Special Case Solicited Node Mcast Join for MGID %s\n",
+			inet_ntop(AF_INET6, p_mgid->raw, gid_str,
+				  sizeof gid_str));
+	}
+
+	for (i = 0; i <= sa->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
+	     i++)
+		if (sa->p_subn->mgroups[i] &&
+		    match_mgrp_by_mgid(sa->p_subn->mgroups[i], p_mgid))
+			return sa->p_subn->mgroups[i];
+
+	return NULL;
+}
+
+/**********************************************************************
+ Call this function to find or create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(IN osm_sa_t * sa,
+				     IN ib_net64_t comp_mask,
+				     IN ib_member_rec_t *
+				     const p_recvd_mcmember_rec,
+				     OUT osm_mgrp_t ** pp_mgrp)
+{
+	osm_mgrp_t *mgrp;
+
+	if ((mgrp = osm_get_mgrp_by_mgid(sa, &p_recvd_mcmember_rec->mgid))) {
+		*pp_mgrp = mgrp;
+		return IB_SUCCESS;
+	}
+	return osm_mcmr_rcv_create_new_mgrp(sa, comp_mask,
+					    p_recvd_mcmember_rec, NULL,
+					    pp_mgrp);
+}
+
+/*********************************************************************
+Process a request for leaving the group
+**********************************************************************/
+static void
+__osm_mcmr_rcv_leave_mgrp(IN osm_sa_t * sa,
+			  IN osm_madw_t * const p_madw)
+{
+	osm_mgrp_t *p_mgrp;
+	ib_sa_mad_t *p_sa_mad;
+	ib_member_rec_t *p_recvd_mcmember_rec;
+	ib_member_rec_t mcmember_rec;
+	ib_net16_t mlid;
+	ib_net64_t portguid;
+	osm_mcm_port_t *p_mcm_port;
+	int removed;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_mcmember_rec =
+	    (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	mcmember_rec = *p_recvd_mcmember_rec;
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of record\n");
+		osm_dump_mc_record(sa->p_log, &mcmember_rec, OSM_LOG_DEBUG);
+	}
+
+	CL_PLOCK_EXCL_ACQUIRE(sa->p_lock);
+	p_mgrp = osm_get_mgrp_by_mgid(sa, &p_recvd_mcmember_rec->mgid);
+	if (!p_mgrp) {
+		char gid_str[INET6_ADDRSTRLEN];
+		CL_PLOCK_RELEASE(sa->p_lock);
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Failed since multicast group %s not present\n",
+			inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw,
+				gid_str, sizeof gid_str));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	mlid = p_mgrp->mlid;
+	portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+	/* check validity of the delete request o15-0.1.14 */
+	if (!__validate_delete(sa, p_mgrp, osm_madw_get_mad_addr_ptr(p_madw),
+			       p_recvd_mcmember_rec, &p_mcm_port)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		char gid_str2[INET6_ADDRSTRLEN];
+		CL_PLOCK_RELEASE(sa->p_lock);
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B25: "
+			"Received an invalid delete request for "
+			"MGID: %s for PortGID: %s\n",
+			inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw,
+				  gid_str, sizeof gid_str),
+			inet_ntop(AF_INET6, p_recvd_mcmember_rec->port_gid.raw,
+				  gid_str2, sizeof gid_str2));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* store state - we'll need it if the port is removed */
+	mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+	/* remove port or update join state */
+	removed = osm_mgrp_remove_port(sa->p_subn, sa->p_log, p_mgrp, p_mcm_port,
+				       p_recvd_mcmember_rec->scope_state&0x0F);
+	if (!removed)
+		mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+	CL_PLOCK_RELEASE(sa->p_lock);
+
+	/* we can leave if port was deleted from MCG */
+	if (removed && osm_sm_mcgrp_leave(sa->sm, mlid, portguid))
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B09: "
+			"osm_sm_mcgrp_leave failed\n");
+
+	/* Send an SA response */
+	__osm_mcmr_rcv_respond(sa, p_madw, &mcmember_rec);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ Handle a join (or create) request
+**********************************************************************/
+static void
+__osm_mcmr_rcv_join_mgrp(IN osm_sa_t * sa, IN osm_madw_t * const p_madw)
+{
+	osm_mgrp_t *p_mgrp = NULL;
+	ib_api_status_t status;
+	ib_sa_mad_t *p_sa_mad;
+	ib_member_rec_t *p_recvd_mcmember_rec;
+	ib_member_rec_t mcmember_rec;
+	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(sa->p_log);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_mcmember_rec = ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+	mcmember_rec = *p_recvd_mcmember_rec;
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of incoming record\n");
+		osm_dump_mc_record(sa->p_log, &mcmember_rec, OSM_LOG_DEBUG);
+	}
+
+	CL_PLOCK_EXCL_ACQUIRE(sa->p_lock);
+
+	/* make sure the requested port guid is known to the SM */
+	p_port = osm_get_port_by_guid(sa->p_subn, portguid);
+	if (!p_port) {
+		CL_PLOCK_RELEASE(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Unknown port GUID 0x%016" PRIx64 "\n",
+			cl_ntoh64(portguid));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	p_physp = p_port->p_physp;
+	/* Check that the p_physp and the requester physp are in the same
+	   partition. */
+	p_request_physp =
+	    osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+				      osm_madw_get_mad_addr_ptr(p_madw));
+	if (p_request_physp == NULL) {
+		CL_PLOCK_RELEASE(sa->p_lock);
+		goto Exit;
+	}
+
+	if (!osm_physp_share_pkey(sa->p_log, p_physp, p_request_physp)) {
+		CL_PLOCK_RELEASE(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Port and requester don't share pkey\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	ib_member_get_scope_state(p_recvd_mcmember_rec->scope_state, NULL,
+				  &join_state);
+
+	/* do we need to create a new group? */
+	p_mgrp = osm_get_mgrp_by_mgid(sa, &p_recvd_mcmember_rec->mgid);
+	if (!p_mgrp || p_mgrp->to_be_deleted) {
+		/* check for JoinState.FullMember = 1 o15.0.1.9 */
+		if ((join_state & 0x01) != 0x01) {
+			char gid_str[INET6_ADDRSTRLEN];
+			CL_PLOCK_RELEASE(sa->p_lock);
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B10: "
+				"Provided Join State != FullMember - "
+				"required for create, "
+				"MGID: %s from port 0x%016" PRIx64 " (%s)\n",
+				inet_ntop(AF_INET6,
+					p_recvd_mcmember_rec->mgid.raw,
+					gid_str, sizeof gid_str),
+				cl_ntoh64(portguid),
+				p_port->p_node->print_desc);
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+
+		/* check the comp_mask */
+		if (!__check_create_comp_mask(p_sa_mad->comp_mask,
+					      p_recvd_mcmember_rec)) {
+			char gid_str[INET6_ADDRSTRLEN];
+			CL_PLOCK_RELEASE(sa->p_lock);
+
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B11: "
+				"method = %s, scope_state = 0x%x, "
+				"component mask = 0x%016" PRIx64 ", "
+				"expected comp mask = 0x%016" PRIx64 ", "
+				"MGID: %s from port 0x%016" PRIx64 " (%s)\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),
+				inet_ntop(AF_INET6,
+					p_recvd_mcmember_rec->mgid.raw,
+					gid_str, sizeof gid_str),
+				cl_ntoh64(portguid),
+				p_port->p_node->print_desc);
+
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_INSUF_COMPS);
+			goto Exit;
+		}
+
+		status = osm_mcmr_rcv_create_new_mgrp(sa, p_sa_mad->comp_mask,
+						      p_recvd_mcmember_rec,
+						      p_physp, &p_mgrp);
+		if (status != IB_SUCCESS) {
+			CL_PLOCK_RELEASE(sa->p_lock);
+			osm_sa_send_error(sa, p_madw, status);
+			goto Exit;
+		}
+		/* copy the MGID to the result */
+		mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid;
+		is_new_group = 1;
+		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:
+	 */
+	if (!__validate_more_comp_fields(sa->p_log, p_mgrp,
+					 p_recvd_mcmember_rec,
+					 p_sa_mad->comp_mask)
+	    || !__validate_port_caps(sa->p_log, p_mgrp, p_physp)
+	    || !(join_state != 0)) {
+		/* since we might have created the new group we need to cleanup */
+		__cleanup_mgrp(sa, mlid);
+
+		CL_PLOCK_RELEASE(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B12: "
+			"__validate_more_comp_fields, __validate_port_caps, "
+			"or JoinState = 0 failed from port 0x%016" PRIx64
+			" (%s), " "sending IB_SA_MAD_STATUS_REQ_INVALID\n",
+			cl_ntoh64(portguid), p_port->p_node->print_desc);
+
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/*
+	 * o15-0.2.1 requires validation of the requesting port
+	 * in the case of modification:
+	 */
+	if (!is_new_group &&
+	    !__validate_modify(sa, p_mgrp, osm_madw_get_mad_addr_ptr(p_madw),
+			       p_recvd_mcmember_rec, &p_mcmr_port)) {
+		CL_PLOCK_RELEASE(sa->p_lock);
+
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B13: "
+			"__validate_modify failed from port 0x%016" PRIx64
+			" (%s), sending IB_SA_MAD_STATUS_REQ_INVALID\n",
+			cl_ntoh64(portguid), p_port->p_node->print_desc);
+
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* create or update existing port (join-state will be updated) */
+	status = __add_new_mgrp_port(sa, 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(sa, mlid);
+
+		CL_PLOCK_RELEASE(sa->p_lock);
+
+		osm_sa_send_error(sa, p_madw, status == IB_INVALID_PARAMETER ?
+				  IB_SA_MAD_STATUS_REQ_INVALID :
+				  IB_SA_MAD_STATUS_NO_RESOURCES);
+		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(sa->p_lock);
+
+	/* do the actual routing (actually schedule the update) */
+	status = osm_sm_mcgrp_join(sa->sm, mlid,
+				   p_recvd_mcmember_rec->port_gid.unicast.
+				   interface_id, req_type);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B14: "
+			"osm_sm_mcgrp_join failed from port 0x%016" PRIx64
+			" (%s), " "sending IB_SA_MAD_STATUS_NO_RESOURCES\n",
+			cl_ntoh64(portguid), p_port->p_node->print_desc);
+
+		CL_PLOCK_EXCL_ACQUIRE(sa->p_lock);
+
+		/* the request for routing failed so we need to remove the port */
+		p_mgrp = osm_get_mgrp_by_mlid(sa->p_subn, mlid);
+		if (p_mgrp != NULL) {
+			osm_mgrp_delete_port(sa->p_subn, sa->p_log, p_mgrp,
+					     p_recvd_mcmember_rec->port_gid.
+					     unicast.interface_id);
+			__cleanup_mgrp(sa, mlid);
+		}
+		CL_PLOCK_RELEASE(sa->p_lock);
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES);
+		goto Exit;
+
+	}
+	/* failed to route */
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_mc_record(sa->p_log, &mcmember_rec, OSM_LOG_DEBUG);
+
+	__osm_mcmr_rcv_respond(sa, p_madw, &mcmember_rec);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ Add a patched multicast group to the results list
+**********************************************************************/
+static ib_api_status_t
+__osm_mcmr_rcv_new_mcmr(IN osm_sa_t * sa,
+			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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B15: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	/* HACK: Untrusted requesters should result with 0 Join
+	   State, Port Guid, and Proxy */
+	p_rec_item->rec = *p_rcvd_rec;
+	cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ Match the given mgrp to the requested mcmr
+**********************************************************************/
+static void mcmr_by_comp_mask(osm_sa_t *sa, const ib_member_rec_t *p_rcvd_rec,
+			      ib_net64_t comp_mask, osm_mgrp_t *p_mgrp,
+			      const osm_physp_t *p_req_physp,
+			      boolean_t trusted_req, cl_qlist_t *list)
+{
+	/* since we might change scope_state */
+	ib_member_rec_t match_rec;
+	osm_mcm_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 = FALSE;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Checking mlid:0x%X\n", cl_ntoh16(p_mgrp->mlid));
+
+	/* the group might be marked for deletion */
+	if (p_mgrp->to_be_deleted) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"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(sa->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) && query_sl != mgrp_sl)
+			goto Exit;
+
+		if ((IB_MCR_COMPMASK_FLOW & comp_mask) &&
+		     query_flow != mgrp_flow)
+			goto Exit;
+
+		if ((IB_MCR_COMPMASK_HOP & comp_mask) && 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;
+
+	/* need to validate mtu, rate, and pkt_lifetime fields */
+	if (__validate_more_comp_fields(sa->p_log, p_mgrp, p_rcvd_rec,
+					comp_mask) == FALSE)
+		goto Exit;
+
+	/* Port specific fields */
+	/* so did we get the PortGUID mask */
+	if (IB_MCR_COMPMASK_PORT_GID & comp_mask) {
+		/* try to find this port */
+		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;
+	}
+
+	if (IB_MCR_COMPMASK_SCOPE & comp_mask)
+		scope_state_mask = 0xF0;
+
+	if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask)
+		scope_state_mask = scope_state_mask | 0x0F;
+
+	/* Many MC records returned */
+	if (trusted_req == TRUE
+	    && !(IB_MCR_COMPMASK_PORT_GID & comp_mask)) {
+		char gid_str[INET6_ADDRSTRLEN];
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Trusted req is TRUE and no specific port defined\n");
+
+		/* return all the ports that match in this MC group */
+		p_item = cl_qmap_head(&(p_mgrp->mcm_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(sa->p_log, OSM_LOG_DEBUG,
+					"Record of port_gid: %s"
+					" in multicast_lid: 0x%X is returned\n",
+					inet_ntop(AF_INET6, match_rec.port_gid.raw,
+						  gid_str, sizeof gid_str),
+					cl_ntoh16(p_mgrp->mlid));
+
+				match_rec.proxy_join =
+				    (uint8_t) (p_mcm_port->proxy_join);
+
+				__osm_mcmr_rcv_new_mcmr(sa, &match_rec, 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(sa, &match_rec, list);
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ Handle a query request
+**********************************************************************/
+static void
+__osm_mcmr_query_mgrp(IN osm_sa_t * sa,
+		      IN 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;
+	ib_net64_t comp_mask;
+	osm_physp_t *p_req_physp;
+	boolean_t trusted_req;
+	osm_mgrp_t *p_mgrp;
+	int i;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec = (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+	comp_mask = p_rcvd_mad->comp_mask;
+
+	/*
+	   if sm_key is not zero and does not match we never get here
+	   see main SA receiver
+	 */
+	trusted_req = (p_rcvd_mad->sm_key != 0);
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B04: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	cl_qlist_init(&rec_list);
+
+	CL_PLOCK_ACQUIRE(sa->p_lock);
+
+	/* simply go over all MCGs and match */
+	for (i = 0; i <= sa->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
+	     i++) {
+		p_mgrp = sa->p_subn->mgroups[i];
+		if (p_mgrp)
+			mcmr_by_comp_mask(sa, p_rcvd_rec, comp_mask, p_mgrp,
+					  p_req_physp, trusted_req, &rec_list);
+	}
+
+	CL_PLOCK_RELEASE(sa->p_lock);
+
+	/*
+	   p923 - The PortGID, JoinState and ProxyJoin shall be zero,
+	   except in the case of a trusted request.
+	   Note: In the mad controller we check that the SM_Key received on
+	   the mad is valid. Meaning - is either zero or equal to the local
+	   sm_key.
+	 */
+
+	if (!p_rcvd_mad->sm_key) {
+		osm_mcmr_item_t *item;
+		for (item = (osm_mcmr_item_t *) cl_qlist_head(&rec_list);
+		     item != (osm_mcmr_item_t *) cl_qlist_end(&rec_list);
+		     item = (osm_mcmr_item_t *)cl_qlist_next(&item->list_item)) {
+			memset(&item->rec.port_gid, 0, sizeof(ib_gid_t));
+			ib_member_set_join_state(&item->rec, 0);
+			item->rec.proxy_join = 0;
+		}
+	}
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_member_rec_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mcmr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	ib_sa_mad_t *p_sa_mad;
+	ib_member_rec_t *p_recvd_mcmember_rec;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_mcmember_rec =
+	    (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD);
+
+	switch (p_sa_mad->method) {
+	case IB_MAD_METHOD_SET:
+		if (!__check_join_comp_mask(p_sa_mad->comp_mask)) {
+			char gid_str[INET6_ADDRSTRLEN];
+			char gid_str2[INET6_ADDRSTRLEN];
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B18: "
+				"component mask = 0x%016" PRIx64 ", "
+				"expected comp mask = 0x%016" PRIx64 ", "
+				"MGID: %s for PortGID: %s\n",
+				cl_ntoh64(p_sa_mad->comp_mask),
+				CL_NTOH64(JOIN_MC_COMP_MASK),
+				inet_ntop(AF_INET6,
+					p_recvd_mcmember_rec->mgid.raw,
+					gid_str, sizeof gid_str),
+				inet_ntop(AF_INET6,
+					p_recvd_mcmember_rec->port_gid.raw,
+					gid_str2, sizeof gid_str2));
+
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+
+		/*
+		 * Join or Create Multicast Group
+		 */
+		__osm_mcmr_rcv_join_mgrp(sa, p_madw);
+		break;
+	case IB_MAD_METHOD_DELETE:
+		if (!__check_join_comp_mask(p_sa_mad->comp_mask)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B20: "
+				"component mask = 0x%016" PRIx64 ", "
+				"expected comp mask = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_sa_mad->comp_mask),
+				CL_NTOH64(JOIN_MC_COMP_MASK));
+
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+
+		/*
+		 * Leave Multicast Group
+		 */
+		__osm_mcmr_rcv_leave_mgrp(sa, p_madw);
+		break;
+	case IB_MAD_METHOD_GET:
+	case IB_MAD_METHOD_GETTABLE:
+		/*
+		 * Querying a Multicast Group
+		 */
+		__osm_mcmr_query_mgrp(sa, p_madw);
+		break;
+	default:
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B21: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw,
+				  IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		break;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return;
+}
diff --git a/opensm/osm_sa_mft_record.c b/opensm/osm_sa_mft_record.c
new file mode 100644
index 0000000..bda9aee
--- /dev/null
+++ b/opensm/osm_sa_mft_record.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_mftr_rcv_t.
+ *   This object represents the MulticastForwardingTable Receiver object.
+ *   This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_mftr_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_mftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mftr_rcv_new_mftr(IN osm_sa_t * sa,
+			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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A02: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New MulticastForwardingTable: sw 0x%016" PRIx64
+		"\n\t\t\t\tblock %u position %u lid %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)),
+		block, position, cl_ntoh16(lid));
+
+	position_block_num = ((uint16_t) position << 12) |
+	    (block & IB_MCAST_BLOCK_ID_MASK_HO);
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_sa_t *sa = p_ctxt->sa;
+	ib_net64_t const comp_mask = p_ctxt->comp_mask;
+	const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
+	osm_port_t *p_port;
+	uint16_t min_lid_ho, max_lid_ho;
+	uint16_t position_block_num_ho;
+	uint16_t min_block, max_block, block;
+	const osm_physp_t *p_physp;
+	uint8_t min_position, max_position, position;
+
+	/* In switches, the port guid is the node guid. */
+	p_port =
+	    osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid);
+	if (!p_port) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A05: "
+			"Failed to find Port by Node Guid:0x%016" PRIx64
+			"\n", cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		return;
+	}
+
+	/* check that the requester physp and the current physp are under
+	   the same partition. */
+	p_physp = p_port->p_physp;
+	if (!p_physp) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A06: "
+			"Failed to find default physical Port by Node Guid:0x%016"
+			PRIx64 "\n",
+			cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		return;
+	}
+	if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp))
+		return;
+
+	/* get the port 0 of the switch */
+	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+	/* compare the lids - if required */
+	if (comp_mask & IB_MFTR_COMPMASK_LID) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Comparing lid:%u to port lid range: %u .. %u\n",
+			cl_ntoh16(p_rcvd_rec->lid), min_lid_ho, max_lid_ho);
+		/* ok we are ready for range check */
+		if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) ||
+		    max_lid_ho < cl_ntoh16(p_rcvd_rec->lid))
+			return;
+	}
+
+	if (!osm_switch_supports_mcast(p_sw))
+		return;
+
+	/* Are there any blocks in use ? */
+	if (osm_switch_get_mft_max_block_in_use(p_sw) == -1)
+		return;
+
+	position_block_num_ho = cl_ntoh16(p_rcvd_rec->position_block_num);
+
+	/* now we need to decide which blocks to output */
+	if (comp_mask & IB_MFTR_COMPMASK_BLOCK) {
+		max_block = min_block =
+		    position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO;
+		if (max_block > osm_switch_get_mft_max_block_in_use(p_sw))
+			return;
+	} else {
+		/* use as many blocks as needed */
+		min_block = 0;
+		max_block = osm_switch_get_mft_max_block_in_use(p_sw);
+	}
+
+	/* need to decide which positions to output */
+	if (comp_mask & IB_MFTR_COMPMASK_POSITION) {
+		min_position = max_position =
+		    (position_block_num_ho & 0xF000) >> 12;
+		if (max_position > osm_switch_get_mft_max_position(p_sw))
+			return;
+	} else {
+		/* use as many positions as needed */
+		min_position = 0;
+		max_position = osm_switch_get_mft_max_position(p_sw);
+	}
+
+	/* so we can add these one by one ... */
+	for (block = min_block; block <= max_block; block++)
+		for (position = min_position; position <= max_position;
+		     position++)
+			__osm_mftr_rcv_new_mftr(sa, p_sw, p_ctxt->p_list,
+						osm_port_get_base_lid(p_port),
+						block, position);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mftr_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_mft_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_mftr_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec = (ib_mft_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_MFT_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A08: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log,
+						sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 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.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	/* Go over all switches */
+	cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl,
+			   __osm_mftr_rcv_by_comp_mask, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_mft_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_multipath_record.c b/opensm/osm_sa_multipath_record.c
new file mode 100644
index 0000000..b9164be
--- /dev/null
+++ b/opensm/osm_sa_multipath_record.c
@@ -0,0 +1,1536 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Implementation of osm_mpr_rcv_t.
+ *	This object represents the MultiPath Record Receiver object.
+ *	This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+
+#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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_qos_policy.h>
+#include <opensm/osm_sa.h>
+
+#define OSM_SA_MPR_MAX_NUM_PATH        127
+
+typedef struct osm_mpr_item {
+	cl_list_item_t list_item;
+	ib_path_rec_t path_rec;
+	const osm_port_t *p_src_port;
+	const osm_port_t *p_dest_port;
+	int hops;
+} 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;
+
+/**********************************************************************
+ **********************************************************************/
+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 = p_port->p_node;
+	vend_id = ib_node_info_get_vendor_id(&p_node->node_info);
+
+	return ((p_node->node_info.device_id == CL_HTON16(23108)) &&
+		((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))));
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__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_MPR_COMPMASK_MTU)) {
+		switch (ib_multipath_rec_mtu_sel(p_mpr)) {
+		case 0:	/* must be greater than */
+		case 2:	/* exact match */
+			if (IB_MTU_LEN_1024 < required_mtu)
+				return (FALSE);
+			break;
+
+		case 1:	/* must be less than */
+			/* can't be disqualified by this one */
+			break;
+
+		case 3:	/* largest available */
+			/* the ULP intentionally requested */
+			/* the largest MTU possible */
+			return (FALSE);
+			break;
+
+		default:
+			/* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
+			CL_ASSERT(FALSE);
+			break;
+		}
+	}
+
+	return (TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mpr_rcv_get_path_parms(IN osm_sa_t * sa,
+			     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_src_physp;
+	const osm_physp_t *p_dest_physp;
+	const osm_prtn_t *p_prtn = NULL;
+	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;
+	ib_net16_t required_pkey;
+	uint8_t required_sl;
+	uint8_t required_pkt_life;
+	ib_net16_t dest_lid;
+	int hops = 0;
+	int in_port_num = 0;
+	uint8_t i;
+	osm_qos_level_t *p_qos_level = NULL;
+	uint16_t valid_sl_mask = 0xffff;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	dest_lid = cl_hton16(dest_lid_ho);
+
+	p_dest_physp = p_dest_port->p_physp;
+	p_physp = p_src_port->p_physp;
+	p_src_physp = p_physp;
+	p_pi = &p_physp->port_info;
+
+	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 (sa->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(sa->p_log, OSM_LOG_DEBUG,
+				"Optimized Path MTU to 1K for Mellanox Tavor device\n");
+		}
+
+	/*
+	   Walk the subnet object from source to destination,
+	   tracking the most restrictive rate and mtu values along the way...
+
+	   If source port node is a switch, then p_physp should
+	   point to the port that routes the destination lid
+	 */
+
+	p_node = osm_physp_get_node_ptr(p_physp);
+
+	if (p_node->sw) {
+		/*
+		 * Source node is a switch.
+		 * Make sure that p_physp points to the out port of the
+		 * switch that routes to the destination lid (dest_lid_ho)
+		 */
+		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4514: "
+				"Can't find routing to LID %u from switch for GUID 0x%016"
+				PRIx64 "\n", dest_lid_ho,
+				cl_ntoh64(osm_node_get_node_guid(p_node)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	if (sa->p_subn->opt.qos) {
+
+		/*
+		 * Whether this node is switch or CA, the IN port for
+		 * the sl2vl table is 0, because this is a source node.
+		 */
+		p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0);
+
+		/* update valid SLs that still exist on this route */
+		for (i = 0; i < IB_MAX_NUM_VLS; i++) {
+			if (valid_sl_mask & (1 << i) &&
+			    ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
+				valid_sl_mask &= ~(1 << i);
+		}
+		if (!valid_sl_mask) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"All the SLs lead to VL15 on this path\n");
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	/*
+	 * Same as above
+	 */
+	p_node = osm_physp_get_node_ptr(p_dest_physp);
+
+	if (p_node->sw) {
+		/*
+		 * if destination is switch, we want p_dest_physp to point to port 0
+		 */
+		p_dest_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+
+		if (p_dest_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4515: "
+				"Can't find routing to LID %u from switch for GUID 0x%016"
+				PRIx64 "\n", dest_lid_ho,
+				cl_ntoh64(osm_node_get_node_guid(p_node)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	}
+
+	/*
+	 * Now go through the path step by step
+	 */
+
+	while (p_physp != p_dest_physp) {
+
+		p_node = osm_physp_get_node_ptr(p_physp);
+		p_physp = osm_physp_get_remote(p_physp);
+
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4505: "
+				"Can't find remote phys port when routing to LID %u 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++;
+		in_port_num = osm_physp_get_port_num(p_physp);
+
+		/*
+		   This is point to point case (no switch in between)
+		 */
+		if (p_physp == p_dest_physp)
+			break;
+
+		p_node = osm_physp_get_node_ptr(p_physp);
+
+		if (!p_node->sw) {
+			/*
+			   There is some sort of problem in the subnet object!
+			   If this isn't a switch, we should have reached
+			   the destination by now!
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4503: "
+				"Internal error, bad path\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		/*
+		   Check parameters for the ingress port in this switch.
+		 */
+		p_pi = &p_physp->port_info;
+
+		if (mtu > ib_port_info_get_mtu_cap(p_pi))
+			mtu = ib_port_info_get_mtu_cap(p_pi);
+
+		if (rate > ib_port_info_compute_rate(p_pi))
+			rate = ib_port_info_compute_rate(p_pi);
+
+		/*
+		   Continue with the egress port on this switch.
+		 */
+		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4516: "
+				"Dead end on path to LID %u 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;
+		}
+
+		p_pi = &p_physp->port_info;
+
+		if (mtu > ib_port_info_get_mtu_cap(p_pi))
+			mtu = ib_port_info_get_mtu_cap(p_pi);
+
+		if (rate > ib_port_info_compute_rate(p_pi))
+			rate = ib_port_info_compute_rate(p_pi);
+
+		if (sa->p_subn->opt.qos) {
+			/*
+			 * Check SL2VL table of the switch and update valid SLs
+			 */
+			p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, in_port_num);
+			for (i = 0; i < IB_MAX_NUM_VLS; i++) {
+				if (valid_sl_mask & (1 << i) &&
+				    ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
+					valid_sl_mask &= ~(1 << i);
+			}
+			if (!valid_sl_mask) {
+				OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+					"All the SLs lead to VL15 "
+					"on this path\n");
+				status = IB_NOT_FOUND;
+				goto Exit;
+			}
+		}
+	}
+
+	/*
+	   p_physp now points to the destination
+	 */
+	p_pi = &p_physp->port_info;
+
+	if (mtu > ib_port_info_get_mtu_cap(p_pi))
+		mtu = ib_port_info_get_mtu_cap(p_pi);
+
+	if (rate > ib_port_info_compute_rate(p_pi))
+		rate = ib_port_info_compute_rate(p_pi);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Path min MTU = %u, min rate = %u\n", mtu, rate);
+
+	/*
+	 * Get QoS Level object according to the MultiPath request
+	 * and adjust MultiPath parameters according to QoS settings
+	 */
+	if (sa->p_subn->opt.qos &&
+	    sa->p_subn->p_qos_policy &&
+	    (p_qos_level =
+	     osm_qos_policy_get_qos_level_by_mpr(sa->p_subn->p_qos_policy,
+						 p_mpr, p_src_physp,
+						 p_dest_physp, comp_mask))) {
+
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"MultiPathRecord request matches QoS Level '%s' (%s)\n",
+			p_qos_level->name,
+			p_qos_level->use ? p_qos_level->use : "no description");
+
+		if (p_qos_level->mtu_limit_set
+		    && (mtu > p_qos_level->mtu_limit))
+			mtu = p_qos_level->mtu_limit;
+
+		if (p_qos_level->rate_limit_set
+		    && (rate > p_qos_level->rate_limit))
+			rate = p_qos_level->rate_limit;
+
+		if (p_qos_level->sl_set) {
+			required_sl = p_qos_level->sl;
+			if (!(valid_sl_mask & (1 << required_sl))) {
+				status = IB_NOT_FOUND;
+				goto Exit;
+			}
+		}
+	}
+
+	/*
+	   Determine if these values meet the user criteria
+	 */
+
+	/* we silently ignore cases where only the MTU selector is defined */
+	if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) &&
+	    (comp_mask & IB_MPR_COMPMASK_MTU)) {
+		required_mtu = ib_multipath_rec_mtu(p_mpr);
+		switch (ib_multipath_rec_mtu_sel(p_mpr)) {
+		case 0:	/* must be greater than */
+			if (mtu <= required_mtu)
+				status = IB_NOT_FOUND;
+			break;
+
+		case 1:	/* must be less than */
+			if (mtu >= required_mtu) {
+				/* adjust to use the highest mtu
+				   lower then the required one */
+				if (required_mtu > 1)
+					mtu = required_mtu - 1;
+				else
+					status = IB_NOT_FOUND;
+			}
+			break;
+
+		case 2:	/* exact match */
+			if (mtu < required_mtu)
+				status = IB_NOT_FOUND;
+			else
+				mtu = required_mtu;
+			break;
+
+		case 3:	/* largest available */
+			/* can't be disqualified by this one */
+			break;
+
+		default:
+			/* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
+			CL_ASSERT(FALSE);
+			status = IB_ERROR;
+			break;
+		}
+	}
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* we silently ignore cases where only the Rate selector is defined */
+	if ((comp_mask & IB_MPR_COMPMASK_RATESELEC) &&
+	    (comp_mask & IB_MPR_COMPMASK_RATE)) {
+		required_rate = ib_multipath_rec_rate(p_mpr);
+		switch (ib_multipath_rec_rate_sel(p_mpr)) {
+		case 0:	/* must be greater than */
+			if (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;
+		}
+	}
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Verify the pkt_life_time */
+	/* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,
+	   for loopback paths, packetLifeTime shall be zero. */
+	if (p_src_port == p_dest_port)
+		pkt_life = 0;	/* loopback */
+	else if (p_qos_level && p_qos_level->pkt_life_set)
+		pkt_life = p_qos_level->pkt_life;
+	else
+		pkt_life = sa->p_subn->opt.subnet_timeout;
+
+	/* we silently ignore cases where only the PktLife selector is defined */
+	if ((comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC) &&
+	    (comp_mask & IB_MPR_COMPMASK_PKTLIFETIME)) {
+		required_pkt_life = ib_multipath_rec_pkt_life(p_mpr);
+		switch (ib_multipath_rec_pkt_life_sel(p_mpr)) {
+		case 0:	/* must be greater than */
+			if (pkt_life <= required_pkt_life)
+				status = IB_NOT_FOUND;
+			break;
+
+		case 1:	/* must be less than */
+			if (pkt_life >= required_pkt_life) {
+				/* adjust the lifetime to use the highest possible
+				   lower then the required one */
+				if (required_pkt_life > 1)
+					pkt_life = required_pkt_life - 1;
+				else
+					status = IB_NOT_FOUND;
+			}
+			break;
+
+		case 2:	/* exact match */
+			if (pkt_life < required_pkt_life)
+				status = IB_NOT_FOUND;
+			else
+				pkt_life = required_pkt_life;
+			break;
+
+		case 3:	/* smallest available */
+			/* can't be disqualified by this one */
+			break;
+
+		default:
+			/* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */
+			CL_ASSERT(FALSE);
+			status = IB_ERROR;
+			break;
+		}
+	}
+
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/*
+	 * set Pkey for this MultiPath record request
+	 */
+
+	if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
+	    cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
+		required_pkey =
+		    osm_physp_find_common_pkey(p_src_physp, p_dest_physp);
+
+	else if (comp_mask & IB_MPR_COMPMASK_PKEY) {
+		/*
+		 * MPR request has a specific pkey:
+		 * Check that source and destination share this pkey.
+		 * If QoS level has pkeys, check that this pkey exists
+		 * in the QoS level pkeys.
+		 * MPR returned pkey is the requested pkey.
+		 */
+		required_pkey = p_mpr->pkey;
+		if (!osm_physp_share_this_pkey
+		    (p_src_physp, p_dest_physp, required_pkey)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "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_src_physp)),
+				cl_ntoh64(osm_physp_get_port_guid
+					  (p_dest_physp)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+		if (p_qos_level && p_qos_level->pkey_range_len &&
+		    !osm_qos_level_has_pkey(p_qos_level, required_pkey)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451C: "
+				"Ports do not share PKeys defined by QoS level\n");
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	} else if (p_qos_level && p_qos_level->pkey_range_len) {
+		/*
+		 * MPR request doesn't have a specific pkey, but QoS level
+		 * has pkeys - get shared pkey from QoS level pkeys
+		 */
+		required_pkey = osm_qos_level_get_shared_pkey(p_qos_level,
+							      p_src_physp,
+							      p_dest_physp);
+		if (!required_pkey) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451D: "
+				"Ports do not share PKeys defined by QoS level\n");
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	} else {
+		/*
+		 * Neither MPR request nor QoS level have pkey.
+		 * Just get any shared pkey.
+		 */
+		required_pkey =
+		    osm_physp_find_common_pkey(p_src_physp, p_dest_physp);
+		if (!required_pkey) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "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;
+		}
+	}
+
+	if (required_pkey) {
+		p_prtn =
+		    (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
+					       required_pkey &
+					       cl_ntoh16((uint16_t) ~ 0x8000));
+		if (p_prtn ==
+		    (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl))
+			p_prtn = NULL;
+	}
+
+	/*
+	 * Set MultiPathRecord SL.
+	 */
+
+	if (comp_mask & IB_MPR_COMPMASK_SL) {
+		/*
+		 * Specific SL was requested
+		 */
+		required_sl = ib_multipath_rec_sl(p_mpr);
+
+		if (p_qos_level && p_qos_level->sl_set &&
+		    p_qos_level->sl != required_sl) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451E: "
+				"QoS constaraints: required MultiPathRecord SL (%u) "
+				"doesn't match QoS policy SL (%u)\n",
+				required_sl, p_qos_level->sl);
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	} else if (p_qos_level && p_qos_level->sl_set) {
+		/*
+		 * No specific SL was requested,
+		 * but there is an SL in QoS level.
+		 */
+		required_sl = p_qos_level->sl;
+
+		if (required_pkey && p_prtn && p_prtn->sl != p_qos_level->sl)
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"QoS level SL (%u) overrides partition SL (%u)\n",
+				p_qos_level->sl, p_prtn->sl);
+
+	} else if (required_pkey) {
+		/*
+		 * No specific SL in request or in QoS level - use partition SL
+		 */
+		p_prtn =
+		    (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
+					       required_pkey &
+					       cl_ntoh16((uint16_t) ~ 0x8000));
+		if (!p_prtn) {
+			required_sl = OSM_DEFAULT_SL;
+			/* this may be possible when pkey tables are created somehow in
+			   previous runs or things are going wrong here */
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451A: "
+				"No partition found for PKey 0x%04x - using default SL %d\n",
+				cl_ntoh16(required_pkey), required_sl);
+		} else
+			required_sl = p_prtn->sl;
+
+	} else if (sa->p_subn->opt.qos) {
+		if (valid_sl_mask & (1 << OSM_DEFAULT_SL))
+			required_sl = OSM_DEFAULT_SL;
+		else {
+			for (i = 0; i < IB_MAX_NUM_VLS; i++)
+				if (valid_sl_mask & (1 << i))
+					break;
+			required_sl = i;
+		}
+	} else
+		required_sl = OSM_DEFAULT_SL;
+
+	if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << required_sl))) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451F: "
+			"Selected SL (%u) leads to VL15\n", required_sl);
+		status = IB_NOT_FOUND;
+		goto Exit;
+	}
+
+	/* reset pkey when raw traffic */
+	if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
+	    cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
+		required_pkey = 0;
+
+	p_parms->mtu = mtu;
+	p_parms->rate = rate;
+	p_parms->pkey = required_pkey;
+	p_parms->pkt_life = pkt_life;
+	p_parms->sl = required_sl;
+	p_parms->hops = hops;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MultiPath params:"
+		" mtu = %u, rate = %u, packet lifetime = %u,"
+		" pkey = 0x%04X, sl = %u, hops = %u\n", mtu, rate,
+		pkt_life, cl_ntoh16(required_pkey), required_sl, hops);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_build_pr(IN osm_sa_t * sa,
+		       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(sa->p_log);
+
+	p_src_physp = p_src_port->p_physp;
+	p_dest_physp = p_dest_port->p_physp;
+
+	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;
+	ib_path_rec_set_qos_class(p_pr, 0);
+	ib_path_rec_set_sl(p_pr, p_parms->sl);
+	p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80);
+	p_pr->rate = (uint8_t) (p_parms->rate | 0x80);
+
+	/* According to 1.2 spec definition Table 205 PacketLifeTime description,
+	   for loopback paths, packetLifeTime shall be zero. */
+	if (p_src_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(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t *
+__osm_mpr_rcv_get_lid_pair_path(IN osm_sa_t * sa,
+				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(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID %u, Dest LID %u\n",
+		src_lid_ho, dest_lid_ho);
+
+	p_pr_item = malloc(sizeof(*p_pr_item));
+	if (p_pr_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4501: "
+			"Unable to allocate path record\n");
+		goto Exit;
+	}
+	memset(p_pr_item, 0, sizeof(*p_pr_item));
+
+	status = __osm_mpr_rcv_get_path_parms(sa, p_mpr, p_src_port,
+					      p_dest_port, dest_lid_ho,
+					      comp_mask, &path_parms);
+
+	if (status != IB_SUCCESS) {
+		free(p_pr_item);
+		p_pr_item = NULL;
+		goto Exit;
+	}
+
+	/* now try the reversible path */
+	rev_path_status =
+	    __osm_mpr_rcv_get_path_parms(sa, 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(sa->p_log, OSM_LOG_DEBUG,
+				"Requested reversible path but failed to get one\n");
+
+			free(p_pr_item);
+			p_pr_item = NULL;
+			goto Exit;
+		}
+	}
+
+	p_pr_item->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(sa, p_src_port, p_dest_port, src_lid_ho,
+			       dest_lid_ho, preference, &path_parms,
+			       &p_pr_item->path_rec);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (p_pr_item);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static uint32_t
+__osm_mpr_rcv_get_port_pair_paths(IN osm_sa_t * sa,
+				  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(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"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(sa->p_log, p_req_port, p_src_port) == FALSE
+	    || osm_port_share_pkey(sa->p_log, p_req_port,
+				   p_dest_port) == FALSE
+	    || osm_port_share_pkey(sa->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);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID [%u-%u], Dest LID [%u-%u]\n",
+		src_lid_min_ho, src_lid_max_ho,
+		dest_lid_min_ho, dest_lid_max_ho);
+
+	src_lid_ho = src_lid_min_ho;
+	dest_lid_ho = dest_lid_min_ho;
+
+	/*
+	   Preferred paths come first in OpenSM
+	 */
+	preference = 0;
+
+	while (path_num < rem_paths) {
+		/*
+		   These paths are "fully redundant"
+		 */
+		p_pr_item = __osm_mpr_rcv_get_lid_pair_path(sa, 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, &p_pr_item->list_item);
+			++path_num;
+		}
+
+		if (++src_lid_ho > src_lid_max_ho)
+			break;
+
+		if (++dest_lid_ho > dest_lid_max_ho)
+			break;
+	}
+
+	/*
+	   Check if we've accumulated all the paths that the user cares to see
+	 */
+	if (path_num == rem_paths)
+		goto Exit;
+
+	/*
+	   Don't bother reporting preference 1 paths for now.
+	   It's more trouble than it's worth and can only occur
+	   if ports have different LMC values, which isn't supported
+	   by OpenSM right now anyway.
+	 */
+	preference = 2;
+	src_lid_ho = src_lid_min_ho;
+	dest_lid_ho = dest_lid_min_ho;
+	src_offset = 0;
+	dest_offset = 0;
+
+	/*
+	   Iterate over the remaining paths
+	 */
+	while (path_num < rem_paths) {
+		dest_offset++;
+		dest_lid_ho++;
+
+		if (dest_lid_ho > dest_lid_max_ho) {
+			src_offset++;
+			src_lid_ho++;
+
+			if (src_lid_ho > src_lid_max_ho)
+				break;	/* done */
+
+			dest_offset = 0;
+			dest_lid_ho = dest_lid_min_ho;
+		}
+
+		/*
+		   These paths are "fully non-redundant" with paths already
+		   identified above and consequently not of much value.
+
+		   Don't return paths we already identified above, as indicated
+		   by the offset values being equal.
+		 */
+		if (src_offset == dest_offset)
+			continue;	/* already reported */
+
+		p_pr_item = __osm_mpr_rcv_get_lid_pair_path(sa, 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, &p_pr_item->list_item);
+			++path_num;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return path_num;
+}
+
+#undef min
+#define min(x,y)	(((x) < (y)) ? (x) : (y))
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t *
+__osm_mpr_rcv_get_apm_port_pair_paths(IN osm_sa_t * sa,
+				      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(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src port 0x%016" PRIx64 ", "
+		"Dst port 0x%016" PRIx64 ", base offs %d\n",
+		cl_ntoh64(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(sa->p_log, OSM_LOG_DEBUG,
+		"Src LIDs [%u-%u] hashed %u, "
+		"Dest LIDs [%u-%u] hashed %u\n",
+		src_lid_min_ho, src_lid_max_ho, src_lid_ho,
+		dest_lid_min_ho, dest_lid_max_ho, dest_lid_ho);
+
+	iterations = min(src_lids, dest_lids);
+
+	while (iterations--) {
+		/*
+		   These paths are "fully redundant"
+		 */
+		p_pr_item = __osm_mpr_rcv_get_lid_pair_path(sa, p_mpr,
+							    p_src_port,
+							    p_dest_port,
+							    src_lid_ho,
+							    dest_lid_ho,
+							    comp_mask, 0);
+
+		if (p_pr_item) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Found matching path from Src LID %u to Dest LID %u with %d hops\n",
+				src_lid_ho, dest_lid_ho, p_pr_item->hops);
+			break;
+		}
+
+		if (++src_lid_ho > src_lid_max_ho)
+			src_lid_ho = src_lid_min_ho;
+
+		if (++dest_lid_ho > dest_lid_max_ho)
+			dest_lid_ho = dest_lid_min_ho;
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+	return p_pr_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_gids(IN osm_sa_t * sa,
+		       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(sa->p_log);
+
+	for (i = 0; i < ngids; i++, gids++) {
+		if (!ib_gid_is_link_local(gids)) {
+			if ((is_sgid && ib_gid_is_multicast(gids)) ||
+			    (ib_gid_get_subnet_prefix(gids) !=
+			     sa->p_subn->opt.subnet_prefix)) {
+				/*
+				   This 'error' is the client's fault (bad gid)
+				   so don't enter it as an error in our own log.
+				   Return an error response to the client.
+				 */
+				OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "ERR 451B: "
+					"%sGID 0x%016" PRIx64
+					" is multicast or non local subnet prefix\n",
+					is_sgid ? "S" : "D",
+					cl_ntoh64(gids->unicast.prefix));
+
+				ib_status = IB_SA_MAD_STATUS_INVALID_GID;
+				goto Exit;
+			}
+		}
+
+		p_port =
+		    osm_get_port_by_guid(sa->p_subn,
+					 gids->unicast.interface_id);
+		if (!p_port) {
+			/*
+			   This 'error' is the client's fault (bad gid) so
+			   don't enter it as an error in our own log.
+			   Return an error response to the client.
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4506: "
+				"No port with GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(gids->unicast.interface_id));
+
+			ib_status = IB_SA_MAD_STATUS_INVALID_GID;
+			goto Exit;
+		}
+
+		pp_port[i] = p_port;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+
+	return ib_status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_end_points(IN osm_sa_t * sa,
+			     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(sa->p_log);
+
+	/*
+	   Determine what fields are valid and then get a pointer
+	   to the source and destination port objects, if possible.
+	 */
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+	gids = (ib_gid_t *) p_mpr->gids;
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	/*
+	   Check a few easy disqualifying cases up front before getting
+	   into the endpoints.
+	 */
+	*nsrc = *ndest = 0;
+
+	if (comp_mask & IB_MPR_COMPMASK_SGIDCOUNT) {
+		*nsrc = p_mpr->sgid_count;
+		if (*nsrc > IB_MULTIPATH_MAX_GIDS)
+			*nsrc = IB_MULTIPATH_MAX_GIDS;
+		sa_status =
+		    __osm_mpr_rcv_get_gids(sa, 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(sa, gids + *nsrc, *ndest, 0,
+					   pp_ports + *nsrc);
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (sa_status);
+}
+
+#define __hash_lids(a, b, lmc)	\
+	(((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103)
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_get_apm_paths(IN osm_sa_t * sa,
+			    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(sa->p_log);
+
+	/*
+	 * We want to:
+	 *    1. use different lid offsets (from base) for the resultant paths
+	 *    to increase the probability of redundant paths or in case
+	 *    of Clos - to ensure it (different offset => different spine!)
+	 *    2. keep consistent paths no matter of direction and order of ports
+	 *    3. distibute the lid offsets to balance the load
+	 * So, we sort the ports (within the srcs, and within the dests),
+	 * hash the lids of S0, D0 (after the sort), and call __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, sa->p_subn->opt.lmc) :
+	    __hash_lids(dest_lid_ho, src_lid_ho, sa->p_subn->opt.lmc);
+
+	matrix[0][0] =
+	    __osm_mpr_rcv_get_apm_port_pair_paths(sa, 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(sa, 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(sa, 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(sa, p_mpr, pp_ports[1],
+						  pp_ports[3], base_offs + 1,
+						  comp_mask, p_list);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "APM matrix:\n"
+		"\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n"
+		"\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n",
+		matrix[0][0]->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(sa->p_log, OSM_LOG_DEBUG,
+			"Diag {0,0} & {1,1} is the best:\n"
+			"\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n",
+			matrix[0][0]->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, &matrix[0][0]->list_item);
+		cl_qlist_insert_tail(p_list, &matrix[1][1]->list_item);
+		free(matrix[0][1]);
+		free(matrix[1][0]);
+	} else {
+		/* Diag B */
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Diag {0,1} & {1,0} is the best:\n"
+			"\t{0,1} 0x%X->0x%X (%d)\t & {1,0} 0x%X->0x%X (%d)\n",
+			matrix[0][1]->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, &matrix[0][1]->list_item);
+		cl_qlist_insert_tail(p_list, &matrix[1][0]->list_item);
+		free(matrix[0][0]);
+		free(matrix[1][1]);
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_process_pairs(IN osm_sa_t * sa,
+			    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(sa->p_log);
+
+	if (comp_mask & IB_MPR_COMPMASK_NUMBPATH)
+		max_paths = p_mpr->num_path & 0x7F;
+	else
+		max_paths = OSM_SA_MPR_MAX_NUM_PATH;
+
+	for (pp_src_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(sa, 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(sa->p_log, OSM_LOG_DEBUG,
+				"%d paths %d total paths %d max paths\n",
+				num_paths, total_paths, max_paths);
+			/* Just take first NumbPaths found */
+			if (total_paths >= max_paths)
+				goto Exit;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_mpr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	const ib_multipath_rec_t *p_mpr;
+	ib_sa_mad_t *p_sa_mad;
+	osm_port_t *requester_port;
+	osm_port_t *pp_ports[IB_MULTIPATH_MAX_GIDS];
+	cl_qlist_t pr_list;
+	ib_net16_t sa_status;
+	int nsrc, ndest;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD);
+
+	if ((p_sa_mad->rmpp_flags & IB_RMPP_FLAG_ACTIVE) != IB_RMPP_FLAG_ACTIVE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4510: "
+			"Invalid request since RMPP_FLAG_ACTIVE is not set\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* we only support SubnAdmGetMulti method */
+	if (p_sa_mad->method != IB_MAD_METHOD_GETMULTI) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4513: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	requester_port = osm_get_port_by_mad_addr(sa->p_log, sa->p_subn,
+						  osm_madw_get_mad_addr_ptr
+						  (p_madw));
+	if (requester_port == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4517: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_multipath_record(sa->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(sa->p_lock);
+
+	sa_status = __osm_mpr_rcv_get_end_points(sa, 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(sa->p_log, OSM_LOG_ERROR, "ERR 4512: "
+				"__osm_mpr_rcv_get_end_points failed, not enough GIDs "
+				"(nsrc %d ndest %d)\n", nsrc, ndest);
+		cl_plock_release(sa->p_lock);
+		if (sa_status == IB_SA_MAD_STATUS_SUCCESS)
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+		else
+			osm_sa_send_error(sa, p_madw, sa_status);
+		goto Exit;
+	}
+
+	/* APM request */
+	if (nsrc == 2 && ndest == 2 && (p_mpr->num_path & 0x7F) == 2)
+		__osm_mpr_rcv_get_apm_paths(sa, p_mpr, requester_port,
+					    pp_ports, p_sa_mad->comp_mask,
+					    &pr_list);
+	else
+		__osm_mpr_rcv_process_pairs(sa, p_mpr, requester_port,
+					    pp_ports, nsrc, ndest,
+					    p_sa_mad->comp_mask, &pr_list);
+
+	cl_plock_release(sa->p_lock);
+
+	/* o15-0.2.7: If MultiPath is supported, then SA shall respond to a
+	   SubnAdmGetMulti() containing a valid MultiPathRecord attribute with
+	   a set of zero or more PathRecords satisfying the constraints
+	   indicated in the MultiPathRecord received. The PathRecord Attribute
+	   ID shall be used in the response.
+	 */
+	p_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
+	osm_sa_respond(sa, p_madw, sizeof(ib_path_rec_t), &pr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+#endif
diff --git a/opensm/osm_sa_node_record.c b/opensm/osm_sa_node_record.c
new file mode 100644
index 0000000..4df2c91
--- /dev/null
+++ b/opensm/osm_sa_node_record.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_nr_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_nr_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_nr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_nr_rcv_new_nr(IN osm_sa_t * sa,
+		    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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D02: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New NodeRecord: node 0x%016" PRIx64
+		"\n\t\t\t\tport 0x%016" PRIx64 ", lid %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)),
+		cl_ntoh64(port_guid), cl_ntoh16(lid));
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_create_nr(IN osm_sa_t * sa,
+		       IN 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(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Looking for NodeRecord with LID: %u GUID:0x%016"
+		PRIx64 "\n", cl_ntoh16(match_lid),
+		cl_ntoh64(match_port_guid));
+
+	/*
+	   For switches, do not return the NodeInfo record
+	   for each port on the switch, just for port 0.
+	 */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
+		num_ports = 1;
+	else
+		num_ports = osm_node_get_num_physp(p_node);
+
+	for (port_num = 0; port_num < num_ports; port_num++) {
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+		if (!p_physp)
+			continue;
+
+		/* Check to see if the found p_physp and the requester physp
+		   share a pkey. If not - continue */
+		if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp))
+			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.
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Comparing LID: %u <= %u <= %u\n",
+				base_lid_ho, match_lid_ho, max_lid_ho);
+
+			if (match_lid_ho < base_lid_ho
+			    || match_lid_ho > max_lid_ho)
+				continue;
+		}
+
+		__osm_nr_rcv_new_nr(sa, p_node, p_list, port_guid, base_lid);
+
+	}
+
+	OSM_LOG_EXIT(sa->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;
+	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_sa_t *sa = p_ctxt->sa;
+	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->sa->p_log);
+
+	osm_dump_node_info(p_ctxt->sa->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) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Looking for node 0x%016" PRIx64
+			", found 0x%016" PRIx64 "\n",
+			cl_ntoh64(p_rcvd_rec->node_info.node_guid),
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+		if ((p_node->node_info.node_guid !=
+		     p_rcvd_rec->node_info.node_guid))
+			goto Exit;
+	}
+	if (comp_mask & IB_NR_COMPMASK_PORTGUID) {
+		match_port_guid = p_rcvd_rec->node_info.port_guid;
+	}
+	if (comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID) {
+		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(sa, p_node, p_ctxt->p_list,
+			       match_port_guid, match_lid, p_req_physp);
+
+Exit:
+	OSM_LOG_EXIT(p_ctxt->sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_nr_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_node_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_nr_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec = (ib_node_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D05: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D04: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_node_record(sa->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.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	cl_qmap_apply_func(&sa->p_subn->node_guid_tbl,
+			   __osm_nr_rcv_by_comp_mask, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_node_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_path_record.c b/opensm/osm_sa_path_record.c
new file mode 100644
index 0000000..5de496e
--- /dev/null
+++ b/opensm/osm_sa_path_record.c
@@ -0,0 +1,1811 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_pr_rcv_t.
+ * This object represents the PathRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <arpa/inet.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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_qos_policy.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_router.h>
+#include <opensm/osm_prefix_route.h>
+
+extern uint8_t osm_get_lash_sl(osm_opensm_t * p_osm,
+			       const osm_port_t * p_src_port,
+			       const osm_port_t * p_dst_port);
+
+typedef struct osm_pr_item {
+	cl_list_item_t list_item;
+	ib_path_rec_t path_rec;
+} osm_pr_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;
+} osm_path_parms_t;
+
+static const ib_gid_t zero_gid = { {0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00},
+};
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__osm_sa_path_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 = p_port->p_node;
+	vend_id = ib_node_info_get_vendor_id(&p_node->node_info);
+
+	return ((p_node->node_info.device_id == CL_HTON16(23108)) &&
+		((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) ||
+		 (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))));
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_sa_path_rec_apply_tavor_mtu_limit(IN const ib_path_rec_t * const p_pr,
+					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_path_rec_is_tavor_port(p_src_port) &&
+	    !__osm_sa_path_rec_is_tavor_port(p_dest_port))
+		return (FALSE);
+
+	/*
+	   we can apply the patch if either:
+	   1. No MTU required
+	   2. Required MTU <
+	   3. Required MTU = 1K or 512 or 256
+	   4. Required MTU > 256 or 512
+	 */
+	required_mtu = ib_path_rec_mtu(p_pr);
+	if ((comp_mask & IB_PR_COMPMASK_MTUSELEC) &&
+	    (comp_mask & IB_PR_COMPMASK_MTU)) {
+		switch (ib_path_rec_mtu_sel(p_pr)) {
+		case 0:	/* must be greater than */
+		case 2:	/* exact match */
+			if (IB_MTU_LEN_1024 < required_mtu)
+				return (FALSE);
+			break;
+
+		case 1:	/* must be less than */
+			/* can't be disqualified by this one */
+			break;
+
+		case 3:	/* largest available */
+			/* the ULP intentionally requested */
+			/* the largest MTU possible */
+			return (FALSE);
+			break;
+
+		default:
+			/* if we're here, there's a bug in ib_path_rec_mtu_sel() */
+			CL_ASSERT(FALSE);
+			break;
+		}
+	}
+
+	return (TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_rcv_get_path_parms(IN osm_sa_t * sa,
+			    IN const ib_path_rec_t * const p_pr,
+			    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_src_physp;
+	const osm_physp_t *p_dest_physp;
+	const osm_prtn_t *p_prtn = NULL;
+	osm_opensm_t *p_osm;
+	const ib_port_info_t *p_pi;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net16_t pkey;
+	uint8_t mtu;
+	uint8_t rate;
+	uint8_t pkt_life;
+	uint8_t required_mtu;
+	uint8_t required_rate;
+	uint8_t required_pkt_life;
+	uint8_t sl;
+	uint8_t in_port_num;
+	ib_net16_t dest_lid;
+	uint8_t i;
+	ib_slvl_table_t *p_slvl_tbl = NULL;
+	osm_qos_level_t *p_qos_level = NULL;
+	uint16_t valid_sl_mask = 0xffff;
+	int is_lash;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	dest_lid = cl_hton16(dest_lid_ho);
+
+	p_dest_physp = p_dest_port->p_physp;
+	p_physp = p_src_port->p_physp;
+	p_src_physp = p_physp;
+	p_pi = &p_physp->port_info;
+	p_osm = sa->p_subn->p_osm;
+
+	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 (sa->p_subn->opt.enable_quirks &&
+	    __osm_sa_path_rec_apply_tavor_mtu_limit(p_pr, p_src_port,
+						    p_dest_port, comp_mask))
+		if (mtu > IB_MTU_LEN_1024) {
+			mtu = IB_MTU_LEN_1024;
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Optimized Path MTU to 1K for Mellanox Tavor device\n");
+		}
+
+	/*
+	   Walk the subnet object from source to destination,
+	   tracking the most restrictive rate and mtu values along the way...
+
+	   If source port node is a switch, then p_physp should
+	   point to the port that routes the destination lid
+	 */
+
+	p_node = osm_physp_get_node_ptr(p_physp);
+
+	if (p_node->sw) {
+		/*
+		 * Source node is a switch.
+		 * Make sure that p_physp points to the out port of the
+		 * switch that routes to the destination lid (dest_lid_ho)
+		 */
+		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F02: "
+				"Cannot find routing to LID %u from switch for GUID 0x%016"
+				PRIx64 "\n", dest_lid_ho,
+				cl_ntoh64(osm_node_get_node_guid(p_node)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	if (sa->p_subn->opt.qos) {
+
+		/*
+		 * Whether this node is switch or CA, the IN port for
+		 * the sl2vl table is 0, because this is a source node.
+		 */
+		p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0);
+
+		/* update valid SLs that still exist on this route */
+		for (i = 0; i < IB_MAX_NUM_VLS; i++) {
+			if (valid_sl_mask & (1 << i) &&
+			    ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
+				valid_sl_mask &= ~(1 << i);
+		}
+		if (!valid_sl_mask) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"All the SLs lead to VL15 on this path\n");
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	/*
+	 * Same as above
+	 */
+	p_node = osm_physp_get_node_ptr(p_dest_physp);
+
+	if (p_node->sw) {
+		/*
+		 * if destination is switch, we want p_dest_physp to point to port 0
+		 */
+		p_dest_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+
+		if (p_dest_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F03: "
+				"Cannot find routing to LID %u from switch for GUID 0x%016"
+				PRIx64 "\n", dest_lid_ho,
+				cl_ntoh64(osm_node_get_node_guid(p_node)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	}
+
+	/*
+	 * Now go through the path step by step
+	 */
+
+	while (p_physp != p_dest_physp) {
+
+		p_node = osm_physp_get_node_ptr(p_physp);
+		p_physp = osm_physp_get_remote(p_physp);
+
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F05: "
+				"Cannot find remote phys port when routing to LID %u from node GUID 0x%016"
+				PRIx64 "\n", dest_lid_ho,
+				cl_ntoh64(osm_node_get_node_guid(p_node)));
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		in_port_num = osm_physp_get_port_num(p_physp);
+
+		/*
+		   This is point to point case (no switch in between)
+		 */
+		if (p_physp == p_dest_physp)
+			break;
+
+		p_node = osm_physp_get_node_ptr(p_physp);
+
+		if (!p_node->sw) {
+			/*
+			   There is some sort of problem in the subnet object!
+			   If this isn't a switch, we should have reached
+			   the destination by now!
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F06: "
+				"Internal error, bad path\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		/*
+		   Check parameters for the ingress port in this switch.
+		 */
+		p_pi = &p_physp->port_info;
+
+		if (mtu > ib_port_info_get_mtu_cap(p_pi))
+			mtu = ib_port_info_get_mtu_cap(p_pi);
+
+		if (rate > ib_port_info_compute_rate(p_pi))
+			rate = ib_port_info_compute_rate(p_pi);
+
+		/*
+		   Continue with the egress port on this switch.
+		 */
+		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
+		if (p_physp == 0) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F07: "
+				"Dead end on path to LID %u 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;
+		}
+
+		p_pi = &p_physp->port_info;
+
+		if (mtu > ib_port_info_get_mtu_cap(p_pi))
+			mtu = ib_port_info_get_mtu_cap(p_pi);
+
+		if (rate > ib_port_info_compute_rate(p_pi))
+			rate = ib_port_info_compute_rate(p_pi);
+
+		if (sa->p_subn->opt.qos) {
+			/*
+			 * Check SL2VL table of the switch and update valid SLs
+			 */
+			p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, in_port_num);
+			for (i = 0; i < IB_MAX_NUM_VLS; i++) {
+				if (valid_sl_mask & (1 << i) &&
+				    ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
+					valid_sl_mask &= ~(1 << i);
+			}
+			if (!valid_sl_mask) {
+				OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "All the SLs "
+					"lead to VL15 on this path\n");
+				status = IB_NOT_FOUND;
+				goto Exit;
+			}
+		}
+	}
+
+	/*
+	   p_physp now points to the destination
+	 */
+	p_pi = &p_physp->port_info;
+
+	if (mtu > ib_port_info_get_mtu_cap(p_pi))
+		mtu = ib_port_info_get_mtu_cap(p_pi);
+
+	if (rate > ib_port_info_compute_rate(p_pi))
+		rate = ib_port_info_compute_rate(p_pi);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Path min MTU = %u, min rate = %u\n", mtu, rate);
+
+	/*
+	 * Get QoS Level object according to the path request
+	 * and adjust path parameters according to QoS settings
+	 */
+	if (sa->p_subn->opt.qos &&
+	    sa->p_subn->p_qos_policy &&
+	    (p_qos_level =
+	     osm_qos_policy_get_qos_level_by_pr(sa->p_subn->p_qos_policy,
+						p_pr, p_src_physp, p_dest_physp,
+						comp_mask))) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"PathRecord request matches QoS Level '%s' (%s)\n",
+			p_qos_level->name, p_qos_level->use ?
+			p_qos_level->use : "no description");
+
+		if (p_qos_level->mtu_limit_set
+		    && (mtu > p_qos_level->mtu_limit))
+			mtu = p_qos_level->mtu_limit;
+
+		if (p_qos_level->rate_limit_set
+		    && (rate > p_qos_level->rate_limit))
+			rate = p_qos_level->rate_limit;
+
+		if (p_qos_level->sl_set) {
+			sl = p_qos_level->sl;
+			if (!(valid_sl_mask & (1 << sl))) {
+				status = IB_NOT_FOUND;
+				goto Exit;
+			}
+		}
+	}
+
+	/*
+	 * Set packet lifetime.
+	 * According to spec definition IBA 1.2 Table 205
+	 * PacketLifeTime description, for loopback paths,
+	 * packetLifeTime shall be zero.
+	 */
+	if (p_src_port == p_dest_port)
+		pkt_life = 0;
+	else if (p_qos_level && p_qos_level->pkt_life_set)
+		pkt_life = p_qos_level->pkt_life;
+	else
+		pkt_life = sa->p_subn->opt.subnet_timeout;
+
+	/*
+	   Determine if these values meet the user criteria
+	   and adjust appropriately
+	 */
+
+	/* we silently ignore cases where only the MTU selector is defined */
+	if ((comp_mask & IB_PR_COMPMASK_MTUSELEC) &&
+	    (comp_mask & IB_PR_COMPMASK_MTU)) {
+		required_mtu = ib_path_rec_mtu(p_pr);
+		switch (ib_path_rec_mtu_sel(p_pr)) {
+		case 0:	/* must be greater than */
+			if (mtu <= required_mtu)
+				status = IB_NOT_FOUND;
+			break;
+
+		case 1:	/* must be less than */
+			if (mtu >= required_mtu) {
+				/* adjust to use the highest mtu
+				   lower 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_path_rec_mtu_sel() */
+			CL_ASSERT(FALSE);
+			status = IB_ERROR;
+			break;
+		}
+	}
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* we silently ignore cases where only the Rate selector is defined */
+	if ((comp_mask & IB_PR_COMPMASK_RATESELEC) &&
+	    (comp_mask & IB_PR_COMPMASK_RATE)) {
+		required_rate = ib_path_rec_rate(p_pr);
+		switch (ib_path_rec_rate_sel(p_pr)) {
+		case 0:	/* must be greater than */
+			if (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_path_rec_mtu_sel() */
+			CL_ASSERT(FALSE);
+			status = IB_ERROR;
+			break;
+		}
+	}
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* we silently ignore cases where only the PktLife selector is defined */
+	if ((comp_mask & IB_PR_COMPMASK_PKTLIFETIMESELEC) &&
+	    (comp_mask & IB_PR_COMPMASK_PKTLIFETIME)) {
+		required_pkt_life = ib_path_rec_pkt_life(p_pr);
+		switch (ib_path_rec_pkt_life_sel(p_pr)) {
+		case 0:	/* must be greater than */
+			if (pkt_life <= required_pkt_life)
+				status = IB_NOT_FOUND;
+			break;
+
+		case 1:	/* must be less than */
+			if (pkt_life >= required_pkt_life) {
+				/* adjust the lifetime to use the highest possible
+				   lower then the required one */
+				if (required_pkt_life > 1)
+					pkt_life = required_pkt_life - 1;
+				else
+					status = IB_NOT_FOUND;
+			}
+			break;
+
+		case 2:	/* exact match */
+			if (pkt_life < required_pkt_life)
+				status = IB_NOT_FOUND;
+			else
+				pkt_life = required_pkt_life;
+			break;
+
+		case 3:	/* smallest available */
+			/* can't be disqualified by this one */
+			break;
+
+		default:
+			/* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */
+			CL_ASSERT(FALSE);
+			status = IB_ERROR;
+			break;
+		}
+	}
+
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/*
+	 * set Pkey for this path record request
+	 */
+
+	if ((comp_mask & IB_PR_COMPMASK_RAWTRAFFIC) &&
+	    (cl_ntoh32(p_pr->hop_flow_raw) & (1 << 31)))
+		pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp);
+
+	else if (comp_mask & IB_PR_COMPMASK_PKEY) {
+		/*
+		 * PR request has a specific pkey:
+		 * Check that source and destination share this pkey.
+		 * If QoS level has pkeys, check that this pkey exists
+		 * in the QoS level pkeys.
+		 * PR returned pkey is the requested pkey.
+		 */
+		pkey = p_pr->pkey;
+		if (!osm_physp_share_this_pkey(p_src_physp, p_dest_physp, pkey)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1A: "
+				"Ports 0x%016" PRIx64 " 0x%016" PRIx64
+				" do not share specified PKey 0x%04x\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
+				cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)),
+				cl_ntoh16(pkey));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+		if (p_qos_level && p_qos_level->pkey_range_len &&
+		    !osm_qos_level_has_pkey(p_qos_level, pkey)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1D: "
+				"Ports do not share PKeys defined by QoS level\n");
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	} else if (p_qos_level && p_qos_level->pkey_range_len) {
+		/*
+		 * PR request doesn't have a specific pkey, but QoS level
+		 * has pkeys - get shared pkey from QoS level pkeys
+		 */
+		pkey = osm_qos_level_get_shared_pkey(p_qos_level,
+						     p_src_physp, p_dest_physp);
+		if (!pkey) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1E: "
+				"Ports 0x%016" PRIx64 " 0x%016" PRIx64
+				" do not share PKeys defined by QoS level\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
+				cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	} else {
+		/*
+		 * Neither PR request nor QoS level have pkey.
+		 * Just get any shared pkey.
+		 */
+		pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp);
+		if (!pkey) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1B: "
+				"Ports 0x%016" PRIx64 " 0x%016" PRIx64
+				" do not have any shared PKeys\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
+				cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	if (pkey) {
+		p_prtn =
+		    (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
+					       pkey & cl_hton16((uint16_t) ~
+								0x8000));
+		if (p_prtn ==
+		    (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl))
+			p_prtn = NULL;
+	}
+
+	/*
+	 * Set PathRecord SL.
+	 */
+
+	is_lash = (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_LASH);
+
+	if (comp_mask & IB_PR_COMPMASK_SL) {
+		/*
+		 * Specific SL was requested
+		 */
+		sl = ib_path_rec_sl(p_pr);
+
+		if (p_qos_level && p_qos_level->sl_set
+		    && (p_qos_level->sl != sl)) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1F: "
+				"QoS constaraints: required PathRecord SL (%u) "
+				"doesn't match QoS policy SL (%u)\n", sl,
+				p_qos_level->sl);
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+		if (is_lash
+		    && osm_get_lash_sl(p_osm, p_src_port, p_dest_port) != sl) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F23: "
+				"Required PathRecord SL (%u) doesn't "
+				"match LASH SL\n", sl);
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+
+	} else if (is_lash) {
+		/*
+		 * No specific SL in PathRecord request.
+		 * If it's LASH routing - use its SL.
+		 * slid and dest_lid are stored in network in lash.
+		 */
+		sl = osm_get_lash_sl(p_osm, p_src_port, p_dest_port);
+	} else if (p_qos_level && p_qos_level->sl_set) {
+		/*
+		 * No specific SL was requested, and we're not in
+		 * LASH routing, but there is an SL in QoS level.
+		 */
+		sl = p_qos_level->sl;
+
+		if (pkey && p_prtn && p_prtn->sl != p_qos_level->sl)
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"QoS level SL (%u) overrides partition SL (%u)\n",
+				p_qos_level->sl, p_prtn->sl);
+
+	} else if (pkey) {
+		/*
+		 * No specific SL in request or in QoS level - use partition SL
+		 */
+		if (!p_prtn) {
+			sl = OSM_DEFAULT_SL;
+			/* this may be possible when pkey tables are created somehow in
+			   previous runs or things are going wrong here */
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1C: "
+				"No partition found for PKey 0x%04x - using default SL %d\n",
+				cl_ntoh16(pkey), sl);
+		} else
+			sl = p_prtn->sl;
+	} else if (sa->p_subn->opt.qos) {
+		if (valid_sl_mask & (1 << OSM_DEFAULT_SL))
+			sl = OSM_DEFAULT_SL;
+		else {
+			for (i = 0; i < IB_MAX_NUM_VLS; i++)
+				if (valid_sl_mask & (1 << i))
+					break;
+			sl = i;
+		}
+	} else
+		sl = OSM_DEFAULT_SL;
+
+	if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << sl))) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F24: "
+			"Selected SL (%u) leads to VL15\n", sl);
+		status = IB_NOT_FOUND;
+		goto Exit;
+	}
+
+	/* reset pkey when raw traffic */
+	if (comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&
+	    cl_ntoh32(p_pr->hop_flow_raw) & (1 << 31))
+		pkey = 0;
+
+	p_parms->mtu = mtu;
+	p_parms->rate = rate;
+	p_parms->pkt_life = pkt_life;
+	p_parms->pkey = pkey;
+	p_parms->sl = sl;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Path params: mtu = %u, rate = %u,"
+		" packet lifetime = %u, pkey = 0x%04X, sl = %u\n",
+		mtu, rate, pkt_life, cl_ntoh16(pkey), sl);
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_build_pr(IN osm_sa_t * sa,
+		      IN const osm_port_t * const p_src_port,
+		      IN const osm_port_t * const p_dest_port,
+		      IN const ib_gid_t * const p_dgid,
+		      IN const uint16_t src_lid_ho,
+		      IN const uint16_t dest_lid_ho,
+		      IN const uint8_t preference,
+		      IN const osm_path_parms_t * 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;
+	boolean_t is_nonzero_gid = 0;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_src_physp = p_src_port->p_physp;
+
+	if (p_dgid) {
+		if (memcmp(p_dgid, &zero_gid, sizeof(*p_dgid)))
+			is_nonzero_gid = 1;
+	}
+
+	if (is_nonzero_gid)
+		p_pr->dgid = *p_dgid;
+	else {
+		p_dest_physp = p_dest_port->p_physp;
+
+		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);
+
+	/* Only set HopLimit if going through a router */
+	if (is_nonzero_gid)
+		p_pr->hop_flow_raw |= cl_hton32(IB_HOPLIMIT_MAX);
+
+	p_pr->pkey = p_parms->pkey;
+	ib_path_rec_set_sl(p_pr, p_parms->sl);
+	ib_path_rec_set_qos_class(p_pr, 0);
+	p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80);
+	p_pr->rate = (uint8_t) (p_parms->rate | 0x80);
+
+	/* According to 1.2 spec definition Table 205 PacketLifeTime description,
+	   for loopback paths, packetLifeTime shall be zero. */
+	if (p_src_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(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_pr_item_t *
+__osm_pr_rcv_get_lid_pair_path(IN osm_sa_t * sa,
+			       IN const ib_path_rec_t * const p_pr,
+			       IN const osm_port_t * const p_src_port,
+			       IN const osm_port_t * const p_dest_port,
+			       IN const ib_gid_t * const p_dgid,
+			       IN const uint16_t src_lid_ho,
+			       IN const uint16_t dest_lid_ho,
+			       IN const ib_net64_t comp_mask,
+			       IN const uint8_t preference)
+{
+	osm_path_parms_t path_parms;
+	osm_path_parms_t rev_path_parms;
+	osm_pr_item_t *p_pr_item;
+	ib_api_status_t status, rev_path_status;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID %u, Dest LID %u\n",
+		src_lid_ho, dest_lid_ho);
+
+	p_pr_item = malloc(sizeof(*p_pr_item));
+	if (p_pr_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F01: "
+			"Unable to allocate path record\n");
+		goto Exit;
+	}
+	memset(p_pr_item, 0, sizeof(*p_pr_item));
+
+	status = __osm_pr_rcv_get_path_parms(sa, p_pr, p_src_port,
+					     p_dest_port, dest_lid_ho,
+					     comp_mask, &path_parms);
+
+	if (status != IB_SUCCESS) {
+		free(p_pr_item);
+		p_pr_item = NULL;
+		goto Exit;
+	}
+
+	/* now try the reversible path */
+	rev_path_status = __osm_pr_rcv_get_path_parms(sa, p_pr, 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_PR_COMPMASK_REVERSIBLE) {
+		if ((!path_parms.reversible && (p_pr->num_path & 0x80))) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Requested reversible path but failed to get one\n");
+
+			free(p_pr_item);
+			p_pr_item = NULL;
+			goto Exit;
+		}
+	}
+
+	__osm_pr_rcv_build_pr(sa, p_src_port, p_dest_port, p_dgid,
+			      src_lid_ho, dest_lid_ho, preference, &path_parms,
+			      &p_pr_item->path_rec);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (p_pr_item);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_get_port_pair_paths(IN osm_sa_t * sa,
+				 IN const osm_madw_t * const p_madw,
+				 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 ib_gid_t * const p_dgid,
+				 IN const ib_net64_t comp_mask,
+				 IN cl_qlist_t * const p_list)
+{
+	const ib_path_rec_t *p_pr;
+	const ib_sa_mad_t *p_sa_mad;
+	osm_pr_item_t *p_pr_item;
+	uint16_t src_lid_min_ho;
+	uint16_t src_lid_max_ho;
+	uint16_t dest_lid_min_ho;
+	uint16_t dest_lid_max_ho;
+	uint16_t src_lid_ho;
+	uint16_t dest_lid_ho;
+	uint32_t path_num;
+	uint8_t preference;
+	uintn_t iterations;
+	uintn_t src_offset;
+	uintn_t dest_offset;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Src port 0x%016" PRIx64 ", Dst port 0x%016" PRIx64 "\n",
+		cl_ntoh64(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(sa->p_log, p_req_port, p_src_port) == FALSE
+	    || osm_port_share_pkey(sa->p_log, p_req_port,
+				   p_dest_port) == FALSE
+	    || osm_port_share_pkey(sa->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;
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_pr = (ib_path_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	/*
+	   We shouldn't be here if the paths are disqualified in some way...
+	   Thus, we assume every possible connection is valid.
+
+	   We desire to return high-quality paths first.
+	   In OpenSM, higher quality means least overlap with other paths.
+	   This is acheived in practice by returning paths with
+	   different LID value on each end, which means these
+	   paths are more redundant that paths with the same LID repeated
+	   on one side.  For example, in OpenSM the paths between two
+	   endpoints with LMC = 1 might be as follows:
+
+	   Port A, LID 1 <-> Port B, LID 3
+	   Port A, LID 1 <-> Port B, LID 4
+	   Port A, LID 2 <-> Port B, LID 3
+	   Port A, LID 2 <-> Port B, LID 4
+
+	   The OpenSM unicast routing algorithms attempt to disperse each path
+	   to as varied a physical path as is reasonable.  1<->3 and 1<->4 have
+	   more physical overlap (hence less redundancy) than 1<->3 and 2<->4.
+
+	   OpenSM ranks paths in three preference groups:
+
+	   Preference Value    Description
+	   ----------------    -------------------------------------------
+	   0             Redundant in both directions with other
+	   pref value = 0 paths
+
+	   1             Redundant in one direction with other
+	   pref value = 0 and pref value = 1 paths
+
+	   2             Not redundant in either direction with
+	   other paths
+
+	   3-FF          Unused
+
+	   SA clients don't need to know these details, only that the lower
+	   preference paths are preferred, as stated in the spec.  The paths
+	   may not actually be physically redundant depending on the topology
+	   of the subnet, but the point of LMC > 0 is to offer redundancy,
+	   so it is assumed that the subnet is physically appropriate for the
+	   specified LMC value.  A more advanced implementation would inspect for
+	   physical redundancy, but I'm not going to bother with that now.
+	 */
+
+	/*
+	   Refine our search if the client specified end-point LIDs
+	 */
+	if (comp_mask & IB_PR_COMPMASK_DLID) {
+		dest_lid_min_ho = cl_ntoh16(p_pr->dlid);
+		dest_lid_max_ho = cl_ntoh16(p_pr->dlid);
+	} else
+		osm_port_get_lid_range_ho(p_dest_port, &dest_lid_min_ho,
+					  &dest_lid_max_ho);
+
+	if (comp_mask & IB_PR_COMPMASK_SLID) {
+		src_lid_min_ho = cl_ntoh16(p_pr->slid);
+		src_lid_max_ho = cl_ntoh16(p_pr->slid);
+	} else
+		osm_port_get_lid_range_ho(p_src_port, &src_lid_min_ho,
+					  &src_lid_max_ho);
+
+	if (src_lid_min_ho == 0) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F20:"
+			"Obtained source LID of 0. No such LID possible\n");
+		goto Exit;
+	}
+
+	if (dest_lid_min_ho == 0) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F21:"
+			"Obtained destination LID of 0. No such LID possible\n");
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Src LIDs [%u-%u], Dest LIDs [%u-%u]\n",
+		src_lid_min_ho, src_lid_max_ho,
+		dest_lid_min_ho, dest_lid_max_ho);
+
+	src_lid_ho = src_lid_min_ho;
+	dest_lid_ho = dest_lid_min_ho;
+
+	/*
+	   Preferred paths come first in OpenSM
+	 */
+	preference = 0;
+	path_num = 0;
+
+	/* If SubnAdmGet, assume NumbPaths 1 (1.2 erratum) */
+	if (p_sa_mad->method != IB_MAD_METHOD_GET)
+		if (comp_mask & IB_PR_COMPMASK_NUMBPATH)
+			iterations = ib_path_rec_num_path(p_pr);
+		else
+			iterations = (uintn_t) (-1);
+	else
+		iterations = 1;
+
+	while (path_num < iterations) {
+		/*
+		   These paths are "fully redundant"
+		 */
+
+		p_pr_item = __osm_pr_rcv_get_lid_pair_path(sa, p_pr,
+							   p_src_port,
+							   p_dest_port, p_dgid,
+							   src_lid_ho,
+							   dest_lid_ho,
+							   comp_mask,
+							   preference);
+
+		if (p_pr_item) {
+			cl_qlist_insert_tail(p_list, &p_pr_item->list_item);
+			++path_num;
+		}
+
+		if (++src_lid_ho > src_lid_max_ho)
+			break;
+
+		if (++dest_lid_ho > dest_lid_max_ho)
+			break;
+	}
+
+	/*
+	   Check if we've accumulated all the paths that the user cares to see
+	 */
+	if (path_num == iterations)
+		goto Exit;
+
+	/*
+	   Don't bother reporting preference 1 paths for now.
+	   It's more trouble than it's worth and can only occur
+	   if ports have different LMC values, which isn't supported
+	   by OpenSM right now anyway.
+	 */
+	preference = 2;
+	src_lid_ho = src_lid_min_ho;
+	dest_lid_ho = dest_lid_min_ho;
+	src_offset = 0;
+	dest_offset = 0;
+
+	/*
+	   Iterate over the remaining paths
+	 */
+	while (path_num < iterations) {
+		dest_offset++;
+		dest_lid_ho++;
+
+		if (dest_lid_ho > dest_lid_max_ho) {
+			src_offset++;
+			src_lid_ho++;
+
+			if (src_lid_ho > src_lid_max_ho)
+				break;	/* done */
+
+			dest_offset = 0;
+			dest_lid_ho = dest_lid_min_ho;
+		}
+
+		/*
+		   These paths are "fully non-redundant" with paths already
+		   identified above and consequently not of much value.
+
+		   Don't return paths we already identified above, as indicated
+		   by the offset values being equal.
+		 */
+		if (src_offset == dest_offset)
+			continue;	/* already reported */
+
+		p_pr_item = __osm_pr_rcv_get_lid_pair_path(sa, p_pr,
+							   p_src_port,
+							   p_dest_port, p_dgid,
+							   src_lid_ho,
+							   dest_lid_ho,
+							   comp_mask,
+							   preference);
+
+		if (p_pr_item) {
+			cl_qlist_insert_tail(p_list, &p_pr_item->list_item);
+			++path_num;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_pr_rcv_get_end_points(IN osm_sa_t * sa,
+			    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,
+			    OUT ib_gid_t * const p_dgid)
+{
+	const ib_path_rec_t *p_pr;
+	const ib_sa_mad_t *p_sa_mad;
+	ib_net64_t comp_mask;
+	ib_net64_t dest_guid;
+	ib_api_status_t status;
+	ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;
+	osm_router_t *p_rtr;
+	osm_port_t *p_rtr_port;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/*
+	   Determine what fields are valid and then get a pointer
+	   to the source and destination port objects, if possible.
+	 */
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_pr = (ib_path_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	/*
+	   Check a few easy disqualifying cases up front before getting
+	   into the endpoints.
+	 */
+
+	if (comp_mask & IB_PR_COMPMASK_SGID) {
+		if (!ib_gid_is_link_local(&p_pr->sgid)) {
+			if (ib_gid_get_subnet_prefix(&p_pr->sgid) !=
+			    sa->p_subn->opt.subnet_prefix) {
+				/*
+				   This 'error' is the client's fault (bad gid)
+				   so don't enter it as an error in our own log.
+				   Return an error response to the client.
+				 */
+				OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+					"Non local SGID subnet prefix 0x%016"
+					PRIx64 "\n",
+					cl_ntoh64(p_pr->sgid.unicast.prefix));
+
+				sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+				goto Exit;
+			}
+		}
+
+		*pp_src_port = osm_get_port_by_guid(sa->p_subn,
+						    p_pr->sgid.unicast.
+						    interface_id);
+		if (!*pp_src_port) {
+			/*
+			   This 'error' is the client's fault (bad gid) so
+			   don't enter it as an error in our own log.
+			   Return an error response to the client.
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+				"No source port with GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_pr->sgid.unicast.interface_id));
+
+			sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+			goto Exit;
+		}
+	} else {
+		*pp_src_port = 0;
+		if (comp_mask & IB_PR_COMPMASK_SLID) {
+			status = cl_ptr_vector_at(&sa->p_subn->port_lid_tbl,
+						  cl_ntoh16(p_pr->slid),
+						  (void **)pp_src_port);
+
+			if ((status != CL_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(sa->p_log, OSM_LOG_VERBOSE,
+					"No source port with LID %u\n",
+					cl_ntoh16(p_pr->slid));
+
+				sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+				goto Exit;
+			}
+		}
+	}
+
+	if (p_dgid)
+		memset(p_dgid, 0, sizeof(*p_dgid));
+
+	if (comp_mask & IB_PR_COMPMASK_DGID) {
+		dest_guid = p_pr->dgid.unicast.interface_id;
+		if (!ib_gid_is_link_local(&p_pr->dgid)) {
+			if (!ib_gid_is_multicast(&p_pr->dgid) &&
+			    ib_gid_get_subnet_prefix(&p_pr->dgid) !=
+			    sa->p_subn->opt.subnet_prefix) {
+				OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+					"Non local DGID subnet prefix 0x%016"
+					PRIx64 "\n",
+					cl_ntoh64(p_pr->dgid.unicast.prefix));
+
+				/* Find the router port that is configured to
+				   handle this prefix, if any */
+				osm_prefix_route_t *route = NULL;
+				osm_prefix_route_t *r = (osm_prefix_route_t *)
+					cl_qlist_head(&sa->p_subn->prefix_routes_list);
+
+				while (r != (osm_prefix_route_t *)
+				       cl_qlist_end(&sa->p_subn->prefix_routes_list))
+				{
+					if (r->prefix == p_pr->dgid.unicast.prefix ||
+					    r->prefix == 0)
+					{
+						route = r;
+						break;
+					}
+					r = (osm_prefix_route_t *) cl_qlist_next(&r->list_item);
+				}
+
+				if (!route) {
+					/*
+					  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.
+					*/
+					sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+					goto Exit;
+				} else if (route->guid == 0) {
+					/* first router */
+					p_rtr = (osm_router_t *)
+						cl_qmap_head(&sa->
+							     p_subn->
+							     rtr_guid_tbl);
+				} else {
+					p_rtr = (osm_router_t *)
+						cl_qmap_get(&sa->
+							    p_subn->
+							    rtr_guid_tbl,
+							    route->guid);
+				}
+
+				if (p_rtr ==
+				    (osm_router_t *) cl_qmap_end(&sa->
+								 p_subn->
+								 rtr_guid_tbl))
+				{
+					OSM_LOG(sa->p_log, OSM_LOG_ERROR,
+						"ERR 1F22: "
+						"Off subnet DGID but router not found\n");
+					sa_status =
+					    IB_SA_MAD_STATUS_INVALID_GID;
+					goto Exit;
+				}
+
+				p_rtr_port = osm_router_get_port_ptr(p_rtr);
+				dest_guid = osm_port_get_guid(p_rtr_port);
+				if (p_dgid)
+					*p_dgid = p_pr->dgid;
+			}
+		}
+
+		*pp_dest_port = osm_get_port_by_guid(sa->p_subn, dest_guid);
+		if (!*pp_dest_port) {
+			/*
+			   This 'error' is the client's fault (bad gid) so
+			   don't enter it as an error in our own log.
+			   Return an error response to the client.
+			 */
+			OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+				"No dest port with GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(dest_guid));
+
+			sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+			goto Exit;
+		}
+	} else {
+		*pp_dest_port = 0;
+		if (comp_mask & IB_PR_COMPMASK_DLID) {
+			status = cl_ptr_vector_at(&sa->p_subn->port_lid_tbl,
+						  cl_ntoh16(p_pr->dlid),
+						  (void **)pp_dest_port);
+
+			if ((status != CL_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(sa->p_log, OSM_LOG_VERBOSE,
+					"No dest port with LID %u\n",
+					cl_ntoh16(p_pr->dlid));
+
+				sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+				goto Exit;
+			}
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (sa_status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_world(IN osm_sa_t * sa,
+			   IN const osm_madw_t * const p_madw,
+			   IN const osm_port_t * const requester_port,
+			   IN const ib_gid_t * const p_dgid,
+			   IN const ib_net64_t comp_mask,
+			   IN cl_qlist_t * const p_list)
+{
+	const cl_qmap_t *p_tbl;
+	const osm_port_t *p_dest_port;
+	const osm_port_t *p_src_port;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/*
+	   Iterate the entire port space over itself.
+	   A path record from a port to itself is legit, so no
+	   need for a special case there.
+
+	   We compute both A -> B and B -> A, since we don't have
+	   any check to determine the reversability of the paths.
+	 */
+	p_tbl = &sa->p_subn->port_guid_tbl;
+
+	p_dest_port = (osm_port_t *) cl_qmap_head(p_tbl);
+	while (p_dest_port != (osm_port_t *) cl_qmap_end(p_tbl)) {
+		p_src_port = (osm_port_t *) cl_qmap_head(p_tbl);
+		while (p_src_port != (osm_port_t *) cl_qmap_end(p_tbl)) {
+			__osm_pr_rcv_get_port_pair_paths(sa, p_madw,
+							 requester_port,
+							 p_src_port,
+							 p_dest_port, p_dgid,
+							 comp_mask, p_list);
+
+			p_src_port =
+			    (osm_port_t *) cl_qmap_next(&p_src_port->map_item);
+		}
+
+		p_dest_port =
+		    (osm_port_t *) cl_qmap_next(&p_dest_port->map_item);
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_half(IN osm_sa_t * sa,
+			  IN const osm_madw_t * const p_madw,
+			  IN const osm_port_t * const requester_port,
+			  IN const osm_port_t * const p_src_port,
+			  IN const osm_port_t * const p_dest_port,
+			  IN const ib_gid_t * const p_dgid,
+			  IN const ib_net64_t comp_mask,
+			  IN cl_qlist_t * const p_list)
+{
+	const cl_qmap_t *p_tbl;
+	const osm_port_t *p_port;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	/*
+	   Iterate over every port, looking for matches...
+	   A path record from a port to itself is legit, so no
+	   need to special case that one.
+	 */
+	p_tbl = &sa->p_subn->port_guid_tbl;
+
+	if (p_src_port) {
+		/*
+		   The src port if fixed, so iterate over destination ports.
+		 */
+		p_port = (osm_port_t *) cl_qmap_head(p_tbl);
+		while (p_port != (osm_port_t *) cl_qmap_end(p_tbl)) {
+			__osm_pr_rcv_get_port_pair_paths(sa, p_madw,
+							 requester_port,
+							 p_src_port, p_port,
+							 p_dgid, comp_mask,
+							 p_list);
+			p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item);
+		}
+	} else {
+		/*
+		   The dest port if fixed, so iterate over source ports.
+		 */
+		p_port = (osm_port_t *) cl_qmap_head(p_tbl);
+		while (p_port != (osm_port_t *) cl_qmap_end(p_tbl)) {
+			__osm_pr_rcv_get_port_pair_paths(sa, p_madw,
+							 requester_port, p_port,
+							 p_dest_port, p_dgid,
+							 comp_mask, p_list);
+			p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item);
+		}
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_pair(IN osm_sa_t * sa,
+			  IN const osm_madw_t * const p_madw,
+			  IN const osm_port_t * const requester_port,
+			  IN const osm_port_t * const p_src_port,
+			  IN const osm_port_t * const p_dest_port,
+			  IN const ib_gid_t * const p_dgid,
+			  IN const ib_net64_t comp_mask,
+			  IN cl_qlist_t * const p_list)
+{
+	OSM_LOG_ENTER(sa->p_log);
+
+	__osm_pr_rcv_get_port_pair_paths(sa, p_madw, requester_port,
+					 p_src_port, p_dest_port, p_dgid,
+					 comp_mask, p_list);
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mgrp_t *pr_get_mgrp(IN osm_sa_t * sa,
+			       IN const osm_madw_t * const p_madw)
+{
+	ib_path_rec_t *p_pr;
+	const ib_sa_mad_t *p_sa_mad;
+	ib_net64_t comp_mask;
+	osm_mgrp_t *mgrp = NULL;
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_pr = (ib_path_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	if ((comp_mask & IB_PR_COMPMASK_DGID) &&
+	    !(mgrp = osm_get_mgrp_by_mgid(sa, &p_pr->dgid))) {
+		char gid_str[INET6_ADDRSTRLEN];
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F09: "
+			"No MC group found for PathRecord destination GID %s\n",
+			inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str,
+				  sizeof gid_str));
+		goto Exit;
+	}
+
+	if (comp_mask & IB_PR_COMPMASK_DLID) {
+		if (mgrp) {
+			/* check that the MLID in the MC group is */
+			/* the same as the DLID in the PathRecord */
+			if (mgrp->mlid != p_pr->dlid) {
+				/* Note: perhaps this might be better indicated as an invalid request */
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F10: "
+					"MC group MLID 0x%x does not match "
+					"PathRecord destination LID 0x%x\n",
+					mgrp->mlid, p_pr->dlid);
+				mgrp = NULL;
+				goto Exit;
+			}
+		} else if (!(mgrp = osm_get_mgrp_by_mlid(sa->p_subn, p_pr->dlid)))
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F11: "
+				"No MC group found for PathRecord "
+				"destination LID 0x%x\n", p_pr->dlid);
+	}
+
+Exit:
+	return mgrp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_match_mgrp_attributes(IN osm_sa_t * sa,
+			       IN const osm_madw_t * const p_madw,
+			       IN const osm_mgrp_t * const p_mgrp)
+{
+	const ib_path_rec_t *p_pr;
+	const ib_sa_mad_t *p_sa_mad;
+	ib_net64_t comp_mask;
+	ib_api_status_t status = IB_ERROR;
+	uint32_t flow_label;
+	uint8_t sl;
+	uint8_t hop_limit;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_pr = (ib_path_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	/* If SGID and/or SLID specified, should validate as member of MC group */
+	/* Also, MTU, rate, packet lifetime, and raw traffic requested are not currently checked */
+	if (comp_mask & IB_PR_COMPMASK_PKEY) {
+		if (p_pr->pkey != p_mgrp->mcmember_rec.pkey)
+			goto Exit;
+	}
+
+	ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+				  &sl, &flow_label, &hop_limit);
+
+	if (comp_mask & IB_PR_COMPMASK_SL) {
+		if (ib_path_rec_sl(p_pr) != sl)
+			goto Exit;
+	}
+
+	/* If SubnAdmGet, assume NumbPaths of 1 (1.2 erratum) */
+	if ((comp_mask & IB_PR_COMPMASK_NUMBPATH) &&
+	    (p_sa_mad->method != IB_MAD_METHOD_GET)) {
+		if (ib_path_rec_num_path(p_pr) == 0)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_PR_COMPMASK_FLOWLABEL) {
+		if (ib_path_rec_flow_lbl(p_pr) != flow_label)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_PR_COMPMASK_HOPLIMIT) {
+		if (ib_path_rec_hop_limit(p_pr) != hop_limit)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_PR_COMPMASK_TCLASS) {
+		if (p_pr->tclass != p_mgrp->mcmember_rec.tclass)
+			goto Exit;
+	}
+
+	status = IB_SUCCESS;
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__osm_pr_rcv_check_mcast_dest(IN osm_sa_t * sa,
+			      IN const osm_madw_t * const p_madw)
+{
+	const ib_path_rec_t *p_pr;
+	const ib_sa_mad_t *p_sa_mad;
+	ib_net64_t comp_mask;
+	int is_multicast = 0;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_pr = (ib_path_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	if (comp_mask & IB_PR_COMPMASK_DGID) {
+		is_multicast = ib_gid_is_multicast(&p_pr->dgid);
+		if (!is_multicast)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_PR_COMPMASK_DLID) {
+		if (cl_ntoh16(p_pr->dlid) >= IB_LID_MCAST_START_HO &&
+		    cl_ntoh16(p_pr->dlid) <= IB_LID_MCAST_END_HO)
+			is_multicast = 1;
+		else if (is_multicast) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F12: "
+				"PathRecord request indicates MGID but not MLID\n");
+			is_multicast = -1;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (is_multicast);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	const ib_path_rec_t *p_pr;
+	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 pr_list;
+	ib_gid_t dgid;
+	ib_net16_t sa_status;
+	osm_port_t *requester_port;
+	int ret;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	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_PATH_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_sa_mad->method != IB_MAD_METHOD_GET &&
+	    p_sa_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F17: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	requester_port = osm_get_port_by_mad_addr(sa->p_log, sa->p_subn,
+						  osm_madw_get_mad_addr_ptr
+						  (p_madw));
+	if (requester_port == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F16: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_path_record(sa->p_log, p_pr, 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(sa->p_lock);
+
+	/* Handle multicast destinations separately */
+	if ((ret = __osm_pr_rcv_check_mcast_dest(sa, p_madw)) < 0) {
+		/* Multicast DGID with unicast DLID */
+		cl_plock_release(sa->p_lock);
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_INVALID_FIELD);
+		goto Exit;
+	}
+
+	if (ret > 0)
+		goto McastDest;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unicast destination requested\n");
+
+	sa_status = __osm_pr_rcv_get_end_points(sa, p_madw,
+						&p_src_port, &p_dest_port,
+						&dgid);
+
+	if (sa_status == IB_SA_MAD_STATUS_SUCCESS) {
+		/*
+		   What happens next depends on the type of endpoint information
+		   that was specified....
+		 */
+		if (p_src_port) {
+			if (p_dest_port)
+				__osm_pr_rcv_process_pair(sa, p_madw,
+							  requester_port,
+							  p_src_port,
+							  p_dest_port, &dgid,
+							  p_sa_mad->comp_mask,
+							  &pr_list);
+			else
+				__osm_pr_rcv_process_half(sa, p_madw,
+							  requester_port,
+							  p_src_port, NULL,
+							  &dgid,
+							  p_sa_mad->comp_mask,
+							  &pr_list);
+		} else {
+			if (p_dest_port)
+				__osm_pr_rcv_process_half(sa, p_madw,
+							  requester_port, NULL,
+							  p_dest_port, &dgid,
+							  p_sa_mad->comp_mask,
+							  &pr_list);
+			else
+				/*
+				   Katie, bar the door!
+				 */
+				__osm_pr_rcv_process_world(sa, p_madw,
+							   requester_port,
+							   &dgid,
+							   p_sa_mad->comp_mask,
+							   &pr_list);
+		}
+	}
+	goto Unlock;
+
+McastDest:
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Multicast destination requested\n");
+	{
+		osm_mgrp_t *p_mgrp = NULL;
+		ib_api_status_t status;
+		osm_pr_item_t *p_pr_item;
+		uint32_t flow_label;
+		uint8_t sl;
+		uint8_t hop_limit;
+
+		/* First, get the MC info */
+		p_mgrp = pr_get_mgrp(sa, p_madw);
+
+		if (!p_mgrp)
+			goto Unlock;
+
+		/* Make sure the rest of the PathRecord matches the MC group attributes */
+		status = __osm_pr_match_mgrp_attributes(sa, p_madw, p_mgrp);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F19: "
+				"MC group attributes don't match PathRecord request\n");
+			goto Unlock;
+		}
+
+		p_pr_item = malloc(sizeof(*p_pr_item));
+		if (p_pr_item == NULL) {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F18: "
+				"Unable to allocate path record for MC group\n");
+			goto Unlock;
+		}
+		memset(p_pr_item, 0, sizeof(*p_pr_item));
+
+		/* Copy PathRecord request into response */
+		p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+		p_pr = (ib_path_rec_t *)
+		    ib_sa_mad_get_payload_ptr(p_sa_mad);
+		p_pr_item->path_rec = *p_pr;
+
+		/* Now, use the MC info to cruft up the PathRecord response */
+		p_pr_item->path_rec.dgid = p_mgrp->mcmember_rec.mgid;
+		p_pr_item->path_rec.dlid = p_mgrp->mcmember_rec.mlid;
+		p_pr_item->path_rec.tclass = p_mgrp->mcmember_rec.tclass;
+		p_pr_item->path_rec.num_path = 1;
+		p_pr_item->path_rec.pkey = p_mgrp->mcmember_rec.pkey;
+
+		/* MTU, rate, and packet lifetime should be exactly */
+		p_pr_item->path_rec.mtu = (2 << 6) | p_mgrp->mcmember_rec.mtu;
+		p_pr_item->path_rec.rate = (2 << 6) | p_mgrp->mcmember_rec.rate;
+		p_pr_item->path_rec.pkt_life =
+		    (2 << 6) | p_mgrp->mcmember_rec.pkt_life;
+
+		/* SL, Hop Limit, and Flow Label */
+		ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+					  &sl, &flow_label, &hop_limit);
+		ib_path_rec_set_sl(&p_pr_item->path_rec, sl);
+		ib_path_rec_set_qos_class(&p_pr_item->path_rec, 0);
+
+		/* HopLimit is not yet set in non link local MC groups */
+		/* If it were, this would not be needed */
+		if (ib_mgid_get_scope(&p_mgrp->mcmember_rec.mgid) != IB_MC_SCOPE_LINK_LOCAL)
+			hop_limit = IB_HOPLIMIT_MAX;
+
+		p_pr_item->path_rec.hop_flow_raw =
+			cl_hton32(hop_limit) | (flow_label << 8);
+
+		cl_qlist_insert_tail(&pr_list, &p_pr_item->list_item);
+	}
+
+Unlock:
+	cl_plock_release(sa->p_lock);
+
+	/* Now, (finally) respond to the PathRecord request */
+	osm_sa_respond(sa, p_madw, sizeof(ib_path_rec_t), &pr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_pkey_record.c b/opensm/osm_sa_pkey_record.c
new file mode 100644
index 0000000..d57c239
--- /dev/null
+++ b/opensm/osm_sa_pkey_record.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_pkey_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_pkey_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_create(IN osm_sa_t * sa,
+		     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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4602: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+		lid = p_physp->port_info.base_lid;
+	else
+		lid = osm_node_get_base_lid(p_physp->p_node, 0);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New P_Key table for: port 0x%016" PRIx64
+		", lid %u, port %u Block:%u\n",
+		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+		cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block);
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_check_physp(IN osm_sa_t * sa,
+			  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(sa->p_log);
+
+	/* we got here with the phys port - all is left is to get the right block */
+	if (comp_mask & IB_PKEY_COMPMASK_BLOCK) {
+		__osm_sa_pkey_create(sa, p_physp, p_ctxt, p_ctxt->block_num);
+	} else {
+		num_blocks =
+		    osm_pkey_tbl_get_num_blocks(osm_physp_get_pkey_tbl
+						(p_physp));
+		for (block = 0; block < num_blocks; block++) {
+			__osm_sa_pkey_create(sa, p_physp, p_ctxt, block);
+		}
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_by_comp_mask(IN osm_sa_t * sa,
+			   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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	port_num = p_rcvd_rec->port_num;
+	p_req_physp = p_ctxt->p_req_physp;
+
+	/* if this is a switch port we can search all ports
+	   otherwise we must be looking on port 0 */
+	if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) {
+		/* we put it in the comp mask and port num */
+		port_num = p_port->p_physp->port_num;
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Using Physical Default Port Number: 0x%X (for End Node)\n",
+			port_num);
+		comp_mask |= IB_PKEY_COMPMASK_PORT;
+	}
+
+	if (comp_mask & IB_PKEY_COMPMASK_PORT) {
+		if (port_num < osm_node_get_num_physp(p_port->p_node)) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_port->p_node, port_num);
+			/* Check that the p_physp is valid, and that is shares a pkey
+			   with the p_req_physp. */
+			if (p_physp &&
+			    (osm_physp_share_pkey
+			     (sa->p_log, p_req_physp, p_physp)))
+				__osm_sa_pkey_check_physp(sa, p_physp,
+							  p_ctxt);
+		} else {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4603: "
+				"Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+				port_num,
+				osm_node_get_num_physp(p_port->p_node));
+			goto Exit;
+		}
+	} else {
+		num_ports = osm_node_get_num_physp(p_port->p_node);
+		for (port_num = 0; port_num < num_ports; port_num++) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_port->p_node, port_num);
+			if (!p_physp)
+				continue;
+
+			/* if the requester and the p_physp don't share a pkey -
+			   continue */
+			if (!osm_physp_share_pkey
+			    (sa->p_log, p_req_physp, p_physp))
+				continue;
+
+			__osm_sa_pkey_check_physp(sa, p_physp, p_ctxt);
+		}
+	}
+Exit:
+	OSM_LOG_EXIT(sa->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->sa, p_port, p_ctxt);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_rec_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_pkey_table_record_t *p_rcvd_rec;
+	const 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_pkey_search_ctxt_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net64_t comp_mask;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_pkey_table_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+	comp_mask = p_rcvd_mad->comp_mask;
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_PKEY_TBL_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4605: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/*
+	   p922 - P_KeyTableRecords shall only be provided in response
+	   to trusted requests.
+	   Check that the requester is a trusted one.
+	 */
+	if (p_rcvd_mad->sm_key != sa->p_subn->opt.sa_key) {
+		/* This is not a trusted requester! */
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4608: "
+			"Request from non-trusted requester: "
+			"Given SM_Key:0x%016" PRIx64 "\n",
+			cl_ntoh64(p_rcvd_mad->sm_key));
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 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.sa = sa;
+	context.block_num = p_rcvd_rec->block_num;
+	context.p_req_physp = p_req_physp;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Got Query Lid:%u(%02X), 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(sa->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 = &sa->p_subn->port_lid_tbl;
+
+		CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
+
+		status = osm_get_port_by_base_lid(sa->p_subn, p_rcvd_rec->lid,
+						  &p_port);
+		if (status != IB_SUCCESS || p_port == NULL) {
+			status = IB_NOT_FOUND;
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 460B: "
+				"No port found with LID %u\n",
+				cl_ntoh16(p_rcvd_rec->lid));
+		}
+	}
+
+	if (status == IB_SUCCESS) {
+		/* if we got a unique port - no need for a port search */
+		if (p_port)
+			/* this does the loop on all the port phys ports */
+			__osm_sa_pkey_by_comp_mask(sa, p_port, &context);
+		else
+			cl_qmap_apply_func(&sa->p_subn->port_guid_tbl,
+					   __osm_sa_pkey_by_comp_mask_cb,
+					   &context);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_pkey_table_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_portinfo_record.c b/opensm/osm_sa_portinfo_record.c
new file mode 100644
index 0000000..753c3db
--- /dev/null
+++ b/opensm/osm_sa_portinfo_record.c
@@ -0,0 +1,592 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_pir_rcv_t.
+ * This object represents the PortInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_pir_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+	boolean_t is_enhanced_comp_mask;
+} osm_pir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pir_rcv_new_pir(IN osm_sa_t * sa,
+		      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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2102: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New PortInfoRecord: port 0x%016" PRIx64
+		", lid %u, port %u\n",
+		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+		cl_ntoh16(lid), osm_physp_get_port_num(p_physp));
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	p_rec_item->rec.lid = lid;
+	p_rec_item->rec.port_info = p_physp->port_info;
+	p_rec_item->rec.port_num = osm_physp_get_port_num(p_physp);
+
+	cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_create(IN osm_sa_t * sa,
+		    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(sa->p_log);
+
+	if (p_physp->p_node->sw) {
+		p_node_physp = osm_node_get_physp_ptr(p_physp->p_node, 0);
+		base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_node_physp));
+		lmc =
+		    osm_switch_sp0_is_lmc_capable(p_physp->p_node->sw,
+						  sa->
+						  p_subn) ?
+		    osm_physp_get_lmc(p_node_physp) : 0;
+	} else {
+		lmc = osm_physp_get_lmc(p_physp);
+		base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp));
+	}
+	max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1);
+
+	if (p_ctxt->comp_mask & IB_PIR_COMPMASK_LID) {
+		match_lid_ho = cl_ntoh16(p_ctxt->p_rcvd_rec->lid);
+
+		/*
+		   We validate that the lid belongs to this node.
+		 */
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Comparing LID: %u <= %u <= %u\n",
+			base_lid_ho, match_lid_ho, max_lid_ho);
+
+		if (match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho)
+			goto Exit;
+	}
+
+	__osm_pir_rcv_new_pir(sa, p_physp, p_ctxt->p_list,
+			      cl_hton16(base_lid_ho));
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_check_physp(IN osm_sa_t * sa,
+			 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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	p_comp_pi = &p_rcvd_rec->port_info;
+	p_pi = &p_physp->port_info;
+
+	osm_dump_port_info(sa->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(sa, p_physp, p_ctxt);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask(IN osm_sa_t * sa,
+			  IN osm_node_t * const p_node,
+			  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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	p_req_physp = p_ctxt->p_req_physp;
+
+	num_ports = osm_node_get_num_physp(p_node);
+
+	if (comp_mask & IB_PIR_COMPMASK_PORTNUM) {
+		if (p_rcvd_rec->port_num < num_ports) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_node,
+						   p_rcvd_rec->port_num);
+			/* Check that the p_physp is valid, and that the
+			   p_physp and the p_req_physp share a pkey. */
+			if (p_physp &&
+			    osm_physp_share_pkey(sa->p_log, p_req_physp,
+						 p_physp))
+				__osm_sa_pir_check_physp(sa, p_physp,
+							 p_ctxt);
+		}
+	} else {
+		for (port_num = 0; port_num < num_ports; port_num++) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_node, port_num);
+			if (!p_physp)
+				continue;
+
+			/* if the requester and the p_physp don't share a pkey -
+			   continue */
+			if (!osm_physp_share_pkey
+			    (sa->p_log, p_req_physp, p_physp))
+				continue;
+
+			__osm_sa_pir_check_physp(sa, p_physp, p_ctxt);
+		}
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask_cb(IN cl_map_item_t * const p_map_item,
+			     IN void *context)
+{
+	osm_node_t *const p_node = (osm_node_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->sa, p_node, p_ctxt);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pir_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_portinfo_record_t *p_rcvd_rec;
+	const 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_pir_search_ctxt_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net64_t comp_mask;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_portinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+	comp_mask = p_rcvd_mad->comp_mask;
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2105: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2104: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_portinfo_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG);
+
+	p_tbl = &sa->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.sa = sa;
+	context.p_req_physp = p_req_physp;
+	context.is_enhanced_comp_mask =
+	    cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31);
+
+	cl_plock_acquire(sa->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(sa->p_subn, p_rcvd_rec->lid,
+					     &p_port);
+		if ((status != IB_SUCCESS) || (p_port == NULL)) {
+			status = IB_NOT_FOUND;
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2109: "
+				"No port found with LID %u\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(sa->p_log, OSM_LOG_ERROR, "ERR 2103: "
+				"Given LID (%u) is out of range:%u\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(sa, p_port->p_node,
+						  &context);
+		else
+			cl_qmap_apply_func(&sa->p_subn->node_guid_tbl,
+					   __osm_sa_pir_by_comp_mask_cb,
+					   &context);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	/*
+	   p922 - The M_Key returned shall be zero, except in the case of a
+	   trusted request.
+	   Note: In the mad controller we check that the SM_Key received on
+	   the mad is valid. Meaning - is either zero or equal to the local
+	   sm_key.
+	 */
+	if (!p_rcvd_mad->sm_key) {
+		osm_pir_item_t *item;
+		for (item = (osm_pir_item_t *) cl_qlist_head(&rec_list);
+		     item != (osm_pir_item_t *) cl_qlist_end(&rec_list);
+		     item = (osm_pir_item_t *)cl_qlist_next(&item->list_item))
+			item->rec.port_info.m_key = 0;
+	}
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_portinfo_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_service_record.c b/opensm/osm_sa_service_record.c
new file mode 100644
index 0000000..66b4cb7
--- /dev/null
+++ b/opensm/osm_sa_service_record.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_service.h>
+#include <opensm/osm_pkey.h>
+
+typedef struct osm_sr_item {
+	cl_list_item_t list_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_sa_t *sa;
+} osm_sr_match_item_t;
+
+typedef struct osm_sr_search_ctxt {
+	osm_sr_match_item_t *p_sr_item;
+	const osm_physp_t *p_req_physp;
+} osm_sr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__match_service_pkey_with_ports_pkey(IN osm_sa_t * sa,
+				     IN const osm_madw_t * 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(sa->p_log,
+						sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2404: "
+			"Cannot find requester physical port\n");
+		valid = FALSE;
+		goto Exit;
+	}
+
+	if ((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) {
+		/* We have a ServiceP_Key - check matching on requester port, and
+		   ServiceGid port (if such exists) */
+		/* Make sure it matches the p_req_physp */
+		if (!osm_physp_has_pkey
+		    (sa->p_log, p_service_rec->service_pkey, p_req_physp)) {
+			valid = FALSE;
+			goto Exit;
+		}
+
+		/* 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_get_port_by_guid(sa->p_subn, service_guid);
+			if (!service_port) {
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2405: "
+					"No port object for port 0x%016" PRIx64
+					"\n", cl_ntoh64(service_guid));
+				valid = FALSE;
+				goto Exit;
+			}
+			/* check on the table of the default physical port of the service port */
+			if (!osm_physp_has_pkey(sa->p_log,
+						p_service_rec->service_pkey,
+						service_port->p_physp)) {
+				valid = FALSE;
+				goto Exit;
+			}
+		}
+	}
+
+Exit:
+	return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__match_name_to_key_association(IN osm_sa_t * sa,
+				ib_service_record_t * p_service_rec,
+				ib_net64_t comp_mask)
+{
+	UNUSED_PARAM(p_service_rec);
+	UNUSED_PARAM(sa);
+
+	if ((comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) ==
+	    (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) {
+		/* For now, we are not maintaining the ServiceAssociation record
+		 * so just return TRUE
+		 */
+		return TRUE;
+	}
+
+	return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__validate_sr(IN osm_sa_t * sa, IN const osm_madw_t * 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(sa->p_log);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_service_rec =
+	    (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	valid = __match_service_pkey_with_ports_pkey(sa,
+						     p_madw,
+						     p_recvd_service_rec,
+						     p_sa_mad->comp_mask);
+
+	if (!valid) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"No Match for Service Pkey\n");
+		valid = FALSE;
+		goto Exit;
+	}
+
+	valid = __match_name_to_key_association(sa,
+						p_recvd_service_rec,
+						p_sa_mad->comp_mask);
+
+	if (!valid) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Service Record Name to key matching failed\n");
+		valid = FALSE;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_respond(IN osm_sa_t * sa,
+		     IN osm_madw_t * const p_madw,
+		     IN cl_qlist_t * const p_list)
+{
+	/* p923 - The ServiceKey shall be set to 0, except in the case of
+	   a trusted request.
+	   Note: In the mad controller we check that the SM_Key received on
+	   the mad is valid. Meaning - is either zero or equal to the local
+	   sm_key.
+	 */
+	if (!osm_madw_get_sa_mad_ptr(p_madw)->sm_key) {
+		osm_sr_item_t *item;
+		for (item = (osm_sr_item_t *) cl_qlist_head(p_list);
+		     item != (osm_sr_item_t *) cl_qlist_end(p_list);
+		     item = (osm_sr_item_t *)cl_qlist_next(&item->list_item))
+			memset(item->service_rec.service_key, 0,
+			       sizeof(item->service_rec.service_key));
+	}
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_service_record_t), p_list);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_matching_sr(IN cl_list_item_t * 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->sa->p_log,
+					p_svcr->service_record.service_pkey,
+					p_req_physp)) {
+			OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_VERBOSE,
+				"requester port doesn't have the service_pkey: 0x%X\n",
+				cl_ntoh16(p_svcr->service_record.service_pkey));
+			return;
+		}
+	}
+
+	p_sr_pool_item = malloc(sizeof(*p_sr_pool_item));
+	if (p_sr_pool_item == NULL) {
+		OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_ERROR, "ERR 2408: "
+			"Unable to acquire Service Record from pool\n");
+		goto Exit;
+	}
+
+	p_sr_pool_item->service_rec = p_svcr->service_record;
+
+	cl_qlist_insert_tail(&p_sr_item->sr_list, &p_sr_pool_item->list_item);
+
+Exit:
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_get_method(IN osm_sa_t * sa,
+			      IN 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(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log,
+						sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 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(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_service_record(sa->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.sa = sa;
+
+	context.p_sr_item = &sr_match_item;
+	context.p_req_physp = p_req_physp;
+
+	/* Grab the lock */
+	cl_plock_excl_acquire(sa->p_lock);
+
+	cl_qlist_apply_func(&sa->p_subn->sa_sr_list,
+			    __get_matching_sr, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	if (p_sa_mad->method == IB_MAD_METHOD_GET &&
+	    cl_qlist_count(&sr_match_item.sr_list) == 0) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"No records matched the Service Record query\n");
+
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS);
+		goto Exit;
+	}
+
+	__osm_sr_rcv_respond(sa, p_madw, &sr_match_item.sr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_set_method(IN osm_sa_t * sa,
+			      IN 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(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_service_rec =
+	    (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_service_record(sa->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(sa->p_log, OSM_LOG_VERBOSE,
+			"Component Mask RID check failed for METHOD_SET\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+		goto Exit;
+	}
+
+	/* if we were not provided with a service lease make it
+	   infinite */
+	if ((comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"ServiceLease Component Mask not set - using infinite lease\n");
+		p_recvd_service_rec->service_lease = 0xFFFFFFFF;
+	}
+
+	/* Grab the lock */
+	cl_plock_excl_acquire(sa->p_lock);
+
+	/* If Record exists with matching RID */
+	p_svcr = osm_svcr_get_by_rid(sa->p_subn,
+				     sa->p_log, p_recvd_service_rec);
+
+	if (p_svcr == NULL) {
+		/* Create the instance of the osm_svcr_t object */
+		p_svcr = osm_svcr_new(p_recvd_service_rec);
+		if (p_svcr == NULL) {
+			cl_plock_release(sa->p_lock);
+
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2411: "
+				"osm_svcr_get_by_rid failed\n");
+
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_NO_RESOURCES);
+			goto Exit;
+		}
+
+		/* Add this new osm_svcr_t object to subnet object */
+		osm_svcr_insert_to_db(sa->p_subn, sa->p_log, p_svcr);
+
+	} else {
+		/* Update the old instance of the osm_svcr_t object */
+		osm_svcr_init(p_svcr, p_recvd_service_rec);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	if (p_recvd_service_rec->service_lease != 0xFFFFFFFF) {
+#if 0
+		cl_timer_trim(&sa->sr_timer,
+			      p_recvd_service_rec->service_lease * 1000);
+#endif
+		/*  This was a bug since no check was made to see if too long */
+		/*  just make sure the timer works - get a call back within a second */
+		cl_timer_trim(&sa->sr_timer, 1000);
+		p_svcr->modified_time = cl_get_time_stamp_sec();
+	}
+
+	p_sr_item = malloc(sizeof(*p_sr_item));
+	if (p_sr_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2412: "
+			"Unable to acquire Service record\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES);
+		goto Exit;
+	}
+
+	if ((comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY) {
+		/* Set the Default Service P_Key in the response */
+		p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY;
+	}
+
+	p_sr_item->service_rec = *p_recvd_service_rec;
+	cl_qlist_init(&sr_list);
+
+	cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item);
+
+	__osm_sr_rcv_respond(sa, p_madw, &sr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_delete_method(IN osm_sa_t * sa,
+				 IN 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(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_recvd_service_rec =
+	    (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
+
+	comp_mask = p_sa_mad->comp_mask;
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_service_record(sa->p_log, p_recvd_service_rec,
+					OSM_LOG_DEBUG);
+
+	/* Grab the lock */
+	cl_plock_excl_acquire(sa->p_lock);
+
+	/* If Record exists with matching RID */
+	p_svcr = osm_svcr_get_by_rid(sa->p_subn,
+				     sa->p_log, p_recvd_service_rec);
+
+	if (p_svcr == NULL) {
+		cl_plock_release(sa->p_lock);
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"No records matched the RID\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS);
+		goto Exit;
+	} else {
+		osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	p_sr_item = malloc(sizeof(*p_sr_item));
+	if (p_sr_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2413: "
+			"Unable to acquire Service record\n");
+		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES);
+		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, &p_sr_item->list_item);
+
+	if (p_svcr)
+		osm_svcr_delete(p_svcr);
+
+	__osm_sr_rcv_respond(sa, p_madw, &sr_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sr_rcv_process(IN void *context, IN void *data)
+{
+	osm_sa_t *sa = context;
+	osm_madw_t *p_madw = data;
+	ib_sa_mad_t *p_sa_mad;
+	boolean_t valid;
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
+
+	CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD);
+
+	switch (p_sa_mad->method) {
+	case IB_MAD_METHOD_SET:
+		valid = __validate_sr(sa, p_madw);
+		if (!valid) {
+			OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
+				"Component Mask check failed for set request\n");
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+		osm_sr_rcv_process_set_method(sa, p_madw);
+		break;
+	case IB_MAD_METHOD_DELETE:
+		valid = __validate_sr(sa, p_madw);
+		if (!valid) {
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Component Mask check failed for delete request\n");
+			osm_sa_send_error(sa, p_madw,
+					  IB_SA_MAD_STATUS_REQ_INVALID);
+			goto Exit;
+		}
+		osm_sr_rcv_process_delete_method(sa, p_madw);
+		break;
+	case IB_MAD_METHOD_GET:
+	case IB_MAD_METHOD_GETTABLE:
+		osm_sr_rcv_process_get_method(sa, p_madw);
+		break;
+	default:
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_sa_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		break;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sr_rcv_lease_cb(IN void *context)
+{
+	osm_sa_t *sa = context;
+	cl_list_item_t *p_list_item;
+	cl_list_item_t *p_next_list_item;
+	osm_svcr_t *p_svcr;
+	uint32_t curr_time;
+	uint32_t elapsed_time;
+	uint32_t trim_time = 20;	/*  maxiaml timer refresh is 20 seconds */
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	cl_plock_excl_acquire(sa->p_lock);
+
+	p_list_item = cl_qlist_head(&sa->p_subn->sa_sr_list);
+
+	while (p_list_item != cl_qlist_end(&sa->p_subn->sa_sr_list)) {
+		p_svcr = (osm_svcr_t *) p_list_item;
+
+		if (p_svcr->service_record.service_lease == 0xFFFFFFFF) {
+			p_list_item = cl_qlist_next(p_list_item);
+			continue;
+		}
+
+		/* current time in seconds */
+		curr_time = cl_get_time_stamp_sec();
+		/* elapsed time from last modify */
+		elapsed_time = curr_time - p_svcr->modified_time;
+		/* but it can not be less then 1 */
+		if (elapsed_time < 1)
+			elapsed_time = 1;
+
+		if (elapsed_time < p_svcr->lease_period) {
+			/*
+			   Just update the service lease period
+			   note: for simplicity we work with a uint32_t field
+			   external to the network order lease_period of the MAD
+			 */
+			p_svcr->lease_period -= elapsed_time;
+
+			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+				"Remaining time for Service Name:%s is:0x%X\n",
+				p_svcr->service_record.service_name,
+				p_svcr->lease_period);
+
+			p_svcr->modified_time = curr_time;
+
+			/* Update the trim timer */
+			if (trim_time > p_svcr->lease_period) {
+				trim_time = p_svcr->lease_period;
+				if (trim_time < 1)
+					trim_time = 1;
+			}
+
+			p_list_item = cl_qlist_next(p_list_item);
+			continue;
+
+		} else {
+			p_next_list_item = cl_qlist_next(p_list_item);
+
+			/* Remove the service Record */
+			osm_svcr_remove_from_db(sa->p_subn,
+						sa->p_log, p_svcr);
+
+			osm_svcr_delete(p_svcr);
+
+			p_list_item = p_next_list_item;
+			continue;
+		}
+	}
+
+	/* Release the Lock */
+	cl_plock_release(sa->p_lock);
+
+	if (trim_time != 0xFFFFFFFF) {
+		cl_timer_trim(&sa->sr_timer, trim_time * 1000);	/* Convert to milli seconds */
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_slvl_record.c b/opensm/osm_sa_slvl_record.c
new file mode 100644
index 0000000..34320c5
--- /dev/null
+++ b/opensm/osm_sa_slvl_record.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rec_rcv_t.
+ * This object represents the SLtoVL Mapping Query Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_slvl_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_slvl_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_slvl_create(IN osm_sa_t * sa,
+		     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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2602: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+		lid = p_physp->port_info.base_lid;
+	else
+		lid = osm_node_get_base_lid(p_physp->p_node, 0);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New SLtoVL Map for: OUT port 0x%016" PRIx64
+		", lid 0x%X, port %u to In Port:%u\n",
+		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+		cl_ntoh16(lid), osm_physp_get_port_num(p_physp), in_port_idx);
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_slvl_by_comp_mask(IN osm_sa_t * sa,
+			   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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	num_ports = osm_node_get_num_physp(p_port->p_node);
+	in_port_start = 0;
+	in_port_end = num_ports - 1;
+	out_port_start = 0;
+	out_port_end = num_ports - 1;
+	p_req_physp = p_ctxt->p_req_physp;
+
+	if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) {
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Using Physical Default Port Number: 0x%X (for End Node)\n",
+			p_port->p_physp->port_num);
+		p_out_physp = p_port->p_physp;
+		/* check that the p_out_physp and the p_req_physp share a pkey */
+		if (osm_physp_share_pkey
+		    (sa->p_log, p_req_physp, p_out_physp))
+			__osm_sa_slvl_create(sa, p_out_physp, p_ctxt, 0);
+	} else {
+		if (comp_mask & IB_SLVL_COMPMASK_OUT_PORT)
+			out_port_start = out_port_end =
+			    p_rcvd_rec->out_port_num;
+		if (comp_mask & IB_SLVL_COMPMASK_IN_PORT)
+			in_port_start = in_port_end = p_rcvd_rec->in_port_num;
+
+		for (out_port_num = out_port_start;
+		     out_port_num <= out_port_end; out_port_num++) {
+			p_out_physp =
+			    osm_node_get_physp_ptr(p_port->p_node,
+						   out_port_num);
+			if (!p_out_physp)
+				continue;
+
+			for (in_port_num = in_port_start;
+			     in_port_num <= in_port_end; in_port_num++) {
+#if 0
+				if (out_port_num && out_port_num == in_port_num)
+					continue;
+#endif
+
+				p_in_physp =
+				    osm_node_get_physp_ptr(p_port->p_node,
+							   in_port_num);
+				if (!p_in_physp)
+					continue;
+
+				/* if the requester and the p_out_physp don't share a pkey -
+				   continue */
+				if (!osm_physp_share_pkey
+				    (sa->p_log, p_req_physp, p_out_physp))
+					continue;
+
+				__osm_sa_slvl_create(sa, p_out_physp, p_ctxt,
+						     in_port_num);
+			}
+		}
+	}
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static 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->sa, p_port, p_ctxt);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_slvl_rec_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *p_rcvd_mad;
+	const ib_slvl_table_record_t *p_rcvd_rec;
+	const cl_ptr_vector_t *p_tbl;
+	const osm_port_t *p_port = NULL;
+	cl_qlist_t rec_list;
+	osm_slvl_search_ctxt_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net64_t comp_mask;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_slvl_table_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
+	comp_mask = p_rcvd_mad->comp_mask;
+
+	CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_SLVL_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
+	    p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2604: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(p_rcvd_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2603: "
+			"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.sa = sa;
+	context.in_port_num = p_rcvd_rec->in_port_num;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Got Query Lid:%u(%02X), In-Port:0x%02X(%02X), Out-Port:0x%02X(%02X)\n",
+		cl_ntoh16(p_rcvd_rec->lid),
+		(comp_mask & IB_SLVL_COMPMASK_LID) != 0,
+		p_rcvd_rec->in_port_num,
+		(comp_mask & IB_SLVL_COMPMASK_IN_PORT) != 0,
+		p_rcvd_rec->out_port_num,
+		(comp_mask & IB_SLVL_COMPMASK_OUT_PORT) != 0);
+
+	/*
+	   If the user specified a LID, it obviously narrows our
+	   work load, since we don't have to search every port
+	 */
+	if (comp_mask & IB_SLVL_COMPMASK_LID) {
+
+		p_tbl = &sa->p_subn->port_lid_tbl;
+
+		CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
+
+		status =
+		    osm_get_port_by_base_lid(sa->p_subn, p_rcvd_rec->lid,
+					     &p_port);
+		if ((status != IB_SUCCESS) || (p_port == NULL)) {
+			status = IB_NOT_FOUND;
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2608: "
+				"No port found with LID %u\n",
+				cl_ntoh16(p_rcvd_rec->lid));
+		}
+	}
+
+	if (status == IB_SUCCESS) {
+		/* if we have a unique port - no need for a port search */
+		if (p_port)
+			/*  this does the loop on all the port phys ports */
+			__osm_sa_slvl_by_comp_mask(sa, p_port, &context);
+		else
+			cl_qmap_apply_func(&sa->p_subn->port_guid_tbl,
+					   __osm_sa_slvl_by_comp_mask_cb,
+					   &context);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_slvl_table_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_sminfo_record.c b/opensm/osm_sa_sminfo_record.c
new file mode 100644
index 0000000..de99065
--- /dev/null
+++ b/opensm/osm_sa_sminfo_record.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_smir_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.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_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_opensm.h>
+
+typedef struct osm_smir_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_smir_search_ctxt_t;
+
+static ib_api_status_t
+__osm_smir_rcv_new_smir(IN osm_sa_t * sa,
+			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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2801: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New SMInfo: GUID 0x%016" PRIx64 "\n", cl_ntoh64(guid));
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_smir_by_comp_mask(IN osm_sa_t * sa,
+			   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(sa->p_log);
+
+	if (comp_mask & IB_SMIR_COMPMASK_GUID) {
+		if (p_rem_sm->smi.guid != p_rcvd_rec->sm_info.guid)
+			goto Exit;
+	}
+
+	if (comp_mask & IB_SMIR_COMPMASK_PRIORITY) {
+		if (ib_sminfo_get_priority(&p_rem_sm->smi) !=
+		    ib_sminfo_get_priority(&p_rcvd_rec->sm_info))
+			goto Exit;
+	}
+
+	if (comp_mask & IB_SMIR_COMPMASK_SMSTATE) {
+		if (ib_sminfo_get_state(&p_rem_sm->smi) !=
+		    ib_sminfo_get_state(&p_rcvd_rec->sm_info))
+			goto Exit;
+	}
+
+	/* Implement any other needed search cases */
+
+	__osm_smir_rcv_new_smir(sa, 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(sa->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->sa, p_rem_sm, p_ctxt);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_smir_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *sad_mad;
+	const ib_sminfo_record_t *p_rcvd_rec;
+	const osm_port_t *p_port = NULL;
+	const ib_sm_info_t *p_smi;
+	cl_qlist_t rec_list;
+	osm_smir_search_ctxt_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net64_t comp_mask;
+	ib_net64_t port_guid;
+	osm_physp_t *p_req_physp;
+	osm_port_t *local_port;
+	osm_remote_sm_t *p_rem_sm;
+	cl_qmap_t *p_sm_guid_tbl;
+	uint8_t pri_state;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	sad_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_sminfo_record_t *) ib_sa_mad_get_payload_ptr(sad_mad);
+	comp_mask = sad_mad->comp_mask;
+
+	CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (sad_mad->method != IB_MAD_METHOD_GET &&
+	    sad_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2804: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(sad_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2803: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_sm_info_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG);
+
+	p_smi = &p_rcvd_rec->sm_info;
+
+	cl_qlist_init(&rec_list);
+
+	context.p_rcvd_rec = p_rcvd_rec;
+	context.p_list = &rec_list;
+	context.comp_mask = sad_mad->comp_mask;
+	context.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->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(sa->p_subn, p_rcvd_rec->lid,
+					     &p_port);
+		if ((status != IB_SUCCESS) || (p_port == NULL)) {
+			status = IB_NOT_FOUND;
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2806: "
+				"No port found with LID %u\n",
+				cl_ntoh16(p_rcvd_rec->lid));
+		}
+	}
+
+	if (status == IB_SUCCESS) {
+		/* Handle our own SM first */
+		local_port = osm_get_port_by_guid(sa->p_subn,
+						  sa->p_subn->sm_port_guid);
+		if (!local_port) {
+			cl_plock_release(sa->p_lock);
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2809: "
+				"No port found with GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(sa->p_subn->sm_port_guid));
+			goto Exit;
+		}
+
+		if (!p_port || local_port == p_port) {
+			if (FALSE ==
+			    osm_physp_share_pkey(sa->p_log, p_req_physp,
+						 local_port->p_physp)) {
+				cl_plock_release(sa->p_lock);
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2805: "
+					"Cannot get SMInfo record due to pkey violation\n");
+				goto Exit;
+			}
+
+			/* Check that other search components specified match */
+			if ((comp_mask & IB_SMIR_COMPMASK_GUID) &&
+			    sa->p_subn->sm_port_guid != p_smi->guid)
+				goto Remotes;
+			if ((comp_mask & IB_SMIR_COMPMASK_PRIORITY) &&
+			    sa->p_subn->opt.sm_priority !=
+			       ib_sminfo_get_priority(p_smi))
+				goto Remotes;
+			if ((comp_mask & IB_SMIR_COMPMASK_SMSTATE) &&
+			    sa->p_subn->sm_state != ib_sminfo_get_state(p_smi))
+				goto Remotes;
+
+			/* Now, add local SMInfo to list */
+			pri_state = sa->p_subn->sm_state & 0x0F;
+			pri_state |=
+			    (sa->p_subn->opt.sm_priority & 0x0F) << 4;
+			__osm_smir_rcv_new_smir(sa, local_port, context.p_list,
+						sa->p_subn->sm_port_guid,
+						cl_ntoh32(sa->p_subn->p_osm->stats.qp0_mads_sent),
+						pri_state, p_req_physp);
+		}
+
+	      Remotes:
+		if (p_port && p_port != local_port) {
+			/* Find remote SM corresponding to p_port */
+			port_guid = osm_port_get_guid(p_port);
+			p_sm_guid_tbl = &sa->p_subn->sm_guid_tbl;
+			p_rem_sm =
+			    (osm_remote_sm_t *) cl_qmap_get(p_sm_guid_tbl,
+							    port_guid);
+			if (p_rem_sm !=
+			    (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl))
+				__osm_sa_smir_by_comp_mask(sa, p_rem_sm,
+							   &context);
+			else
+				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 280A: "
+					"No remote SM for GUID 0x%016" PRIx64
+					"\n", cl_ntoh64(port_guid));
+		} else {
+			/* Go over all other known (remote) SMs */
+			cl_qmap_apply_func(&sa->p_subn->sm_guid_tbl,
+					   __osm_sa_smir_by_comp_mask_cb,
+					   &context);
+		}
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_sminfo_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_sw_info_record.c b/opensm/osm_sa_sw_info_record.c
new file mode 100644
index 0000000..649b0ac
--- /dev/null
+++ b/opensm/osm_sa_sw_info_record.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sir_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_sir_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_sir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sir_rcv_new_sir(IN osm_sa_t * sa,
+		      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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5308: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New SwitchInfoRecord: lid %u\n", cl_ntoh16(lid));
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	p_rec_item->rec.lid = lid;
+	p_rec_item->rec.switch_info = p_sw->switch_info;
+
+	cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sir_rcv_create_sir(IN osm_sa_t * sa,
+			 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(sa->p_log);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Looking for SwitchInfoRecord with LID: %u\n",
+		cl_ntoh16(match_lid));
+
+	/* In switches, the port guid is the node guid. */
+	p_port =
+	    osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid);
+	if (!p_port) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530A: "
+			"Failed to find Port by Node Guid:0x%016" PRIx64
+			"\n", cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		goto Exit;
+	}
+
+	/* check that the requester physp and the current physp are under
+	   the same partition. */
+	p_physp = p_port->p_physp;
+	if (!p_physp) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530B: "
+			"Failed to find default physical Port by Node Guid:0x%016"
+			PRIx64 "\n",
+			cl_ntoh64(p_sw->p_node->node_info.node_guid));
+		goto Exit;
+	}
+	if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp))
+		goto Exit;
+
+	/* get the port 0 of the switch */
+	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+	match_lid_ho = cl_ntoh16(match_lid);
+	if (match_lid_ho) {
+		/*
+		   We validate that the lid belongs to this switch.
+		 */
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Comparing LID: %u <= %u <= %u\n",
+			min_lid_ho, match_lid_ho, max_lid_ho);
+
+		if (match_lid_ho < min_lid_ho || match_lid_ho > max_lid_ho)
+			goto Exit;
+
+	}
+
+	__osm_sir_rcv_new_sir(sa, p_sw, p_list, osm_port_get_base_lid(p_port));
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__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_sa_t *sa = p_ctxt->sa;
+	ib_net64_t const comp_mask = p_ctxt->comp_mask;
+	ib_net16_t match_lid = 0;
+
+	OSM_LOG_ENTER(p_ctxt->sa->p_log);
+
+	osm_dump_switch_info(p_ctxt->sa->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(sa, p_sw, p_ctxt->p_list,
+				 match_lid, p_req_physp);
+
+Exit:
+	OSM_LOG_EXIT(p_ctxt->sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sir_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *sad_mad;
+	const ib_switch_info_record_t *p_rcvd_rec;
+	cl_qlist_t rec_list;
+	osm_sir_search_ctxt_t context;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	sad_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_switch_info_record_t *) ib_sa_mad_get_payload_ptr(sad_mad);
+
+	CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (sad_mad->method != IB_MAD_METHOD_GET &&
+	    sad_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5305: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(sad_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5304: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
+		osm_dump_switch_info_record(sa->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 = sad_mad->comp_mask;
+	context.sa = sa;
+	context.p_req_physp = p_req_physp;
+
+	cl_plock_acquire(sa->p_lock);
+
+	/* Go over all switches */
+	cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl,
+			   __osm_sir_rcv_by_comp_mask, &context);
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_switch_info_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_sa_vlarb_record.c b/opensm/osm_sa_vlarb_record.c
new file mode 100644
index 0000000..43c0d65
--- /dev/null
+++ b/opensm/osm_sa_vlarb_record.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_vlarb_rec_rcv_t.
+ * This object represents the VLArbitrationRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_sa.h>
+
+typedef struct osm_vl_arb_item {
+	cl_list_item_t list_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_sa_t *sa;
+	const osm_physp_t *p_req_physp;
+} osm_vl_arb_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_vl_arb_create(IN osm_sa_t * sa,
+		       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(sa->p_log);
+
+	p_rec_item = malloc(sizeof(*p_rec_item));
+	if (p_rec_item == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A02: "
+			"rec_item alloc failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+	if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+		lid = p_physp->port_info.base_lid;
+	else
+		lid = osm_node_get_base_lid(p_physp->p_node, 0);
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"New VLArbitration for: port 0x%016" PRIx64
+		", lid %u, port %u Block:%u\n",
+		cl_ntoh64(osm_physp_get_port_guid(p_physp)),
+		cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block);
+
+	memset(p_rec_item, 0, sizeof(*p_rec_item));
+
+	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, &p_rec_item->list_item);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_vl_arb_check_physp(IN osm_sa_t * sa,
+			    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(sa->p_log);
+
+	/* we got here with the phys port - all that's left is to get the right block */
+	for (block = 1; block <= 4; block++) {
+		if (!(comp_mask & IB_VLA_COMPMASK_BLOCK)
+		    || block == p_ctxt->block_num) {
+			__osm_sa_vl_arb_create(sa, p_physp, p_ctxt, block);
+		}
+	}
+
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_vl_arb_by_comp_mask(IN osm_sa_t * sa,
+			     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(sa->p_log);
+
+	p_rcvd_rec = p_ctxt->p_rcvd_rec;
+	comp_mask = p_ctxt->comp_mask;
+	port_num = p_rcvd_rec->port_num;
+	p_req_physp = p_ctxt->p_req_physp;
+
+	/* if this is a switch port we can search all ports
+	   otherwise we must be looking on port 0 */
+	if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) {
+		/* we put it in the comp mask and port num */
+		port_num = p_port->p_physp->port_num;
+		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+			"Using Physical Default Port Number: 0x%X (for End Node)\n",
+			port_num);
+		comp_mask |= IB_VLA_COMPMASK_OUT_PORT;
+	}
+
+	if (comp_mask & IB_VLA_COMPMASK_OUT_PORT) {
+		if (port_num < osm_node_get_num_physp(p_port->p_node)) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_port->p_node, port_num);
+			/* check that the p_physp is valid, and that the requester
+			   and the p_physp share a pkey. */
+			if (p_physp &&
+			    osm_physp_share_pkey(sa->p_log, p_req_physp,
+						 p_physp))
+				__osm_sa_vl_arb_check_physp(sa, p_physp,
+							    p_ctxt);
+		} else {
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A03: "
+				"Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+				port_num,
+				osm_node_get_num_physp(p_port->p_node));
+			goto Exit;
+		}
+	} else {
+		num_ports = osm_node_get_num_physp(p_port->p_node);
+		for (port_num = 0; port_num < num_ports; port_num++) {
+			p_physp =
+			    osm_node_get_physp_ptr(p_port->p_node, port_num);
+			if (!p_physp)
+				continue;
+
+			/* if the requester and the p_physp don't share a pkey -
+			   continue */
+			if (!osm_physp_share_pkey
+			    (sa->p_log, p_req_physp, p_physp))
+				continue;
+
+			__osm_sa_vl_arb_check_physp(sa, p_physp, p_ctxt);
+		}
+	}
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static 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->sa, p_port, p_ctxt);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vlarb_rec_rcv_process(IN void *ctx, IN void *data)
+{
+	osm_sa_t *sa = ctx;
+	osm_madw_t *p_madw = data;
+	const ib_sa_mad_t *sad_mad;
+	const ib_vl_arb_table_record_t *p_rcvd_rec;
+	const 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_vl_arb_search_ctxt_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	ib_net64_t comp_mask;
+	osm_physp_t *p_req_physp;
+
+	CL_ASSERT(sa);
+
+	OSM_LOG_ENTER(sa->p_log);
+
+	CL_ASSERT(p_madw);
+
+	sad_mad = osm_madw_get_sa_mad_ptr(p_madw);
+	p_rcvd_rec =
+	    (ib_vl_arb_table_record_t *) ib_sa_mad_get_payload_ptr(sad_mad);
+	comp_mask = sad_mad->comp_mask;
+
+	CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_VLARB_RECORD);
+
+	/* we only support SubnAdmGet and SubnAdmGetTable methods */
+	if (sad_mad->method != IB_MAD_METHOD_GET &&
+	    sad_mad->method != IB_MAD_METHOD_GETTABLE) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A05: "
+			"Unsupported Method (%s)\n",
+			ib_get_sa_method_str(sad_mad->method));
+		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
+		goto Exit;
+	}
+
+	/* update the requester physical port. */
+	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
+						osm_madw_get_mad_addr_ptr
+						(p_madw));
+	if (p_req_physp == NULL) {
+		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A04: "
+			"Cannot find requester physical port\n");
+		goto Exit;
+	}
+
+	p_vl_arb = (ib_vl_arb_table_t *) ib_sa_mad_get_payload_ptr(sad_mad);
+
+	cl_qlist_init(&rec_list);
+
+	context.p_rcvd_rec = p_rcvd_rec;
+	context.p_list = &rec_list;
+	context.comp_mask = sad_mad->comp_mask;
+	context.sa = sa;
+	context.block_num = p_rcvd_rec->block_num;
+	context.p_req_physp = p_req_physp;
+
+	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
+		"Got Query Lid:%u(%02X), Port:0x%02X(%02X), Block:0x%02X(%02X)\n",
+		cl_ntoh16(p_rcvd_rec->lid),
+		(comp_mask & IB_VLA_COMPMASK_LID) != 0, p_rcvd_rec->port_num,
+		(comp_mask & IB_VLA_COMPMASK_OUT_PORT) != 0,
+		p_rcvd_rec->block_num,
+		(comp_mask & IB_VLA_COMPMASK_BLOCK) != 0);
+
+	cl_plock_acquire(sa->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 = &sa->p_subn->port_lid_tbl;
+
+		CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
+
+		status =
+		    osm_get_port_by_base_lid(sa->p_subn, p_rcvd_rec->lid,
+					     &p_port);
+		if ((status != IB_SUCCESS) || (p_port == NULL)) {
+			status = IB_NOT_FOUND;
+			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A09: "
+				"No port found with LID %u\n",
+				cl_ntoh16(p_rcvd_rec->lid));
+		}
+	}
+
+	if (status == IB_SUCCESS) {
+		/* if we got a unique port - no need for a port search */
+		if (p_port)
+			/*  this does the loop on all the port phys ports */
+			__osm_sa_vl_arb_by_comp_mask(sa, p_port, &context);
+		else
+			cl_qmap_apply_func(&sa->p_subn->port_guid_tbl,
+					   __osm_sa_vl_arb_by_comp_mask_cb,
+					   &context);
+	}
+
+	cl_plock_release(sa->p_lock);
+
+	osm_sa_respond(sa, p_madw, sizeof(ib_vl_arb_table_record_t), &rec_list);
+
+Exit:
+	OSM_LOG_EXIT(sa->p_log);
+}
diff --git a/opensm/osm_service.c b/opensm/osm_service.c
new file mode 100644
index 0000000..b7c1270
--- /dev/null
+++ b/opensm/osm_service.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of service record functions.
+ */
+
+#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_delete(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) {
+		memset(p_svcr, 0, sizeof(*p_svcr));
+		osm_svcr_init(p_svcr, p_svc_rec);
+	}
+
+	return (p_svcr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+    cl_status_t
+__match_rid_of_svc_rec(IN const cl_list_item_t * 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);
+
+	p_list_item = cl_qlist_find_from_head(&p_subn->sa_sr_list,
+					      __match_rid_of_svc_rec,
+					      p_svc_rec);
+
+	if (p_list_item == cl_qlist_end(&p_subn->sa_sr_list))
+		p_list_item = NULL;
+
+	OSM_LOG_EXIT(p_log);
+	return (osm_svcr_t *) p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_insert_to_db(IN osm_subn_t * p_subn,
+		      IN osm_log_t * p_log, IN osm_svcr_t * p_svcr)
+{
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Inserting new Service Record into Database\n");
+
+	cl_qlist_insert_head(&p_subn->sa_sr_list, &p_svcr->list_item);
+
+	OSM_LOG_EXIT(p_log);
+}
+
+void
+osm_svcr_remove_from_db(IN osm_subn_t * p_subn,
+			IN osm_log_t * p_log, IN osm_svcr_t * p_svcr)
+{
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Removing Service Record Name:%s ID:0x%016" PRIx64
+		" from Database\n", p_svcr->service_record.service_name,
+		p_svcr->service_record.service_id);
+
+	cl_qlist_remove_item(&p_subn->sa_sr_list, &p_svcr->list_item);
+
+	OSM_LOG_EXIT(p_log);
+}
diff --git a/opensm/osm_slvl_map_rcv.c b/opensm/osm_slvl_map_rcv.c
new file mode 100644
index 0000000..e177345
--- /dev/null
+++ b/opensm/osm_slvl_map_rcv.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+void osm_slvl_rcv_process(IN void *context, IN void *p_data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = p_data;
+	ib_slvl_table_t *p_slvl_tbl;
+	ib_smp_t *p_smp;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	osm_slvl_context_t *p_context;
+	ib_net64_t port_guid;
+	ib_net64_t node_guid;
+	uint8_t out_port_num, in_port_num;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_context = osm_madw_get_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);
+
+	cl_plock_excl_acquire(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+
+	if (!p_port) {
+		cl_plock_release(sm->p_lock);
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2C06: "
+			"No port object for port with GUID 0x%" PRIx64
+			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+			", TID 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid),
+			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+		goto Exit;
+	}
+
+	p_node = p_port->p_node;
+	CL_ASSERT(p_node);
+
+	/* in case of a non switch node the attr modifier should be ignored */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {
+		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 = p_port->p_physp;
+		out_port_num = p_physp->port_num;
+		in_port_num = 0;
+	}
+
+	/*
+	   We do not mind if this is a result of a set or get - all we want is to update
+	   the subnet.
+	 */
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Got 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 (!p_physp) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"Got invalid port number %u\n", out_port_num);
+		goto Exit;
+	}
+
+	osm_dump_slvl_map_table(sm->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(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_sm.c b/opensm/osm_sm.c
new file mode 100644
index 0000000..efebf4a
--- /dev/null
+++ b/opensm/osm_sm.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_t.
+ * This object represents the SM Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_thread.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_mcm_info.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_opensm.h>
+
+#define  OSM_SM_INITIAL_TID_VALUE 0x1233
+
+extern void osm_lft_rcv_process(IN void *context, IN void *data);
+extern void osm_mft_rcv_process(IN void *context, IN void *data);
+extern void osm_nd_rcv_process(IN void *context, IN void *data);
+extern void osm_ni_rcv_process(IN void *context, IN void *data);
+extern void osm_pkey_rcv_process(IN void *context, IN void *data);
+extern void osm_pi_rcv_process(IN void *context, IN void *data);
+extern void osm_slvl_rcv_process(IN void *context, IN void *p_data);
+extern void osm_sminfo_rcv_process(IN void *context, IN void *data);
+extern void osm_si_rcv_process(IN void *context, IN void *data);
+extern void osm_trap_rcv_process(IN void *context, IN void *data);
+extern void osm_vla_rcv_process(IN void *context, IN void *data);
+
+extern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal);
+extern void osm_sm_state_mgr_polling_callback(IN void *context);
+
+/**********************************************************************
+ **********************************************************************/
+static void osm_sm_process(osm_sm_t * sm, osm_signal_t signal)
+{
+#ifdef ENABLE_OSM_PERF_MGR
+	if (signal == OSM_SIGNAL_PERFMGR_SWEEP)
+		osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr);
+	else
+#endif
+		osm_state_mgr_process(sm, signal);
+}
+
+static void __osm_sm_sweeper(IN void *p_ptr)
+{
+	ib_api_status_t status;
+	osm_sm_t *const p_sm = (osm_sm_t *) p_ptr;
+	unsigned signals, i;
+
+	OSM_LOG_ENTER(p_sm->p_log);
+
+	while (p_sm->thread_state == OSM_THREAD_STATE_RUN) {
+		/*
+		 * Wait on the event with a timeout.
+		 * Sweeps may be initiated "off schedule" by simply
+		 * signaling the event.
+		 */
+		status = cl_event_wait_on(&p_sm->signal_event,
+					  EVENT_NO_TIMEOUT, TRUE);
+
+		if (status == CL_SUCCESS)
+			OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
+				"Off schedule sweep signalled\n");
+		else if (status != CL_TIMEOUT) {
+			OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E01: "
+				"Event wait failed (%s)\n",
+				CL_STATUS_MSG(status));
+			continue;
+		}
+
+		if (osm_exit_flag)
+			break;
+
+		cl_spinlock_acquire(&p_sm->signal_lock);
+		signals = p_sm->signal_mask;
+		p_sm->signal_mask = 0;
+		cl_spinlock_release(&p_sm->signal_lock);
+
+		for (i = 0; signals; signals >>= 1, i++)
+			if (signals & 1)
+				osm_sm_process(p_sm, i);
+	}
+
+	OSM_LOG_EXIT(p_sm->p_log);
+}
+
+static void sm_sweep(void *arg)
+{
+	osm_sm_t *sm = arg;
+
+	/*  do the sweep only if we are in MASTER state */
+	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER ||
+	    sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING)
+		osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+	cl_timer_start(&sm->sweep_timer, sm->p_subn->opt.sweep_interval * 1000);
+}
+
+static void sweep_fail_process(IN void *context, IN void *p_data)
+{
+	osm_sm_t *sm = context;
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n");
+	sm->p_subn->force_heavy_sweep = TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_construct(IN osm_sm_t * 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_spinlock_construct(&p_sm->signal_lock);
+	cl_spinlock_construct(&p_sm->state_lock);
+	cl_timer_construct(&p_sm->polling_timer);
+	cl_event_construct(&p_sm->signal_event);
+	cl_event_construct(&p_sm->subnet_up_event);
+	cl_event_wheel_construct(&p_sm->trap_aging_tracker);
+	cl_thread_construct(&p_sm->sweeper);
+	cl_spinlock_construct(&p_sm->mgrp_lock);
+	osm_sm_mad_ctrl_construct(&p_sm->mad_ctrl);
+	osm_lid_mgr_construct(&p_sm->lid_mgr);
+	osm_ucast_mgr_construct(&p_sm->ucast_mgr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_shutdown(IN osm_sm_t * const p_sm)
+{
+	boolean_t signal_event = FALSE;
+
+	OSM_LOG_ENTER(p_sm->p_log);
+
+	/*
+	 * Signal our threads that we're leaving.
+	 */
+	if (p_sm->thread_state != OSM_THREAD_STATE_NONE)
+		signal_event = TRUE;
+
+	p_sm->thread_state = OSM_THREAD_STATE_EXIT;
+
+	/*
+	 * Don't trigger unless event has been initialized.
+	 * Destroy the thread before we tear down the other objects.
+	 */
+	if (signal_event)
+		cl_event_signal(&p_sm->signal_event);
+
+	cl_timer_stop(&p_sm->polling_timer);
+	cl_timer_stop(&p_sm->sweep_timer);
+	cl_thread_destroy(&p_sm->sweeper);
+
+	/*
+	 * Always destroy controllers before the corresponding
+	 * receiver to guarantee that all callbacks from the
+	 * dispatcher are complete.
+	 */
+	osm_sm_mad_ctrl_destroy(&p_sm->mad_ctrl);
+	cl_disp_unregister(p_sm->ni_disp_h);
+	cl_disp_unregister(p_sm->pi_disp_h);
+	cl_disp_unregister(p_sm->si_disp_h);
+	cl_disp_unregister(p_sm->nd_disp_h);
+	cl_disp_unregister(p_sm->lft_disp_h);
+	cl_disp_unregister(p_sm->mft_disp_h);
+	cl_disp_unregister(p_sm->sm_info_disp_h);
+	cl_disp_unregister(p_sm->trap_disp_h);
+	cl_disp_unregister(p_sm->slvl_disp_h);
+	cl_disp_unregister(p_sm->vla_disp_h);
+	cl_disp_unregister(p_sm->pkey_disp_h);
+	cl_disp_unregister(p_sm->sweep_fail_disp_h);
+
+	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_lid_mgr_destroy(&p_sm->lid_mgr);
+	osm_ucast_mgr_destroy(&p_sm->ucast_mgr);
+	cl_event_wheel_destroy(&p_sm->trap_aging_tracker);
+	cl_timer_destroy(&p_sm->sweep_timer);
+	cl_timer_destroy(&p_sm->polling_timer);
+	cl_event_destroy(&p_sm->signal_event);
+	cl_event_destroy(&p_sm->subnet_up_event);
+	cl_spinlock_destroy(&p_sm->signal_lock);
+	cl_spinlock_destroy(&p_sm->mgrp_lock);
+	cl_spinlock_destroy(&p_sm->state_lock);
+
+	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);
+
+	p_sm->p_subn = p_subn;
+	p_sm->p_db = p_db;
+	p_sm->p_vendor = p_vendor;
+	p_sm->p_mad_pool = p_mad_pool;
+	p_sm->p_vl15 = p_vl15;
+	p_sm->p_log = p_log;
+	p_sm->p_disp = p_disp;
+	p_sm->p_lock = p_lock;
+
+	status = cl_spinlock_init(&p_sm->signal_lock);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	status = cl_spinlock_init(&p_sm->state_lock);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	status = cl_event_init(&p_sm->signal_event, FALSE);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	status = cl_event_init(&p_sm->subnet_up_event, FALSE);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	status = cl_timer_init(&p_sm->polling_timer,
+			       osm_sm_state_mgr_polling_callback, p_sm);
+	if (status != CL_SUCCESS)
+		goto Exit;
+
+	cl_qlist_init(&p_sm->mgrp_list);
+
+	status = cl_spinlock_init(&p_sm->mgrp_lock);
+	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 = cl_event_wheel_init(&p_sm->trap_aging_tracker);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	p_sm->sweep_fail_disp_h = cl_disp_register(p_disp,
+						   OSM_MSG_LIGHT_SWEEP_FAIL,
+						   sweep_fail_process, p_sm);
+	if (p_sm->sweep_fail_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->ni_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_INFO,
+					   osm_ni_rcv_process, p_sm);
+	if (p_sm->ni_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->pi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORT_INFO,
+					   osm_pi_rcv_process, p_sm);
+	if (p_sm->pi_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->si_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO,
+					   osm_si_rcv_process, p_sm);
+	if (p_sm->si_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->nd_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_DESC,
+					   osm_nd_rcv_process, p_sm);
+	if (p_sm->nd_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT,
+					    osm_lft_rcv_process, p_sm);
+	if (p_sm->lft_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT,
+					    osm_mft_rcv_process, p_sm);
+	if (p_sm->mft_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->sm_info_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SM_INFO,
+						osm_sminfo_rcv_process, p_sm);
+	if (p_sm->sm_info_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->trap_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NOTICE,
+					     osm_trap_rcv_process, p_sm);
+	if (p_sm->trap_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL,
+					     osm_slvl_rcv_process, p_sm);
+	if (p_sm->slvl_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->vla_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB,
+					    osm_vla_rcv_process, p_sm);
+	if (p_sm->vla_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_sm->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY,
+					     osm_pkey_rcv_process, p_sm);
+	if (p_sm->pkey_disp_h == CL_DISP_INVALID_HANDLE)
+		goto Exit;
+
+	p_subn->sm_state = p_subn->opt.sm_inactive ?
+	    IB_SMINFO_STATE_NOTACTIVE : IB_SMINFO_STATE_DISCOVERING;
+	osm_report_sm_state(p_sm);
+
+	/*
+	 * Now that the component objects are initialized, start
+	 * the sweeper thread if the user wants sweeping.
+	 */
+	p_sm->thread_state = OSM_THREAD_STATE_RUN;
+	status = cl_thread_init(&p_sm->sweeper, __osm_sm_sweeper, p_sm,
+				"opensm sweeper");
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (p_sm->p_subn->opt.sweep_interval)
+		cl_timer_start(&p_sm->sweep_timer,
+			       p_sm->p_subn->opt.sweep_interval * 1000);
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal)
+{
+	cl_spinlock_acquire(&p_sm->signal_lock);
+	p_sm->signal_mask |= 1 << signal;
+	cl_event_signal(&p_sm->signal_event);
+	cl_spinlock_release(&p_sm->signal_lock);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_sweep(IN osm_sm_t * const p_sm)
+{
+	OSM_LOG_ENTER(p_sm->p_log);
+	osm_sm_signal(p_sm, OSM_SIGNAL_SWEEP);
+	OSM_LOG_EXIT(p_sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_bind(IN osm_sm_t * const p_sm, IN const ib_net64_t port_guid)
+{
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(p_sm->p_log);
+
+	status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E10: "
+			"SM MAD Controller bind failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sm_mgrp_process(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)
+{
+	osm_mcast_mgr_ctxt_t *ctx;
+
+	/*
+	 * 'Schedule' all the QP0 traffic for when the state manager
+	 * isn't busy trying to do something else.
+	 */
+	ctx = malloc(sizeof(*ctx));
+	if (!ctx)
+		return IB_ERROR;
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->mlid = p_mgrp->mlid;
+	ctx->req_type = req_type;
+	ctx->port_guid = port_guid;
+
+	cl_spinlock_acquire(&p_sm->mgrp_lock);
+	cl_qlist_insert_tail(&p_sm->mgrp_list, &ctx->list_item);
+	cl_spinlock_release(&p_sm->mgrp_lock);
+
+	osm_sm_signal(p_sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST);
+
+	return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	return __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, req_type);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	__osm_sm_mgrp_process(p_sm, p_mgrp, port_guid,
+			      OSM_MCAST_REQ_TYPE_LEAVE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+	ib_api_status_t status = IB_SUCCESS;
+	osm_mcm_info_t *p_mcm;
+
+	OSM_LOG_ENTER(p_sm->p_log);
+
+	OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE,
+		"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_get_port_by_guid(p_sm->p_subn, port_guid);
+	if (!p_port) {
+		CL_PLOCK_RELEASE(p_sm->p_lock);
+		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "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_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid);
+	if (!p_mgrp) {
+		OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE,
+			"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, "ERR 2E06: "
+				"Unable to allocate multicast group object\n");
+			status = IB_INSUFFICIENT_MEMORY;
+			goto Exit;
+		}
+
+		p_sm->p_subn->mgroups[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO] = p_mgrp;
+	} 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, "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,
+				"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, "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;
+	}
+
+	status = __osm_sm_mgrp_connect(p_sm, p_mgrp, port_guid, req_type);
+	CL_PLOCK_RELEASE(p_sm->p_lock);
+
+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;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_sm->p_log);
+
+	OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE,
+		"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.
+	 */
+	CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock);
+
+	p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid);
+	if (!p_port) {
+		CL_PLOCK_RELEASE(p_sm->p_lock);
+		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "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_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid);
+	if (!p_mgrp) {
+		CL_PLOCK_RELEASE(p_sm->p_lock);
+		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "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_port_remove_mgrp(p_port, mlid);
+
+	__osm_sm_mgrp_disconnect(p_sm, p_mgrp, port_guid);
+	CL_PLOCK_RELEASE(p_sm->p_lock);
+
+Exit:
+	OSM_LOG_EXIT(p_sm->p_log);
+	return (status);
+}
+
+void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority)
+{
+	uint8_t old_pri = sm->p_subn->opt.sm_priority;
+
+	sm->p_subn->opt.sm_priority = priority;
+
+	if (old_pri < priority &&
+	    sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY)
+		osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE);
+}
diff --git a/opensm/osm_sm_mad_ctrl.c b/opensm/osm_sm_mad_ctrl.c
new file mode 100644
index 0000000..267ec85
--- /dev/null
+++ b/opensm/osm_sm_mad_ctrl.c
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_mad_ctrl_t.
+ * This object represents the SM MAD request controller object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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;
+
+	OSM_LOG_ENTER(p_ctrl->p_log);
+
+	CL_ASSERT(p_madw);
+	/*
+	   Return the MAD & wrapper to the pool.
+	 */
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+		"Retiring MAD with TID 0x%" PRIx64 "\n",
+		cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id));
+
+	osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+
+	outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats);
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n",
+		p_ctrl->p_stats->qp0_mads_outstanding,
+		outstanding ? "" : ": wire is clean.");
+
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/************/
+
+/****f* opensm: SM/__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);
+
+	/*
+	   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);
+
+	mads_on_wire =
+	    cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire);
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+		"%u SMPs on the wire, %u outstanding\n", mads_on_wire,
+		p_ctrl->p_stats->qp0_mads_outstanding);
+
+	/*
+	   We can signal the VL15 controller to send another MAD
+	   if any are waiting for transmission.
+	 */
+	osm_vl15_poll(p_ctrl->p_vl15);
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/****f* opensm: SM/__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);
+
+	CL_ASSERT(p_madw);
+	CL_ASSERT(transaction_context);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: "
+			"'D' bit not set in returned SMP\n");
+		osm_dump_dr_smp(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:
+		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: "
+			"Unsupported attribute = 0x%X\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)
+		goto Exit;
+
+	/*
+	   Post this MAD to the dispatcher for asynchronous
+	   processing by the appropriate controller.
+	 */
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
+		osm_get_disp_msg_str(msg_id));
+
+	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
+			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
+
+	if (status != CL_SUCCESS) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: "
+			"Dispatcher post message failed (%s) for attribute = 0x%X\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);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/*
+	   Note that attr_id (like the rest of the MAD) is in
+	   network byte order.
+	 */
+	switch (p_smp->attr_id) {
+	case IB_MAD_ATTR_SM_INFO:
+		msg_id = OSM_MSG_MAD_SM_INFO;
+		break;
+
+	default:
+		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
+			"Ignoring SubnGet MAD - unsupported attribute = 0x%X\n",
+			cl_ntoh16(p_smp->attr_id));
+		break;
+	}
+
+	if (msg_id == CL_DISP_MSGID_NONE) {
+		/*
+		   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);
+		goto Exit;
+	}
+
+	/*
+	   Post this MAD to the dispatcher for asynchronous
+	   processing by the appropriate controller.
+	 */
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
+		osm_get_disp_msg_str(msg_id));
+
+	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
+			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
+
+	if (status != CL_SUCCESS) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: "
+			"Dispatcher post message failed (%s)\n",
+			CL_STATUS_MSG(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__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);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/*
+	   Note that attr_id (like the rest of the MAD) is in
+	   network byte order.
+	 */
+	switch (p_smp->attr_id) {
+	case IB_MAD_ATTR_SM_INFO:
+		msg_id = OSM_MSG_MAD_SM_INFO;
+		break;
+
+	default:
+		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: "
+			"Unsupported attribute = 0x%X\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) {
+		/*
+		   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);
+		goto Exit;
+	}
+
+	/*
+	   Post this MAD to the dispatcher for asynchronous
+	   processing by the appropriate controller.
+	 */
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
+		osm_get_disp_msg_str(msg_id));
+
+	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
+			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
+
+	if (status != CL_SUCCESS) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: "
+			"Dispatcher post message failed (%s)\n",
+			CL_STATUS_MSG(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__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);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/* Make sure OpenSM is master. If not - then we should not process the trap */
+	if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+			"Received trap but OpenSM is not in MASTER state. "
+			"Dropping mad\n");
+		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
+		goto Exit;
+	}
+
+	/*
+	   Note that attr_id (like the rest of the MAD) is in
+	   network byte order.
+	 */
+	switch (p_smp->attr_id) {
+	case IB_MAD_ATTR_NOTICE:
+		msg_id = OSM_MSG_MAD_NOTICE;
+		break;
+
+	default:
+		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: "
+			"Unsupported attribute = 0x%X\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) {
+		/*
+		   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);
+		goto Exit;
+	}
+
+	/*
+	   Post this MAD to the dispatcher for asynchronous
+	   processing by the appropriate controller.
+	 */
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
+		osm_get_disp_msg_str(msg_id));
+
+	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
+			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);
+
+	if (status != CL_SUCCESS) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: "
+			"Dispatcher post message failed (%s)\n",
+			CL_STATUS_MSG(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+}
+
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__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
+ */
+static 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);
+
+	CL_ASSERT(p_madw);
+
+	/*
+	   A MAD was received from the wire, possibly in response to a request.
+	 */
+	cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd);
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n",
+		p_ctrl->p_stats->qp0_mads_rcvd);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/* if we are closing down simply do nothing */
+	if (osm_exit_flag) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR,
+			"Ignoring received mad - since we are exiting\n");
+
+		osm_dump_dr_smp(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, "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:
+		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: "
+			"Unsupported method = 0x%X\n", p_smp->method);
+		osm_dump_dr_smp(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
+ */
+static 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;
+	ib_api_status_t status;
+	ib_smp_t *p_smp;
+
+	OSM_LOG_ENTER(p_ctrl->p_log);
+
+	CL_ASSERT(p_madw);
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "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, "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) {
+		osm_physp_t *p_physp =
+		    osm_get_physp_by_mad_addr(p_ctrl->p_log,
+					      p_ctrl->p_subn,
+					      &(p_madw->mad_addr));
+		if (!p_physp) {
+			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
+				"Failed to find the corresponding phys port\n");
+		} else {
+			osm_physp_replace_dr_path_with_alternate_dr_path
+			    (p_ctrl->p_log, p_ctrl->p_subn, p_physp,
+			     p_madw->h_bind);
+		}
+	}
+#endif
+
+	/*
+	   An error occurred.  No response was received to a request MAD.
+	   Retire the original request MAD.
+	 */
+
+	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) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
+			"Posting Dispatcher message %s\n",
+			osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
+
+		status = cl_disp_post(p_ctrl->h_disp,
+				      osm_madw_get_err_msg(p_madw),
+				      p_madw,
+				      __osm_sm_mad_ctrl_disp_done_callback,
+				      p_ctrl);
+		if (status != CL_SUCCESS)
+			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: "
+				"Dispatcher post message failed (%s)\n",
+				CL_STATUS_MSG(status));
+	} else
+		/*
+		   No error message was provided, just retire the MAD.
+		 */
+		__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_construct(p_ctrl);
+
+	p_ctrl->p_subn = p_subn;
+	p_ctrl->p_log = p_log;
+	p_ctrl->p_disp = p_disp;
+	p_ctrl->p_mad_pool = p_mad_pool;
+	p_ctrl->p_vendor = p_vendor;
+	p_ctrl->p_stats = p_stats;
+	p_ctrl->p_lock = p_lock;
+	p_ctrl->p_vl15 = p_vl15;
+
+	p_ctrl->h_disp = cl_disp_register(p_disp,
+					  CL_DISP_MSGID_NONE, NULL, NULL);
+
+	if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: "
+			"Dispatcher registration failed\n");
+		status = IB_INSUFFICIENT_RESOURCES;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * 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);
+
+	if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: "
+			"Multiple binds not allowed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	bind_info.class_version = 1;
+	bind_info.is_report_processor = FALSE;
+	bind_info.is_responder = TRUE;
+	bind_info.is_trap_processor = TRUE;
+	bind_info.mad_class = IB_MCLASS_SUBN_DIR;
+	bind_info.port_guid = port_guid;
+	bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+	bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+	OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
+		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
+
+	p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor,
+					 &bind_info,
+					 p_ctrl->p_mad_pool,
+					 __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, "ERR 3118: "
+			"Vendor specific bind failed\n");
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_ctrl->p_log);
+	return (status);
+}
diff --git a/opensm/osm_sm_state_mgr.c b/opensm/osm_sm_state_mgr.c
new file mode 100644
index 0000000..343a9e3
--- /dev/null
+++ b/opensm/osm_sm_state_mgr.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_state_mgr_t.
+ * This file implements the SM State Manager object.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <time.h>
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sm.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_helper.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_report_sm_state(osm_sm_t * sm)
+{
+	char buf[64];
+	const char *state_str = osm_get_sm_mgr_state_str(sm->p_subn->sm_state);
+
+	osm_log(sm->p_log, OSM_LOG_SYS, "Entering %s state\n", state_str);
+	snprintf(buf, sizeof(buf), "ENTERING SM %s STATE", state_str);
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, buf);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_sm_state_mgr_send_master_sm_info_req(osm_sm_t * sm)
+{
+	osm_madw_context_t context;
+	const osm_port_t *p_port;
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	memset(&context, 0, sizeof(context));
+	if (sm->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_get_port_by_guid(sm->p_subn, sm->master_sm_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 sm.
+		 * Send a query of SubnGet(SMInfo) to that SM.
+		 */
+		p_port = sm->p_polling_sm->p_port;
+	}
+	if (p_port == NULL) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3203: "
+			"No port object for GUID 0x%016" PRIx64 "\n",
+			cl_ntoh64(sm->master_sm_guid));
+		goto Exit;
+	}
+
+	context.smi_context.port_guid = p_port->guid;
+	context.smi_context.set_method = FALSE;
+
+	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
+			     IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE,
+			     &context);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3204: "
+			"Failure requesting SMInfo (%s)\n",
+			ib_get_err_str(status));
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_sm_state_mgr_start_polling(osm_sm_t * sm)
+{
+	uint32_t timeout = sm->p_subn->opt.sminfo_polling_timeout;
+	cl_status_t cl_status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * Init the retry_number back to zero - need to restart counting
+	 */
+	sm->retry_number = 0;
+
+	/*
+	 * Send a SubnGet(SMInfo) query to the current (or new) master found.
+	 */
+	__osm_sm_state_mgr_send_master_sm_info_req(sm);
+
+	/*
+	 * Start a timer that will wake up every sminfo_polling_timeout milliseconds.
+	 * The callback of the timer will send a SubnGet(SMInfo) to the Master SM
+	 * and restart the timer
+	 */
+	cl_status = cl_timer_start(&sm->polling_timer, timeout);
+	if (cl_status != CL_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3210: "
+			"Failed to start timer\n");
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_state_mgr_polling_callback(IN void *context)
+{
+	osm_sm_t *sm = context;
+	uint32_t timeout = sm->p_subn->opt.sminfo_polling_timeout;
+	cl_status_t cl_status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * We can be here in one of two cases:
+	 * 1. We are a STANDBY sm polling on the master SM.
+	 * 2. We are a MASTER sm, waiting for a handover from a remote master sm.
+	 * If we are not in one of these cases - don't need to restart the poller.
+	 */
+	if (!((sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER &&
+	       sm->p_polling_sm != NULL) ||
+	      (sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY)))
+		goto Exit;
+
+	/*
+	 * If we are a STANDBY sm and the osm_exit_flag is set, then let's
+	 * signal the subnet_up. This is relevant for the case of running only
+	 * once. In that case - the program is stuck until this signal is
+	 * received. In other cases - it is not relevant whether or not the
+	 * signal is on - since we are currently in exit flow
+	 */
+	if (sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY && osm_exit_flag) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Signalling subnet_up_event\n");
+		cl_event_signal(&sm->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
+	 */
+	sm->retry_number++;
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Retry number:%d\n", sm->retry_number);
+
+	if (sm->retry_number >= sm->p_subn->opt.polling_retry_number) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Reached polling_retry_number value in retry_number. "
+			"Go to DISCOVERY state\n");
+		osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_POLLING_TIMEOUT);
+		goto Exit;
+	}
+
+	/* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */
+	__osm_sm_state_mgr_send_master_sm_info_req(sm);
+
+	/* restart the timer */
+	cl_status = cl_timer_start(&sm->polling_timer, timeout);
+	if (cl_status != CL_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3211: "
+			"Failed to restart timer\n");
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_sm_state_mgr_signal_error(osm_sm_t * sm,
+					    IN const osm_sm_signal_t signal)
+{
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3207: "
+		"Invalid signal %s in state %s\n",
+		osm_get_sm_mgr_signal_str(signal),
+		osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sm_state_mgr_signal_master_is_alive(osm_sm_t * sm)
+{
+	OSM_LOG_ENTER(sm->p_log);
+	sm->retry_number = 0;
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osm_sm_state_mgr_process(osm_sm_t * sm,
+					 IN osm_sm_signal_t signal)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * The state lock prevents many race conditions from screwing
+	 * up the state transition process.
+	 */
+	cl_spinlock_acquire(&sm->state_lock);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Received signal %s in state %s\n",
+		osm_get_sm_mgr_signal_str(signal),
+		osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+
+	switch (sm->p_subn->sm_state) {
+	case IB_SMINFO_STATE_DISCOVERING:
+		switch (signal) {
+		case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+			/*
+			 * Update the state of the SM to MASTER
+			 */
+			/* Turn on the first_time_master_sweep flag */
+			sm->p_subn->first_time_master_sweep = TRUE;
+			sm->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+			osm_report_sm_state(sm);
+			/*
+			 * Make sure to set the subnet master_sm_base_lid
+			 * to the sm_base_lid value
+			 */
+			sm->p_subn->master_sm_base_lid =
+			    sm->p_subn->sm_base_lid;
+			break;
+		case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+			/*
+			 * Finished all discovery actions - move to STANDBY
+			 * start the polling
+			 */
+			sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+			osm_report_sm_state(sm);
+			/*
+			 * Since another SM is doing the LFT config - we should not
+			 * ignore the results of it
+			 */
+			sm->p_subn->ignore_existing_lfts = FALSE;
+
+			__osm_sm_state_mgr_start_polling(sm);
+			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(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_STANDBY:
+		switch (signal) {
+		case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+		case OSM_SM_SIGNAL_DISCOVER:
+			/*
+			 * case 1: Polling timeout occured - this means that the Master SM
+			 * is no longer alive.
+			 * case 2: Got a signal to move to DISCOVERING
+			 * Move to DISCOVERING state and start sweeping
+			 */
+			sm->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+			osm_report_sm_state(sm);
+			sm->p_subn->coming_out_of_standby = TRUE;
+			osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+			break;
+		case OSM_SM_SIGNAL_DISABLE:
+			/*
+			 * Update the state to NOT_ACTIVE
+			 */
+			sm->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE;
+			osm_report_sm_state(sm);
+			osm_vendor_set_sm(sm->mad_ctrl.h_bind, FALSE);
+			break;
+		case OSM_SM_SIGNAL_HANDOVER:
+			/*
+			 * Update the state to MASTER, and start sweeping
+			 * OPTIONAL: send ACKNOWLEDGE
+			 */
+			/* Turn on the first_time_master_sweep flag */
+			sm->p_subn->first_time_master_sweep = TRUE;
+			/* Turn on the force_heavy_sweep - we want a
+			 * heavy sweep to occur on the first sweep of this SM. */
+			sm->p_subn->force_heavy_sweep = TRUE;
+
+			sm->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+			osm_report_sm_state(sm);
+			/*
+			 * Make sure to set the subnet master_sm_base_lid
+			 * to the sm_base_lid value
+			 */
+			sm->p_subn->master_sm_base_lid =
+			    sm->p_subn->sm_base_lid;
+			sm->p_subn->coming_out_of_standby = TRUE;
+			osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+			break;
+		case OSM_SM_SIGNAL_ACKNOWLEDGE:
+			/*
+			 * Do nothing - already moved to STANDBY
+			 */
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_NOTACTIVE:
+		switch (signal) {
+		case OSM_SM_SIGNAL_STANDBY:
+			/*
+			 * Update the state to STANDBY
+			 * start the polling
+			 */
+			sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+			osm_report_sm_state(sm);
+			__osm_sm_state_mgr_start_polling(sm);
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_MASTER:
+		switch (signal) {
+		case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+			/*
+			 * we received a polling timeout - this means that we waited for
+			 * a remote master sm to send us a handover, but didn't get it, and
+			 * didn't get a response from that remote sm.
+			 * We want to force a heavy sweep - hopefully this occurred because
+			 * the remote sm died, and we'll find this out and configure the
+			 * subnet after a heavy sweep.
+			 * We also want to clear the 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(sm->p_log, OSM_LOG_VERBOSE,
+				"Forcing heavy sweep. "
+				"Received OSM_SM_SIGNAL_HANDOVER or OSM_SM_SIGNAL_POLLING_TIMEOUT\n");
+			sm->p_polling_sm = NULL;
+			sm->p_subn->force_heavy_sweep = TRUE;
+			osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+			break;
+		case OSM_SM_SIGNAL_HANDOVER_SENT:
+			/*
+			 * Just sent a HANDOVER signal - move to STANDBY
+			 * start the polling
+			 */
+			sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+			osm_report_sm_state(sm);
+			__osm_sm_state_mgr_start_polling(sm);
+			break;
+		case OSM_SM_SIGNAL_WAIT_FOR_HANDOVER:
+			/*
+			 * We found a remote master SM, and we are waiting for it
+			 * to handover the mastership to us. Need to start polling
+			 * 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(sm);
+			break;
+		case OSM_SM_SIGNAL_DISCOVER:
+			sm->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+			osm_report_sm_state(sm);
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3208: "
+			"Invalid state %s\n",
+			osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+
+	}
+
+	cl_spinlock_release(&sm->state_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osm_sm_state_mgr_check_legality(osm_sm_t * sm,
+						IN osm_sm_signal_t signal)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * The state lock prevents many race conditions from screwing
+	 * up the state transition process.
+	 */
+	cl_spinlock_acquire(&sm->state_lock);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Received signal %s in state %s\n",
+		osm_get_sm_mgr_signal_str(signal),
+		osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+
+	switch (sm->p_subn->sm_state) {
+	case IB_SMINFO_STATE_DISCOVERING:
+		switch (signal) {
+		case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+		case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+		case OSM_SM_SIGNAL_HANDOVER:
+			status = IB_SUCCESS;
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_STANDBY:
+		switch (signal) {
+		case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+		case OSM_SM_SIGNAL_DISCOVER:
+		case OSM_SM_SIGNAL_DISABLE:
+		case OSM_SM_SIGNAL_HANDOVER:
+		case OSM_SM_SIGNAL_ACKNOWLEDGE:
+			status = IB_SUCCESS;
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_NOTACTIVE:
+		switch (signal) {
+		case OSM_SM_SIGNAL_STANDBY:
+			status = IB_SUCCESS;
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_MASTER:
+		switch (signal) {
+		case OSM_SM_SIGNAL_HANDOVER:
+		case OSM_SM_SIGNAL_HANDOVER_SENT:
+			status = IB_SUCCESS;
+			break;
+		default:
+			__osm_sm_state_mgr_signal_error(sm, signal);
+			status = IB_INVALID_PARAMETER;
+			break;
+		}
+		break;
+
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3209: "
+			"Invalid state %s\n",
+			osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+		status = IB_INVALID_PARAMETER;
+
+	}
+
+	cl_spinlock_release(&sm->state_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
diff --git a/opensm/osm_sminfo_rcv.c b/opensm/osm_sminfo_rcv.c
new file mode 100644
index 0000000..98c1994
--- /dev/null
+++ b/opensm/osm_sminfo_rcv.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_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.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ 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 osm_sm_t * sm,
+				     IN const ib_sm_info_t * p_remote_smi)
+{
+	return (osm_sm_is_greater_than(ib_sminfo_get_priority(p_remote_smi),
+				       p_remote_smi->guid,
+				       sm->p_subn->opt.sm_priority,
+				       sm->p_subn->sm_port_guid));
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_request(IN osm_sm_t * sm,
+				     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(sm->p_log);
+
+	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 = sm->p_subn->sm_port_guid;
+	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
+	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
+				      sm->p_subn->opt.sm_priority << 4);
+	/*
+	   p.840 line 20 - Return 0 for the SM key unless we authenticate the
+	   requester as the master SM.
+	 */
+	p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw));
+	if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to master SM with real sm_key\n");
+		p_smi->sm_key = sm->p_subn->opt.sm_key;
+	} else {
+		/* The requester is not authenticated as master - set sm_key to zero. */
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to SM not master with zero sm_key\n");
+		p_smi->sm_key = 0;
+	}
+
+	status = osm_resp_send(sm, p_madw, 0, payload);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F02: "
+			"Error sending response (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ * Check if the p_smp received is legal.
+ * Current checks:
+ *   MADHeader:AttributeModifier of ACKNOWLEDGE that was not sent by a
+ *             Standby SM.
+ *   MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER
+ *             that was not sent by a Master SM.
+ * FUTURE - TO DO:
+ *   Check that the SM_Key matches.
+ **********************************************************************/
+static ib_api_status_t
+__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 osm_sm_t * sm,
+				     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 *sm_smi;
+	ib_api_status_t status;
+	osm_sm_signal_t sm_signal;
+	ib_sm_info_t *p_remote_smi;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	memset(payload, 0, sizeof(payload));
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	sm_smi = ib_smp_get_payload_ptr(p_smp);
+
+	if (p_smp->method != IB_MAD_METHOD_SET) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F03: "
+			"Unsupported method 0x%X\n", p_smp->method);
+		goto Exit;
+	}
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+
+	p_smi->guid = sm->p_subn->sm_port_guid;
+	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
+	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
+				      sm->p_subn->opt.sm_priority << 4);
+	/*
+	   p.840 line 20 - Return 0 for the SM key unless we authenticate the
+	   requester as the master SM.
+	 */
+	p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw));
+	if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to master SM with real sm_key\n");
+		p_smi->sm_key = sm->p_subn->opt.sm_key;
+	} else {
+		/* The requester is not authenticated as master - set sm_key to zero. */
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to SM not master with zero sm_key\n");
+		p_smi->sm_key = 0;
+	}
+
+	/* Check the legality of the packet */
+	status = __osm_sminfo_rcv_check_set_req_legality(p_smp);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F04: "
+			"Check legality failed. AttributeModifier:0x%X RemoteState:%s\n",
+			p_smp->attr_mod,
+			osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi)));
+		status = osm_resp_send(sm, p_madw, 7, payload);
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F05: "
+				"Error sending response (%s)\n",
+				ib_get_err_str(status));
+		CL_PLOCK_RELEASE(sm->p_lock);
+		goto Exit;
+	}
+
+	/* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */
+	switch (p_smp->attr_mod) {
+	case IB_SMINFO_ATTR_MOD_HANDOVER:
+		sm_signal = OSM_SM_SIGNAL_HANDOVER;
+		break;
+	case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE:
+		sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE;
+		break;
+	case IB_SMINFO_ATTR_MOD_DISABLE:
+		sm_signal = OSM_SM_SIGNAL_DISABLE;
+		break;
+	case IB_SMINFO_ATTR_MOD_STANDBY:
+		sm_signal = OSM_SM_SIGNAL_STANDBY;
+		break;
+	case IB_SMINFO_ATTR_MOD_DISCOVER:
+		sm_signal = OSM_SM_SIGNAL_DISCOVER;
+		break;
+	default:
+		/*
+		   This code shouldn't be reached - checked in the
+		   check legality
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F06: "
+			"THIS CODE SHOULD NOT BE REACHED!!\n");
+		CL_PLOCK_RELEASE(sm->p_lock);
+		goto Exit;
+	}
+
+	/* check legality of the needed transition in the SM state machine */
+	status = osm_sm_state_mgr_check_legality(sm, sm_signal);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F07: "
+			"Failed check of legality of needed SM transition. AttributeModifier:0x%X RemoteState:%s\n",
+			p_smp->attr_mod,
+			osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi)));
+		status = osm_resp_send(sm, p_madw, 7, payload);
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F08: "
+				"Error sending response (%s)\n",
+				ib_get_err_str(status));
+		CL_PLOCK_RELEASE(sm->p_lock);
+		goto Exit;
+	}
+
+	/* the SubnSet(SMInfo) command is ok. Send a response. */
+	status = osm_resp_send(sm, p_madw, 0, payload);
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F09: "
+			"Error sending response (%s)\n",
+			ib_get_err_str(status));
+
+	/* it is a legal packet - act according to it */
+
+	/* if the AttributeModifier is STANDBY - need to save on the sm in */
+	/* the master_sm_guid variable - the guid of the current master. */
+	if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Received a STANDBY signal. Updating "
+			"sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
+			cl_ntoh64(sm_smi->guid));
+		sm->master_sm_guid = sm_smi->guid;
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+	status = osm_sm_state_mgr_process(sm, sm_signal);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F10: "
+			"Error in SM state transition (%s)\n",
+			ib_get_err_str(status));
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_sminfo_rcv_process_get_sm(IN osm_sm_t * sm,
+				IN const osm_remote_sm_t * const p_sm,
+				boolean_t light_sweep)
+{
+	const ib_sm_info_t *p_smi;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_smi = &p_sm->smi;
+
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Detected SM 0x%016" PRIx64 " in state %u\n",
+		cl_ntoh64(p_smi->guid), ib_sminfo_get_state(p_smi));
+
+	/* Check the state of this SM vs. our own. */
+	switch (sm->p_subn->sm_state) {
+	case IB_SMINFO_STATE_NOTACTIVE:
+		break;
+
+	case IB_SMINFO_STATE_DISCOVERING:
+		switch (ib_sminfo_get_state(p_smi)) {
+		case IB_SMINFO_STATE_NOTACTIVE:
+			break;
+		case IB_SMINFO_STATE_MASTER:
+			sm->master_sm_found = 1;
+			/* save on the sm the guid of the current master. */
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"Found master SM. Updating sm_state_mgr master_guid: 0x%016"
+				PRIx64 "\n", cl_ntoh64(p_sm->p_port->guid));
+			sm->master_sm_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(sm, p_smi)
+			    == TRUE) {
+				/* the remote is a higher sm - need to stop sweeping */
+				sm->master_sm_found = 1;
+				/* save on the sm the guid of the higher SM we found - */
+				/* we will poll it - as long as it lives - we should be in Standby. */
+				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+					"Found higher SM. Updating sm_state_mgr master_guid:"
+					" 0x%016" PRIx64 "\n",
+					cl_ntoh64(p_sm->p_port->guid));
+				sm->master_sm_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(sm);
+			break;
+		case IB_SMINFO_STATE_STANDBY:
+			/* This should be the response from the sm we are polling. */
+			/* If it is - then signal master is alive */
+			if (sm->master_sm_guid == p_sm->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
+				    (sm, p_smi) == TRUE)
+					osm_sm_state_mgr_signal_master_is_alive(sm);
+			}
+			break;
+		default:
+			/* any other state - do nothing */
+			break;
+		}
+		break;
+
+	case IB_SMINFO_STATE_MASTER:
+		switch (ib_sminfo_get_state(p_smi)) {
+		case IB_SMINFO_STATE_MASTER:
+			/* If this is a response due to our polling, this means that we are
+			   waiting for a handover from this SM, and it is still alive -
+			   signal that. */
+			if (sm->p_polling_sm)
+				osm_sm_state_mgr_signal_master_is_alive(sm);
+			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;
+		case IB_SMINFO_STATE_STANDBY:
+			if (light_sweep &&
+			    __osm_sminfo_rcv_remote_sm_is_higher(sm, p_smi))
+				sm->p_subn->force_heavy_sweep = TRUE;
+			break;
+		default:
+			/* any other state - do nothing */
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_response(IN osm_sm_t * sm,
+				      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;
+	osm_port_t *p_port;
+	ib_net64_t port_guid;
+	osm_remote_sm_t *p_sm;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	if (p_smp->method != IB_MAD_METHOD_GET_RESP) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F11: "
+			"Unsupported method 0x%X\n", p_smp->method);
+		goto Exit;
+	}
+
+	p_smi = ib_smp_get_payload_ptr(p_smp);
+	p_sm_tbl = &sm->p_subn->sm_guid_tbl;
+	port_guid = p_smi->guid;
+
+	osm_dump_sm_info(sm->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 != sm->p_subn->opt.sm_key) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F18: "
+			"Got SM with sm_key that doesn't match our "
+			"local key. Exiting\n");
+		osm_log(sm->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(sm->p_lock);
+
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F12: "
+			"No port object for this SM\n");
+		goto _unlock_and_exit;
+	}
+
+	if (osm_port_get_guid(p_port) != p_smi->guid) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F13: "
+			"Bogus SM port GUID\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 _unlock_and_exit;
+	}
+
+	if (port_guid == sm->p_subn->sm_port_guid) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Self query response received - SM port 0x%016" PRIx64
+			"\n", cl_ntoh64(port_guid));
+		goto _unlock_and_exit;
+	}
+
+	p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid);
+	if (p_sm == (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) {
+		p_sm = malloc(sizeof(*p_sm));
+		if (p_sm == NULL) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F14: "
+				"Unable to allocate SM object\n");
+			goto _unlock_and_exit;
+		}
+
+		osm_remote_sm_init(p_sm, p_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;
+
+	__osm_sminfo_rcv_process_get_sm(sm, p_sm,
+					osm_madw_get_smi_context_ptr(p_madw)->light_sweep);
+
+_unlock_and_exit:
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_set_response(IN osm_sm_t * sm,
+				      IN const osm_madw_t * const p_madw)
+{
+	const ib_smp_t *p_smp;
+	const ib_sm_info_t *p_smi;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	if (p_smp->method != IB_MAD_METHOD_GET_RESP) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F16: "
+			"Unsupported method 0x%X\n", p_smp->method);
+		goto Exit;
+	}
+
+	p_smi = ib_smp_get_payload_ptr(p_smp);
+	osm_dump_sm_info(sm->p_log, p_smi, OSM_LOG_DEBUG);
+
+	/* Check the AttributeModifier */
+	if (p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F17: "
+			"Unsupported attribute modifier 0x%X\n",
+			p_smp->attr_mod);
+		goto Exit;
+	}
+
+	/* This is a response on a HANDOVER request - Nothing to do. */
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_sminfo_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_smp_t *p_smp;
+	osm_smi_context_t *p_smi_context;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	/* Determine if this is a request for our own SMInfo or if
+	   this is a response to our request for another SM's SMInfo. */
+	if (ib_smp_is_response(p_smp)) {
+		const ib_sm_info_t *p_smi = ib_smp_get_payload_ptr(p_smp);
+
+		/* Get the context - to see if this is a response to a Get or Set method */
+		p_smi_context = osm_madw_get_smi_context_ptr(p_madw);
+
+		/* Verify that response is from expected port and there is
+		   no port moving issue. */
+		if (p_smi_context->port_guid != p_smi->guid) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F19: "
+				"Unexpected SM port GUID in response"
+				"\n\t\t\t\tExpected 0x%016" PRIx64
+				", Received 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_smi_context->port_guid),
+				cl_ntoh64(p_smi->guid));
+			goto Exit;
+		}
+
+		if (p_smi_context->set_method == FALSE)
+			/* this is a response to a Get method */
+			__osm_sminfo_rcv_process_get_response(sm, p_madw);
+		else
+			/* this is a response to a Set method */
+			__osm_sminfo_rcv_process_set_response(sm, p_madw);
+	} else if (p_smp->method == IB_MAD_METHOD_GET)
+		/* This is a SubnGet request */
+		__osm_sminfo_rcv_process_get_request(sm, p_madw);
+	else
+		/* This should be a SubnSet request */
+		__osm_sminfo_rcv_process_set_request(sm, p_madw);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_state_mgr.c b/opensm/osm_state_mgr.c
new file mode 100644
index 0000000..b2a4a2e
--- /dev/null
+++ b/opensm/osm_state_mgr.c
@@ -0,0 +1,1397 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_t.
+ * This file implements the State Manager object.
+ */
+
+#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 <complib/cl_qmap.h>
+#include <opensm/osm_sm.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_inform.h>
+#include <opensm/osm_opensm.h>
+
+extern void osm_drop_mgr_process(IN osm_sm_t * sm);
+extern osm_signal_t osm_qos_setup(IN osm_opensm_t * p_osm);
+extern osm_signal_t osm_pkey_mgr_process(IN osm_opensm_t * p_osm);
+extern osm_signal_t osm_mcast_mgr_process(IN osm_sm_t * sm);
+extern osm_signal_t osm_mcast_mgr_process_mgroups(IN osm_sm_t * sm);
+extern osm_signal_t osm_link_mgr_process(IN osm_sm_t * sm, IN uint8_t state);
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_state_mgr_up_msg(IN const osm_sm_t * sm)
+{
+	/*
+	 * This message should be written only once - when the
+	 * SM moves to Master state and the subnet is up for
+	 * the first time.
+	 */
+	osm_log(sm->p_log, sm->p_subn->first_time_master_sweep ?
+		OSM_LOG_SYS : OSM_LOG_INFO, "SUBNET UP\n");
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			sm->p_subn->opt.sweep_interval ?
+			"SUBNET UP" : "SUBNET UP (sweep disabled)");
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __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;
+
+	p_node->discovery_count = 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+
+	p_port->discovery_count = 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+
+	p_sw->discovery_count = 0;
+	p_sw->need_update = 1;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_sm_t *sm = context;
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_node = p_sw->p_node;
+	p_dr_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));
+
+	memset(&mad_context, 0, sizeof(mad_context));
+
+	mad_context.si_context.node_guid = osm_node_get_node_guid(p_node);
+	mad_context.si_context.set_method = FALSE;
+	mad_context.si_context.light_sweep = TRUE;
+
+	status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_SWITCH_INFO, 0,
+			     OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3304: "
+			"Request for SwitchInfo failed\n");
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ Initiate a remote port info request for the given physical port
+ **********************************************************************/
+static void
+__osm_state_mgr_get_remote_port_info(IN osm_sm_t * sm,
+				     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(sm->p_log);
+
+	/* generate a dr path leaving on the physp to the remote node */
+	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
+	memcpy(&rem_node_dr_path, p_dr_path, sizeof(osm_dr_path_t));
+	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 = p_physp->port_guid;
+	mad_context.pi_context.set_method = FALSE;
+	mad_context.pi_context.light_sweep = TRUE;
+	mad_context.pi_context.active_transition = FALSE;
+
+	/* note that with some negative logic - if the query failed it means that
+	 * there is no point in going to heavy sweep */
+	status = osm_req_get(sm, &rem_node_dr_path,
+			     IB_MAD_ATTR_PORT_INFO, 0, CL_DISP_MSGID_NONE,
+			     &mad_context);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332E: "
+			"Request for PortInfo failed\n");
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ Initiates a thorough sweep of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t __osm_state_mgr_sweep_hop_0(IN osm_sm_t * sm)
+{
+	ib_api_status_t status;
+	osm_dr_path_t dr_path;
+	osm_bind_handle_t h_bind;
+	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	memset(path_array, 0, sizeof(path_array));
+
+	/*
+	 * First, get the bind handle.
+	 */
+	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
+	if (h_bind != OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+				"INITIATING HEAVY SWEEP");
+		/*
+		 * Start the sweep by clearing the port counts, then
+		 * get our own NodeInfo at 0 hops.
+		 */
+		CL_PLOCK_ACQUIRE(sm->p_lock);
+
+		cl_qmap_apply_func(&sm->p_subn->node_guid_tbl,
+				   __osm_state_mgr_reset_node_count, sm);
+
+		cl_qmap_apply_func(&sm->p_subn->port_guid_tbl,
+				   __osm_state_mgr_reset_port_count, sm);
+
+		cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl,
+				   __osm_state_mgr_reset_switch_count, sm);
+
+		/* Set the in_sweep_hop_0 flag in subn to be TRUE.
+		 * This will indicate the sweeping not to continue beyond the
+		 * the current node.
+		 * This is relevant for the case of SM on switch, since in the
+		 * switch info we need to signal somehow not to continue
+		 * the sweeping. */
+		sm->p_subn->in_sweep_hop_0 = TRUE;
+
+		CL_PLOCK_RELEASE(sm->p_lock);
+
+		osm_dr_path_init(&dr_path, h_bind, 0, path_array);
+		status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_NODE_INFO, 0,
+				     CL_DISP_MSGID_NONE, NULL);
+
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3305: "
+				"Request for NodeInfo failed\n");
+	} else {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"No bound ports. Deferring sweep...\n");
+		status = IB_INVALID_STATE;
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ Clear out all existing port lid assignments
+**********************************************************************/
+static ib_api_status_t __osm_state_mgr_clean_known_lids(IN osm_sm_t * sm)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	cl_ptr_vector_t *p_vec = &(sm->p_subn->port_lid_tbl);
+	uint32_t i;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/* we need a lock here! */
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+
+	for (i = 0; i < cl_ptr_vector_get_size(p_vec); i++)
+		cl_ptr_vector_set(p_vec, i, NULL);
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ 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_sm_t * sm)
+{
+	ib_api_status_t status;
+	osm_bind_handle_t h_bind;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * First, get the bind handle.
+	 */
+	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
+	if (h_bind == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3306: "
+			"No bound ports\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*
+	 * Notify the transport layer that we changed the local LID.
+	 */
+	status = osm_vendor_local_lid_change(h_bind);
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3307: "
+			"Vendor LID update failed (%s)\n",
+			ib_get_err_str(status));
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ Returns true if the SM port is down.
+ The SM's port object must exist in the port_guid table.
+**********************************************************************/
+static boolean_t __osm_state_mgr_is_sm_port_down(IN osm_sm_t * sm)
+{
+	ib_net64_t port_guid;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	uint8_t state;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	port_guid = sm->p_subn->sm_port_guid;
+
+	/*
+	 * If we don't know our own port guid yet, assume the port is down.
+	 */
+	if (port_guid == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3308: "
+			"SM port GUID unknown\n");
+		state = IB_LINK_DOWN;
+		goto Exit;
+	}
+
+	CL_ASSERT(port_guid);
+
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3309: "
+			"SM port with GUID:%016" PRIx64 " is unknown\n",
+			cl_ntoh64(port_guid));
+		state = IB_LINK_DOWN;
+		CL_PLOCK_RELEASE(sm->p_lock);
+		goto Exit;
+	}
+
+	p_physp = p_port->p_physp;
+
+	CL_ASSERT(p_physp);
+
+	state = osm_physp_get_port_state(p_physp);
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (state == IB_LINK_DOWN);
+}
+
+/**********************************************************************
+ Sweeps the node 1 hop away.
+ This sets off a "chain reaction" that causes discovery of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t __osm_state_mgr_sweep_hop_1(IN osm_sm_t * sm)
+{
+	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;
+	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+	uint8_t num_ports;
+	osm_physp_t *p_ext_physp;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	/*
+	 * First, get our own port and node objects.
+	 */
+	port_guid = sm->p_subn->sm_port_guid;
+
+	CL_ASSERT(port_guid);
+
+	/* Set the in_sweep_hop_0 flag in subn to be FALSE.
+	 * This will indicate the sweeping to continue beyond the
+	 * the current node.
+	 * This is relevant for the case of SM on switch, since in the
+	 * switch info we need to signal that the sweeping should
+	 * continue through the switch. */
+	sm->p_subn->in_sweep_hop_0 = FALSE;
+
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: "
+			"No SM port object\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	p_node = p_port->p_node;
+	CL_ASSERT(p_node);
+
+	port_num = ib_node_info_get_local_port_num(&p_node->node_info);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Probing hop 1 on local port %u\n", port_num);
+
+	p_physp = osm_node_get_physp_ptr(p_node, port_num);
+
+	CL_ASSERT(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:
+		memset(&context, 0, sizeof(context));
+		context.ni_context.node_guid = osm_node_get_node_guid(p_node);
+		context.ni_context.port_num = port_num;
+
+		path_array[1] = port_num;
+
+		osm_dr_path_init(&hop_1_path, h_bind, 1, path_array);
+		status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0,
+				     CL_DISP_MSGID_NONE, &context);
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: "
+				"Request for NodeInfo failed\n");
+		break;
+
+	case IB_NODE_TYPE_SWITCH:
+		/* Need to go over all the ports of the switch, and send a node_info
+		 * from them. This doesn't include the port 0 of the switch, which
+		 * hosts the SM.
+		 * Note: We'll send another switchInfo on port 0, since if no ports
+		 * are connected, we still want to get some response, and have the
+		 * subnet come up.
+		 */
+		num_ports = osm_node_get_num_physp(p_node);
+		for (port_num = 0; port_num < num_ports; port_num++) {
+			/* go through the port only if the port is not DOWN */
+			p_ext_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (p_ext_physp && ib_port_info_get_port_state
+			    (&(p_ext_physp->port_info)) > IB_LINK_DOWN) {
+				memset(&context, 0, sizeof(context));
+				context.ni_context.node_guid =
+				    osm_node_get_node_guid(p_node);
+				context.ni_context.port_num = port_num;
+
+				path_array[1] = port_num;
+				osm_dr_path_init(&hop_1_path, h_bind, 1,
+						 path_array);
+				status = osm_req_get(sm, &hop_1_path,
+						     IB_MAD_ATTR_NODE_INFO, 0,
+						     CL_DISP_MSGID_NONE,
+						     &context);
+
+				if (status != IB_SUCCESS)
+					OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3312: "
+						"Request for NodeInfo failed\n");
+			}
+		}
+		break;
+
+	default:
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 3313: Unknown node type %d (%s)\n",
+			osm_node_get_type(p_node), p_node->print_desc);
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+static void query_sm_info(cl_map_item_t *item, void *cxt)
+{
+	osm_madw_context_t context;
+	osm_remote_sm_t *r_sm = cl_item_obj(item, r_sm, map_item);
+	osm_sm_t *sm = cxt;
+	ib_api_status_t ret;
+
+	context.smi_context.port_guid = r_sm->p_port->guid;
+	context.smi_context.set_method = FALSE;
+	context.smi_context.light_sweep = TRUE;
+
+	ret = osm_req_get(sm, osm_physp_get_dr_path_ptr(r_sm->p_port->p_physp),
+			  IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE, &context);
+	if (ret != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3314: "
+			"Failure requesting SMInfo (%s)\n",
+			ib_get_err_str(ret));
+}
+
+/**********************************************************************
+ During a light sweep check each node to see if the node descriptor is valid
+ if not issue a ND query.
+**********************************************************************/
+static void __osm_state_mgr_get_node_desc(IN cl_map_item_t * const p_object,
+					  IN void *context)
+{
+	osm_madw_context_t mad_context;
+	osm_node_t *const p_node = (osm_node_t *) p_object;
+	osm_sm_t *sm = context;
+	osm_physp_t *p_physp = NULL;
+	unsigned i, num_ports;
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_node);
+
+	if (p_node->print_desc && strcmp(p_node->print_desc, OSM_NODE_DESC_UNKNOWN))
+		/* if ND is valid, do nothing */
+		goto exit;
+
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+		"ERR 3319: Unknown node description for node GUID "
+		"0x%016" PRIx64 ".  Reissuing ND query\n",
+		cl_ntoh64(osm_node_get_node_guid (p_node)));
+
+	/* get a physp to request from. */
+	num_ports = osm_node_get_num_physp(p_node);
+	for (i = 0; i < num_ports; i++)
+		if ((p_physp = osm_node_get_physp_ptr(p_node, i)))
+			break;
+
+	if (!p_physp) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: "
+			"Failed to find any valid physical port object.\n");
+		goto exit;
+	}
+
+	mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node);
+
+	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
+			     IB_MAD_ATTR_NODE_DESC, 0, CL_DISP_MSGID_NONE,
+			     &mad_context);
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"ERR 331B: Failure initiating NodeDescription request "
+			"(%s)\n", ib_get_err_str(status));
+
+exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ Initiates a lightweight sweep of the subnet.
+ Used during normal sweeps after the subnet is up.
+**********************************************************************/
+static ib_api_status_t __osm_state_mgr_light_sweep_start(IN osm_sm_t * sm)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osm_bind_handle_t h_bind;
+	cl_qmap_t *p_sw_tbl;
+	cl_map_item_t *p_next;
+	osm_node_t *p_node;
+	osm_physp_t *p_physp;
+	uint8_t port_num;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_sw_tbl = &sm->p_subn->sw_guid_tbl;
+
+	/*
+	 * First, get the bind handle.
+	 */
+	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
+	if (h_bind == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"No bound ports. Deferring sweep...\n");
+		status = IB_INVALID_STATE;
+		goto _exit;
+	}
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP");
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	cl_qmap_apply_func(p_sw_tbl, __osm_state_mgr_get_sw_info, sm);
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, __osm_state_mgr_get_node_desc, sm);
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	/* now scan the list of physical ports that were not down but have no remote port */
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl);
+	while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) {
+		p_node = (osm_node_t *) p_next;
+		p_next = cl_qmap_next(p_next);
+
+		for (port_num = 1; port_num < osm_node_get_num_physp(p_node);
+		     port_num++) {
+			p_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (p_physp && (osm_physp_get_port_state(p_physp) !=
+					IB_LINK_DOWN)
+			    && !osm_physp_get_remote(p_physp)) {
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: "
+					"Unknown remote side for node 0x%016"
+					PRIx64
+					"(%s) port %u. Adding to light sweep sampling list\n",
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_node)),
+					p_node->print_desc, port_num);
+
+				osm_dump_dr_path(sm->p_log,
+						 osm_physp_get_dr_path_ptr
+						 (p_physp), OSM_LOG_ERROR);
+
+				__osm_state_mgr_get_remote_port_info(sm,
+								     p_physp);
+			}
+		}
+	}
+
+	cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm);
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+_exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ * Go over all the remote SMs (as updated in the sm_guid_tbl).
+ * Find if there is a remote sm that is a master SM.
+ * If there is a remote master SM - return a pointer to it,
+ * else - return NULL.
+ **********************************************************************/
+static osm_remote_sm_t *__osm_state_mgr_exists_other_master_sm(IN osm_sm_t * sm)
+{
+	cl_qmap_t *p_sm_tbl;
+	osm_remote_sm_t *p_sm;
+	osm_remote_sm_t *p_sm_res = NULL;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_sm_tbl = &sm->p_subn->sm_guid_tbl;
+
+	/* go over all the remote SMs */
+	for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl);
+	     p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl);
+	     p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) {
+		/* If the sm is in MASTER state - return a pointer to it */
+		if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) {
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"Found remote master SM with guid:0x%016" PRIx64
+				" (node %s)\n", cl_ntoh64(p_sm->smi.guid),
+				p_sm->p_port->p_node ? p_sm->p_port->p_node->
+				print_desc : "UNKNOWN");
+			p_sm_res = p_sm;
+			goto Exit;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+	return (p_sm_res);
+}
+
+/**********************************************************************
+ * Go over all remote SMs (as updated in the sm_guid_tbl).
+ * Find the one with the highest priority and lowest guid.
+ * Compare this SM to the local SM. If the local SM is higher -
+ * return NULL, if the remote SM is higher - return a pointer to it.
+ **********************************************************************/
+static osm_remote_sm_t *__osm_state_mgr_get_highest_sm(IN osm_sm_t * sm)
+{
+	cl_qmap_t *p_sm_tbl;
+	osm_remote_sm_t *p_sm = NULL;
+	osm_remote_sm_t *p_highest_sm;
+	uint8_t highest_sm_priority;
+	ib_net64_t highest_sm_guid;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	p_sm_tbl = &sm->p_subn->sm_guid_tbl;
+
+	/* Start with the local sm as the standard */
+	p_highest_sm = NULL;
+	highest_sm_priority = sm->p_subn->opt.sm_priority;
+	highest_sm_guid = sm->p_subn->sm_port_guid;
+
+	/* go over all the remote SMs */
+	for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl);
+	     p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl);
+	     p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) {
+
+		/* If the sm is in NOTACTIVE state - continue */
+		if (ib_sminfo_get_state(&p_sm->smi) ==
+		    IB_SMINFO_STATE_NOTACTIVE)
+			continue;
+
+		if (osm_sm_is_greater_than(ib_sminfo_get_priority(&p_sm->smi),
+					   p_sm->smi.guid, highest_sm_priority,
+					   highest_sm_guid)) {
+			/* the new p_sm is with higher priority - update the highest_sm */
+			/* to this sm */
+			p_highest_sm = p_sm;
+			highest_sm_priority =
+			    ib_sminfo_get_priority(&p_sm->smi);
+			highest_sm_guid = p_sm->smi.guid;
+		}
+	}
+
+	if (p_highest_sm != NULL)
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Found higher SM with guid: %016" PRIx64 " (node %s)\n",
+			cl_ntoh64(p_highest_sm->smi.guid),
+			p_highest_sm->p_port->p_node ?
+			p_highest_sm->p_port->p_node->print_desc : "UNKNOWN");
+
+	OSM_LOG_EXIT(sm->p_log);
+	return (p_highest_sm);
+}
+
+/**********************************************************************
+ * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
+ * remote_sm indicated.
+ **********************************************************************/
+static void
+__osm_state_mgr_send_handover(IN osm_sm_t * const sm,
+			      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(sm->p_log);
+
+	/*
+	 * 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(sm->p_log, OSM_LOG_ERROR, "ERR 3316: "
+			"No port object on given remote_sm object\n");
+		goto Exit;
+	}
+
+	/* update the master_guid in the sm_state_mgr object according to */
+	/* the guid of the port where the new Master SM should reside. */
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Handing over mastership. Updating sm_state_mgr master_guid: %016"
+		PRIx64 " (node %s)\n", cl_ntoh64(p_port->guid),
+		p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN");
+	sm->master_sm_guid = p_port->guid;
+
+	context.smi_context.port_guid = p_port->guid;
+	context.smi_context.set_method = TRUE;
+
+	p_smi->guid = sm->p_subn->sm_port_guid;
+	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
+	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
+				      sm->p_subn->opt.sm_priority << 4);
+	/*
+	 * Return 0 for the SM key unless we authenticate the requester
+	 * as the master SM.
+	 */
+	if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to master SM with real sm_key\n");
+		p_smi->sm_key = sm->p_subn->opt.sm_key;
+	} else {
+		/* The requester is not authenticated as master - set sm_key to zero */
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Responding to SM not master with zero sm_key\n");
+		p_smi->sm_key = 0;
+	}
+
+	status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
+			     payload, sizeof(payload), IB_MAD_ATTR_SM_INFO,
+			     IB_SMINFO_ATTR_MOD_HANDOVER, CL_DISP_MSGID_NONE,
+			     &context);
+
+	if (status != IB_SUCCESS)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3317: "
+			"Failure requesting SMInfo (%s)\n",
+			ib_get_err_str(status));
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ * Send Trap 64 on all new ports.
+ **********************************************************************/
+static void __osm_state_mgr_report_new_ports(IN osm_sm_t * sm)
+{
+	ib_gid_t port_gid;
+	ib_mad_notice_attr_t notice;
+	ib_api_status_t status;
+	ib_net64_t port_guid;
+	cl_map_item_t *p_next;
+	osm_port_t *p_port;
+	uint16_t min_lid_ho;
+	uint16_t max_lid_ho;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl);
+	while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) {
+		p_port = (osm_port_t *) p_next;
+		p_next = cl_qmap_next(p_next);
+
+		if (!p_port->is_new)
+			continue;
+
+		port_guid = osm_port_get_guid(p_port);
+		/* issue a notice - trap 64 */
+
+		/* details of the notice */
+		notice.generic_type = 0x83;	/* is generic subn mgt type */
+		ib_notice_set_prod_type_ho(&notice, 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 = sm->p_subn->sm_base_lid;
+		/* following C14-72.1.1 and table 119 p739 */
+		/* we need to provide the GID */
+		port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
+		port_gid.unicast.interface_id = port_guid;
+		memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid),
+		       sizeof(ib_gid_t));
+
+		/* According to page 653 - the issuer gid in this case of trap
+		 * is the SM gid, since the SM is the initiator of this trap. */
+		notice.issuer_gid.unicast.prefix =
+		    sm->p_subn->opt.subnet_prefix;
+		notice.issuer_gid.unicast.interface_id =
+		    sm->p_subn->sm_port_guid;
+
+		status = osm_report_notice(sm->p_log, sm->p_subn, &notice);
+		if (status != IB_SUCCESS)
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: "
+				"Error sending trap reports on GUID:0x%016"
+				PRIx64 " (%s)\n", port_gid.unicast.interface_id,
+				ib_get_err_str(status));
+		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+		OSM_LOG(sm->p_log, OSM_LOG_INFO,
+			"Discovered new port with GUID:0x%016" PRIx64
+			" LID range [%u,%u] of node:%s\n",
+			cl_ntoh64(port_gid.unicast.interface_id),
+			min_lid_ho, max_lid_ho,
+			p_port->p_node ? p_port->p_node->
+			print_desc : "UNKNOWN");
+
+		p_port->is_new = 0;
+	}
+	CL_PLOCK_RELEASE(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ * Make sure that the lid_port_tbl of the subnet has only the ports
+ * that are recognized, and in the correct lid place. There could be
+ * errors if we wanted to assign a certain port with lid X, but that
+ * request didn't reach the port. In this case port_lid_tbl will have
+ * the port under lid X, though the port isn't updated with this lid.
+ * We will run a new heavy sweep (since there were errors in the
+ * initialization), but here we'll clean the database from incorrect
+ * information.
+ **********************************************************************/
+static void __osm_state_mgr_check_tbl_consistency(IN osm_sm_t * sm)
+{
+	cl_qmap_t *p_port_guid_tbl;
+	osm_port_t *p_port;
+	osm_port_t *p_next_port;
+	cl_ptr_vector_t *p_port_lid_tbl;
+	size_t max_lid, ref_size, curr_size, lid;
+	osm_port_t *p_port_ref, *p_port_stored;
+	cl_ptr_vector_t ref_port_lid_tbl;
+	uint16_t min_lid_ho;
+	uint16_t max_lid_ho;
+	uint16_t lid_ho;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	cl_ptr_vector_construct(&ref_port_lid_tbl);
+	cl_ptr_vector_init(&ref_port_lid_tbl,
+			   cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl),
+			   OSM_SUBNET_VECTOR_GROW_SIZE);
+
+	p_port_guid_tbl = &sm->p_subn->port_guid_tbl;
+
+	/* Let's go over all the ports according to port_guid_tbl,
+	 * and add the port to a reference port_lid_tbl. */
+	p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
+	while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) {
+		p_port = p_next_port;
+		p_next_port =
+		    (osm_port_t *) cl_qmap_next(&p_next_port->map_item);
+
+		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+		for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
+			cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port);
+	}
+
+	p_port_lid_tbl = &sm->p_subn->port_lid_tbl;
+
+	ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl);
+	curr_size = cl_ptr_vector_get_size(p_port_lid_tbl);
+	/* They should be the same, but compare it anyway */
+	max_lid = (ref_size > curr_size) ? ref_size : curr_size;
+
+	for (lid = 1; lid <= max_lid; lid++) {
+		p_port_ref = NULL;
+		p_port_stored = NULL;
+		cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored);
+		cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref);
+
+		if (p_port_stored == p_port_ref)
+			/* This is the "good" case - both entries are the
+			 * same for this lid. Nothing to do. */
+			continue;
+
+		if (p_port_ref == NULL)
+			/* There is an object in the subnet database for this
+			 * lid, but no such object exists in the reference
+			 * port_list_tbl. This can occur if we wanted to assign
+			 * a certain port with some lid (different than the one
+			 * pre-assigned to it), and the port didn't get the
+			 * PortInfo Set request. Due to this, the port is
+			 * updated with its original lid in our database, but
+			 * with the new lid we wanted to give it in our
+			 * port_lid_tbl. */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: "
+				"lid %zu is wrongly assigned to port 0x%016"
+				PRIx64 " (\'%s\' port %u) in port_lid_tbl\n",
+				lid,
+				cl_ntoh64(osm_port_get_guid(p_port_stored)),
+				p_port_stored->p_node->print_desc,
+				p_port_stored->p_physp->port_num);
+		else if (p_port_stored == NULL)
+			/* There is an object in the new database, but no
+			 * object in our subnet database. This is the matching
+			 * case of the prior check - the port still has its
+			 * original lid. */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: "
+				"port 0x%016" PRIx64 " (\'%s\' port %u)"
+				" exists in new port_lid_tbl under lid %zu,"
+				" but missing in subnet port_lid_tbl db\n",
+				cl_ntoh64(osm_port_get_guid(p_port_ref)),
+				p_port_ref->p_node->print_desc,
+				p_port_ref->p_physp->port_num, lid);
+		else
+			/* if we reached here then p_port_stored != p_port_ref.
+			 * We were trying to set a lid to p_port_stored, but
+			 * it didn't reach it, and p_port_ref also didn't get
+			 * the lid update. */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: "
+				"lid %zu has port 0x%016" PRIx64
+				" (\'%s\' port %u) in new port_lid_tbl db, "
+				"and port 0x%016" PRIx64 " (\'%s\' port %u)"
+				" in subnet port_lid_tbl db\n", lid,
+				cl_ntoh64(osm_port_get_guid(p_port_ref)),
+				p_port_ref->p_node->print_desc,
+				p_port_ref->p_physp->port_num,
+				cl_ntoh64(osm_port_get_guid(p_port_stored)),
+				p_port_ref->p_node->print_desc,
+				p_port_ref->p_physp->port_num);
+
+		/* 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);
+		sm->p_subn->subnet_initialization_error = TRUE;
+	}
+
+	cl_ptr_vector_destroy(&ref_port_lid_tbl);
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+static void cleanup_switch(cl_map_item_t *item, void *log)
+{
+	osm_switch_t *sw = (osm_switch_t *)item;
+
+	if (!sw->new_lft)
+		return;
+	
+	if (memcmp(sw->lft, sw->new_lft, IB_LID_UCAST_END_HO + 1))
+		osm_log(log, OSM_LOG_ERROR, "ERR 331D: "
+			"LFT of switch 0x%016" PRIx64 " is not up to date.\n",
+			cl_ntoh64(sw->p_node->node_info.node_guid));
+	else {
+		free(sw->new_lft);
+		sw->new_lft = NULL;
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+int wait_for_pending_transactions(osm_stats_t * stats)
+{
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_lock(&stats->mutex);
+	while (stats->qp0_mads_outstanding && !osm_exit_flag)
+		pthread_cond_wait(&stats->cond, &stats->mutex);
+	pthread_mutex_unlock(&stats->mutex);
+#else
+	while (1) {
+		unsigned count = stats->qp0_mads_outstanding;
+		if (!count || osm_exit_flag)
+			break;
+		cl_event_wait_on(&stats->event, EVENT_NO_TIMEOUT, TRUE);
+	}
+#endif
+	return osm_exit_flag;
+}
+
+static void do_sweep(osm_sm_t * sm)
+{
+	ib_api_status_t status;
+	osm_remote_sm_t *p_remote_sm;
+
+	if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER &&
+	    sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING)
+		return;
+
+	if (sm->p_subn->coming_out_of_standby)
+		/*
+		 * Need to force re-write of sm_base_lid to all ports
+		 * to do that we want all the ports to be considered
+		 * foreign
+		 */
+		__osm_state_mgr_clean_known_lids(sm);
+
+	sm->master_sm_found = 0;
+
+	/*
+	 * If we already have switches, then try a light sweep.
+	 * Otherwise, this is probably our first discovery pass
+	 * or we are connected in loopback. In both cases do a
+	 * heavy sweep.
+	 * Note: If we are connected in loopback we want a heavy
+	 * sweep, since we will not be getting any traps if there is
+	 * a lost connection.
+	 */
+	/*  if we are in DISCOVERING state - this means it is either in
+	 *  initializing or wake up from STANDBY - run the heavy sweep */
+	if (cl_qmap_count(&sm->p_subn->sw_guid_tbl)
+	    && sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING
+	    && sm->p_subn->opt.force_heavy_sweep == FALSE
+	    && sm->p_subn->force_heavy_sweep == FALSE
+	    && sm->p_subn->force_reroute == FALSE
+	    && sm->p_subn->subnet_initialization_error == FALSE
+	    && (__osm_state_mgr_light_sweep_start(sm) == IB_SUCCESS)) {
+		if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+			return;
+		if (!sm->p_subn->force_heavy_sweep) {
+			OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+					"LIGHT SWEEP COMPLETE");
+			return;
+		}
+	}
+
+	/*
+	 * Unicast cache should be invalidated if there were errors
+	 * during initialization or if subnet re-route is requested.
+	 */
+	if (sm->p_subn->opt.use_ucast_cache &&
+	    (sm->p_subn->subnet_initialization_error ||
+	     sm->p_subn->force_reroute || sm->p_subn->coming_out_of_standby))
+		osm_ucast_cache_invalidate(&sm->ucast_mgr);
+
+	/*
+	 * If we don't need to do a heavy sweep and we want to do a reroute,
+	 * just reroute only.
+	 */
+	if (cl_qmap_count(&sm->p_subn->sw_guid_tbl)
+	    && sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING
+	    && sm->p_subn->opt.force_heavy_sweep == FALSE
+	    && sm->p_subn->force_heavy_sweep == FALSE
+	    && sm->p_subn->force_reroute == TRUE
+	    && sm->p_subn->subnet_initialization_error == FALSE) {
+		/* Reset flag */
+		sm->p_subn->force_reroute = FALSE;
+
+		/* Re-program the switches fully */
+		sm->p_subn->ignore_existing_lfts = TRUE;
+
+		osm_ucast_mgr_process(&sm->ucast_mgr);
+
+		/* Reset flag */
+		sm->p_subn->ignore_existing_lfts = FALSE;
+
+		if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+			return;
+
+		if (!sm->p_subn->subnet_initialization_error) {
+			OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+					"REROUTE COMPLETE");
+			return;
+		}
+	}
+
+	/* go to heavy sweep */
+_repeat_discovery:
+
+	/* First of all - unset all flags */
+	sm->p_subn->force_heavy_sweep = FALSE;
+	sm->p_subn->force_reroute = FALSE;
+	sm->p_subn->subnet_initialization_error = FALSE;
+
+	/* rescan configuration updates */
+	if (osm_subn_rescan_conf_files(sm->p_subn) < 0)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331A: "
+			"osm_subn_rescan_conf_file failed\n");
+
+	if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
+		sm->p_subn->need_update = 1;
+
+	status = __osm_state_mgr_sweep_hop_0(sm);
+	if (status != IB_SUCCESS ||
+	    wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	if (__osm_state_mgr_is_sm_port_down(sm) == TRUE) {
+		osm_log(sm->p_log, OSM_LOG_SYS, "SM port is down\n");
+		OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SM PORT DOWN");
+
+		/* Run the drop manager - we want to clear all records */
+		osm_drop_mgr_process(sm);
+
+		/* Move to DISCOVERING state */
+		osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVER);
+		return;
+	}
+
+	status = __osm_state_mgr_sweep_hop_1(sm);
+	if (status != IB_SUCCESS ||
+	    wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	/* discovery completed - check other sm presense */
+	if (sm->master_sm_found) {
+		/*
+		 * Call the sm_state_mgr with signal
+		 * MASTER_OR_HIGHER_SM_DETECTED_DONE
+		 */
+		osm_sm_state_mgr_process(sm,
+					 OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED);
+		OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+				"ENTERING STANDBY STATE");
+		/* notify master SM about us */
+		osm_send_trap144(sm, 0);
+		return;
+	}
+
+	/* if new sweep requested - don't bother with the rest */
+	if (sm->p_subn->force_heavy_sweep)
+		goto _repeat_discovery;
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "HEAVY SWEEP COMPLETE");
+
+	/* If we are MASTER - get the highest remote_sm, and
+	 * see if it is higher than our local sm.
+	 */
+	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) {
+		p_remote_sm = __osm_state_mgr_get_highest_sm(sm);
+		if (p_remote_sm != NULL) {
+			/* report new ports (trap 64) before leaving MASTER */
+			__osm_state_mgr_report_new_ports(sm);
+
+			/* need to handover the mastership
+			 * to the remote sm, and move to standby */
+			__osm_state_mgr_send_handover(sm, p_remote_sm);
+			osm_sm_state_mgr_process(sm,
+						 OSM_SM_SIGNAL_HANDOVER_SENT);
+			return;
+		} else {
+			/* We are the highest sm - check to see if there is
+			 * a remote SM that is in master state. */
+			p_remote_sm =
+			    __osm_state_mgr_exists_other_master_sm(sm);
+			if (p_remote_sm != NULL) {
+				/* There is a remote SM that is master.
+				 * need to wait for that SM to relinquish control
+				 * of its portion of the subnet. C14-60.2.1.
+				 * Also - need to start polling on that SM. */
+				sm->p_polling_sm = p_remote_sm;
+				osm_sm_state_mgr_process(sm,
+							 OSM_SM_SIGNAL_WAIT_FOR_HANDOVER);
+				return;
+			}
+		}
+	}
+
+	/* Need to continue with lid assignment */
+	osm_drop_mgr_process(sm);
+
+	/*
+	 * If we are not MASTER already - this means that we are
+	 * in discovery state. call osm_sm_state_mgr with signal
+	 * DISCOVERY_COMPLETED
+	 */
+	if (sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING)
+		osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVERY_COMPLETED);
+
+	osm_pkey_mgr_process(sm->p_subn->p_osm);
+
+	osm_qos_setup(sm->p_subn->p_osm);
+
+	/* try to restore SA DB (this should be before lid_mgr
+	   because we may want to disable clients reregistration
+	   when SA DB is restored) */
+	osm_sa_db_file_load(sm->p_subn->p_osm);
+
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	osm_lid_mgr_process_sm(&sm->lid_mgr);
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			"SM LID ASSIGNMENT COMPLETE - STARTING SUBNET LID CONFIG");
+	__osm_state_mgr_notify_lid_change(sm);
+
+	osm_lid_mgr_process_subnet(&sm->lid_mgr);
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	/* At this point we need to check the consistency of
+	 * the port_lid_tbl under the subnet. There might be
+	 * errors in it if PortInfo Set requests didn't reach
+	 * their destination. */
+	__osm_state_mgr_check_tbl_consistency(sm);
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			"LID ASSIGNMENT COMPLETE - STARTING SWITCH TABLE CONFIG");
+
+	/*
+	 * Proceed with unicast forwarding table configuration.
+	 */
+
+	if (!sm->ucast_mgr.cache_valid ||
+	    osm_ucast_cache_process(&sm->ucast_mgr))
+		osm_ucast_mgr_process(&sm->ucast_mgr);
+
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	/* cleanup switch lft buffers */
+	cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl, cleanup_switch, sm->p_log);
+
+	/* We are done setting all LFTs so clear the ignore existing.
+	 * From now on, as long as we are still master, we want to
+	 * take into account these lfts. */
+	sm->p_subn->ignore_existing_lfts = FALSE;
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			"SWITCHES CONFIGURED FOR UNICAST");
+
+	if (!sm->p_subn->opt.disable_multicast) {
+		osm_mcast_mgr_process(sm);
+		if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+			return;
+		OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+				"SWITCHES CONFIGURED FOR MULTICAST");
+	}
+
+	/*
+	 * The LINK_PORTS state is required since we cannot count on
+	 * the port state change MADs to succeed. This is an artifact
+	 * of the spec defining state change from state X to state X
+	 * as an error. The hardware then is not required to process
+	 * other parameters provided by the Set(PortInfo) Packet.
+	 */
+
+	osm_link_mgr_process(sm, IB_LINK_NO_CHANGE);
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			"LINKS PORTS CONFIGURED - SET LINKS TO ARMED STATE");
+
+	osm_link_mgr_process(sm, IB_LINK_ARMED);
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE,
+			"LINKS ARMED - SET LINKS TO ACTIVE STATE");
+
+	osm_link_mgr_process(sm, IB_LINK_ACTIVE);
+	if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats))
+		return;
+
+	/*
+	 * The sweep completed!
+	 */
+
+	/*
+	 * Send trap 64 on newly discovered endports
+	 */
+	__osm_state_mgr_report_new_ports(sm);
+
+	/* in any case we zero this flag */
+	sm->p_subn->coming_out_of_standby = FALSE;
+
+	/* If there were errors - then the subnet is not really up */
+	if (sm->p_subn->subnet_initialization_error == TRUE) {
+		osm_log(sm->p_log, OSM_LOG_SYS,
+			"Errors during initialization\n");
+		OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_ERROR,
+				"ERRORS DURING INITIALIZATION");
+	} else {
+		sm->p_subn->need_update = 0;
+		osm_dump_all(sm->p_subn->p_osm);
+		__osm_state_mgr_up_msg(sm);
+		sm->p_subn->first_time_master_sweep = FALSE;
+
+		if (osm_log_is_active(sm->p_log, OSM_LOG_VERBOSE))
+			osm_sa_db_file_dump(sm->p_subn->p_osm);
+	}
+
+	/*
+	 * Finally signal the subnet up event
+	 */
+	cl_event_signal(&sm->subnet_up_event);
+
+	osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_SUBNET_UP, NULL);
+
+	/* if we got a signal to force heavy sweep or errors
+	 * in the middle of the sweep - try another sweep. */
+	if (sm->p_subn->force_heavy_sweep
+	    || sm->p_subn->subnet_initialization_error)
+		osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+}
+
+static void do_process_mgrp_queue(osm_sm_t * sm)
+{
+	if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
+		return;
+	osm_mcast_mgr_process_mgroups(sm);
+	wait_for_pending_transactions(&sm->p_subn->p_osm->stats);
+}
+
+void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal)
+{
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Received signal %s in state %s\n",
+		osm_get_sm_signal_str(signal),
+		osm_get_sm_mgr_state_str(sm->p_subn->sm_state));
+
+	switch (signal) {
+	case OSM_SIGNAL_SWEEP:
+		do_sweep(sm);
+		break;
+
+	case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST:
+		do_process_mgrp_queue(sm);
+		break;
+
+	default:
+		CL_ASSERT(FALSE);
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3320: "
+			"Invalid SM signal %u\n", signal);
+		break;
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_subnet.c b/opensm/osm_subnet.c
new file mode 100644
index 0000000..c41962d
--- /dev/null
+++ b/opensm/osm_subnet.c
@@ -0,0 +1,1719 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_log.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>
+#include <opensm/osm_console.h>
+#include <opensm/osm_perfmgr.h>
+#include <opensm/osm_event_plugin.h>
+#include <opensm/osm_qos_policy.h>
+
+static const char null_str[] = "(null)";
+
+/**********************************************************************
+ **********************************************************************/
+void osm_subn_construct(IN osm_subn_t * const p_subn)
+{
+	memset(p_subn, 0, sizeof(*p_subn));
+	cl_ptr_vector_construct(&p_subn->port_lid_tbl);
+	cl_qmap_init(&p_subn->sw_guid_tbl);
+	cl_qmap_init(&p_subn->node_guid_tbl);
+	cl_qmap_init(&p_subn->port_guid_tbl);
+	cl_qmap_init(&p_subn->sm_guid_tbl);
+	cl_qlist_init(&p_subn->sa_sr_list);
+	cl_qlist_init(&p_subn->sa_infr_list);
+	cl_qlist_init(&p_subn->prefix_routes_list);
+	cl_qmap_init(&p_subn->rtr_guid_tbl);
+	cl_qmap_init(&p_subn->prtn_pkey_tbl);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_subn_destroy(IN osm_subn_t * const p_subn)
+{
+	int i;
+	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;
+	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);
+	}
+
+	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);
+	}
+
+	for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
+	     i++) {
+		p_mgrp = p_subn->mgroups[i];
+		p_subn->mgroups[i] = NULL;
+		if (p_mgrp)
+			osm_mgrp_delete(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_delete(p_infr);
+	}
+
+	cl_ptr_vector_destroy(&p_subn->port_lid_tbl);
+
+	osm_qos_policy_destroy(p_subn->p_qos_policy);
+
+	while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
+		cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
+		free(item);
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+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->port_lid_tbl,
+				    OSM_SUBNET_VECTOR_MIN_SIZE,
+				    OSM_SUBNET_VECTOR_GROW_SIZE);
+	if (status != CL_SUCCESS)
+		return (status);
+
+	status = cl_ptr_vector_set_capacity(&p_subn->port_lid_tbl,
+					    OSM_SUBNET_VECTOR_CAPACITY);
+	if (status != CL_SUCCESS)
+		return (status);
+
+	/*
+	   LID zero is not valid.  NULL out this entry for the
+	   convenience of other code.
+	 */
+	cl_ptr_vector_set(&p_subn->port_lid_tbl, 0, NULL);
+
+	p_subn->opt = *p_opt;
+	p_subn->max_ucast_lid_ho = IB_LID_UCAST_END_HO;
+	p_subn->max_mcast_lid_ho = IB_LID_MCAST_END_HO;
+	p_subn->min_ca_mtu = IB_MAX_MTU;
+	p_subn->min_ca_rate = IB_MAX_RATE;
+	p_subn->ignore_existing_lfts = TRUE;
+
+	/* we assume master by default - so we only need to set it true if STANDBY */
+	p_subn->coming_out_of_standby = FALSE;
+
+	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;
+
+	if (p_gid == NULL) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "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,
+				"Did not find any port with LID: %u\n",
+				cl_ntoh16(p_mad_addr->dest_lid));
+			return (IB_INVALID_PARAMETER);
+		}
+		p_gid->unicast.interface_id = p_port->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, "ERR 7501: "
+			"LID is out of range: %u\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, "ERR 7502: "
+				"Cannot locate port object by lid: %u\n",
+				cl_ntoh16(p_mad_addr->dest_lid));
+
+			goto Exit;
+		}
+		p_physp = p_port->p_physp;
+	} else {
+		/* The dest_lid is not in the subnet table - this is an error */
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7503: "
+			"Lid is out of range: %u\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, "ERR 7504: "
+			"Lid is out of range: %u\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 ib_net64_t guid)
+{
+	osm_port_t *p_port;
+
+	p_port = (osm_port_t *) cl_qmap_get(&(p_subn->port_guid_tbl), guid);
+	if (p_port == (osm_port_t *) cl_qmap_end(&(p_subn->port_guid_tbl)))
+		p_port = NULL;
+	return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void subn_set_default_qos_options(IN osm_qos_options_t * opt)
+{
+	opt->max_vls = OSM_DEFAULT_QOS_MAX_VLS;
+	opt->high_limit = OSM_DEFAULT_QOS_HIGH_LIMIT;
+	opt->vlarb_high = OSM_DEFAULT_QOS_VLARB_HIGH;
+	opt->vlarb_low = OSM_DEFAULT_QOS_VLARB_LOW;
+	opt->sl2vl = OSM_DEFAULT_QOS_SL2VL;
+}
+
+static void subn_init_qos_options(IN osm_qos_options_t * opt)
+{
+	opt->max_vls = 0;
+	opt->high_limit = -1;
+	opt->vlarb_high = NULL;
+	opt->vlarb_low = NULL;
+	opt->sl2vl = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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->sa_key = OSM_DEFAULT_SA_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 = OSM_DEFAULT_CONSOLE;
+	p_opt->console_port = OSM_DEFAULT_CONSOLE_PORT;
+	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 = 15;
+	p_opt->reassign_lids = FALSE;
+	p_opt->ignore_other_sm = FALSE;
+	p_opt->single_thread = FALSE;
+	p_opt->disable_multicast = FALSE;
+	p_opt->force_log_flush = FALSE;
+	p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
+	p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
+	p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT;
+	p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT;
+	p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
+	p_opt->leaf_head_of_queue_lifetime =
+	    OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
+	p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+	p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+	p_opt->sminfo_polling_timeout =
+	    OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
+	p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER;
+	p_opt->force_heavy_sweep = FALSE;
+	p_opt->log_flags = OSM_LOG_DEFAULT_LEVEL;
+	p_opt->honor_guid2lid_file = FALSE;
+	p_opt->daemon = FALSE;
+	p_opt->sm_inactive = FALSE;
+	p_opt->babbling_port_policy = FALSE;
+#ifdef ENABLE_OSM_PERF_MGR
+	p_opt->perfmgr = FALSE;
+	p_opt->perfmgr_redir = TRUE;
+	p_opt->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
+	p_opt->perfmgr_max_outstanding_queries =
+	    OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
+	p_opt->event_db_dump_file = NULL; /* use default */
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+	p_opt->event_plugin_name = NULL;
+	p_opt->node_name_map_name = NULL;
+
+	p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
+	if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir))
+		p_opt->dump_files_dir = 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->qos = FALSE;
+	p_opt->qos_policy_file = OSM_DEFAULT_QOS_POLICY_FILE;
+	p_opt->accum_log_file = TRUE;
+	p_opt->port_prof_ignore_file = NULL;
+	p_opt->port_profile_switch_nodes = FALSE;
+	p_opt->sweep_on_trap = TRUE;
+	p_opt->use_ucast_cache = FALSE;
+	p_opt->routing_engine_names = NULL;
+	p_opt->connect_roots = FALSE;
+	p_opt->lid_matrix_dump_file = NULL;
+	p_opt->lfts_file = NULL;
+	p_opt->root_guid_file = NULL;
+	p_opt->cn_guid_file = NULL;
+	p_opt->ids_guid_file = NULL;
+	p_opt->guid_routing_order_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;
+	p_opt->prefix_routes_file = OSM_DEFAULT_PREFIX_ROUTES_FILE;
+	p_opt->consolidate_ipv6_snm_req = FALSE;
+	subn_init_qos_options(&p_opt->qos_options);
+	subn_init_qos_options(&p_opt->qos_ca_options);
+	subn_init_qos_options(&p_opt->qos_sw0_options);
+	subn_init_qos_options(&p_opt->qos_swe_options);
+	subn_init_qos_options(&p_opt->qos_rtr_options);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void log_report(const char *fmt, ...)
+{
+	char buf[128];
+	va_list args;
+	va_start(args, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	printf(buf);
+	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
+}
+
+static void log_config_value(char *name, const char *fmt, ...)
+{
+	char buf[128];
+	va_list args;
+	unsigned n;
+	va_start(args, fmt);
+	n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name);
+	if (n > sizeof(buf))
+		n = sizeof(buf);
+	n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args);
+	if (n > sizeof(buf))
+		n = sizeof(buf);
+	snprintf(buf + n, sizeof(buf) - n, "\n");
+	va_end(args);
+	printf(buf);
+	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
+}
+
+static void
+opts_unpack_net64(IN char *p_req_key,
+		  IN char *p_key, IN char *p_val_str, IN uint64_t * p_val)
+{
+	if (!strcmp(p_req_key, p_key)) {
+		uint64_t val = strtoull(p_val_str, NULL, 0);
+		if (cl_hton64(val) != *p_val) {
+			log_config_value(p_key, "0x%016" PRIx64, val);
+			*p_val = cl_ntoh64(val);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+opts_unpack_uint32(IN char *p_req_key,
+		   IN char *p_key, IN char *p_val_str, IN uint32_t * p_val)
+{
+	if (!strcmp(p_req_key, p_key)) {
+		uint32_t val = strtoul(p_val_str, NULL, 0);
+		if (val != *p_val) {
+			log_config_value(p_key, "%u", val);
+			*p_val = val;
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+opts_unpack_int32(IN char *p_req_key,
+		  IN char *p_key, IN char *p_val_str, IN int32_t * p_val)
+{
+	if (!strcmp(p_req_key, p_key)) {
+		int32_t val = strtol(p_val_str, NULL, 0);
+		if (val != *p_val) {
+			log_config_value(p_key, "%d", val);
+			*p_val = val;
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+opts_unpack_uint16(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)) {
+		uint16_t val = (uint16_t) strtoul(p_val_str, NULL, 0);
+		if (val != *p_val) {
+			log_config_value(p_key, "%u", val);
+			*p_val = val;
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+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) {
+			log_config_value(p_key, "0x%04x", val);
+			*p_val = cl_hton16((uint16_t) val);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+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) {
+			log_config_value(p_key, "%u", val);
+			*p_val = (uint8_t) val;
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+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) {
+			log_config_value(p_key, "%s", p_val_str);
+			*p_val = val;
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+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) {
+		const char *current_str = *p_val ? *p_val : null_str ;
+		if (strcmp(p_val_str, current_str)) {
+			log_config_value(p_key, "%s", p_val_str);
+			/* special case the "(null)" string */
+			if (strcmp(null_str, p_val_str) == 0) {
+				*p_val = NULL;
+			} else {
+				/*
+				  Ignore the possible memory leak here;
+				  the pointer may be to a static default.
+				*/
+				*p_val = strdup(p_val_str);
+			}
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static char *clean_val(char *val)
+{
+	char *p = val;
+	/* clean leading spaces */
+	while (isspace(*p))
+		p++;
+	val = p;
+	if (!*val)
+		return val;
+	/* clean trailing spaces */
+	p = val + strlen(val) - 1;
+	while (p > val && isspace(*p))
+		p--;
+	p[1] = '\0';
+	/* clean quotas */
+	if ((*val == '\"' && *p == '\"') || (*val == '\'' && *p == '\'')) {
+		val++;
+		p--;
+	}
+	return val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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);
+	opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls);
+	snprintf(name, sizeof(name), "%s_high_limit", prefix);
+	opts_unpack_int32(name, p_key, p_val_str, &opt->high_limit);
+	snprintf(name, sizeof(name), "%s_vlarb_high", prefix);
+	opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high);
+	snprintf(name, sizeof(name), "%s_vlarb_low", prefix);
+	opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low);
+	snprintf(name, sizeof(name), "%s_sl2vl", prefix);
+	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 %d\n"
+		       "%s_vlarb_high %s\n"
+		       "%s_vlarb_low %s\n"
+		       "%s_sl2vl %s\n",
+		       set_name,
+		       prefix, opt->max_vls,
+		       prefix, opt->high_limit,
+		       prefix, opt->vlarb_high,
+		       prefix, opt->vlarb_low, prefix, opt->sl2vl);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+append_prefix_route(IN osm_subn_t * const p_subn, uint64_t prefix, uint64_t guid)
+{
+	osm_prefix_route_t *route;
+
+	route = malloc(sizeof *route);
+	if (! route) {
+		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "out of memory");
+		return IB_ERROR;
+	}
+
+	route->prefix = cl_hton64(prefix);
+	route->guid = cl_hton64(guid);
+	cl_qlist_insert_tail(&p_subn->prefix_routes_list, &route->list_item);
+	return IB_SUCCESS;
+}
+
+static ib_api_status_t
+osm_parse_prefix_routes_file(IN osm_subn_t * const p_subn)
+{
+	osm_log_t *log = &p_subn->p_osm->log;
+	FILE *fp;
+	char buf[1024];
+	int line = 0;
+	int errors = 0;
+
+	while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
+		cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
+		free(item);
+	}
+
+	fp = fopen(p_subn->opt.prefix_routes_file, "r");
+	if (! fp) {
+		if (errno == ENOENT)
+			return IB_SUCCESS;
+
+		OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s",
+			p_subn->opt.prefix_routes_file, strerror(errno));
+		return IB_ERROR;
+	}
+
+	while (fgets(buf, sizeof buf, fp) != NULL) {
+		char *p_prefix, *p_guid, *p_extra, *p_last, *p_end;
+		uint64_t prefix, guid;
+
+		line++;
+		if (errors > 10)
+			break;
+
+		p_prefix = strtok_r(buf, " \t\n", &p_last);
+		if (! p_prefix)
+			continue; /* ignore blank lines */
+
+		if (*p_prefix == '#')
+			continue; /* ignore comment lines */
+
+		p_guid = strtok_r(NULL, " \t\n", &p_last);
+		if (! p_guid) {
+			OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing GUID\n",
+				p_subn->opt.prefix_routes_file, line);
+			errors++;
+			continue;
+		}
+
+		p_extra = strtok_r(NULL, " \t\n", &p_last);
+		if (p_extra && *p_extra != '#') {
+			OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n",
+				p_subn->opt.prefix_routes_file, line);
+		}
+
+		if (strcmp(p_prefix, "*") == 0)
+			prefix = 0;
+		else {
+			prefix = strtoull(p_prefix, &p_end, 16);
+			if (*p_end != '\0') {
+				OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal prefix: %s\n",
+					p_subn->opt.prefix_routes_file, line, p_prefix);
+				errors++;
+				continue;
+			}
+		}
+
+		if (strcmp(p_guid, "*") == 0)
+			guid = 0;
+		else {
+			guid = strtoull(p_guid, &p_end, 16);
+			if (*p_end != '\0' && *p_end != '#') {
+				OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal GUID: %s\n",
+					p_subn->opt.prefix_routes_file, line, p_guid);
+				errors++;
+				continue;
+			}
+		}
+
+		if (append_prefix_route(p_subn, prefix, guid) != IB_SUCCESS) {
+			errors++;
+			break;
+		}
+	}
+
+	fclose(fp);
+	return (errors == 0) ? IB_SUCCESS : IB_ERROR;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void subn_verify_max_vls(unsigned *max_vls, const char *prefix, unsigned dflt)
+{
+	if (!(*max_vls) || *max_vls > 15) {
+		log_report(" Invalid Cached Option: %s_max_vls=%u: "
+			   "Using Default = %u\n", prefix, *max_vls, dflt);
+		*max_vls = dflt;
+	}
+}
+
+static void subn_verify_high_limit(int *high_limit, const char *prefix, int dflt)
+{
+	if (*high_limit < 0 || *high_limit > 255) {
+		log_report(" Invalid Cached Option: %s_high_limit=%d: "
+			   "Using Default: %d\n", prefix, *high_limit, dflt);
+		*high_limit = dflt;
+	}
+}
+
+static void subn_verify_vlarb(char **vlarb, const char *prefix,
+			      const char *suffix, char *dflt)
+{
+	char *str, *tok, *end, *ptr;
+	int count = 0;
+
+	if (*vlarb == NULL) {
+		log_report(" Invalid Cached Option: %s_vlarb_%s: "
+		"Using Default\n", prefix, suffix);
+		*vlarb = dflt;
+		return;
+	}
+
+	str = strdup(*vlarb);
+
+	tok = strtok_r(str, ",\n", &ptr);
+	while (tok) {
+		char *vl_str, *weight_str;
+
+		vl_str = tok;
+		weight_str = strchr(tok, ':');
+
+		if (weight_str) {
+			long vl, weight;
+
+			*weight_str = '\0';
+			weight_str++;
+
+			vl = strtol(vl_str, &end, 0);
+
+			if (*end)
+				log_report(" Warning: Cached Option "
+					   "%s_vlarb_%s:vl=%s"
+					   " improperly formatted\n",
+					   prefix, suffix, vl_str);
+			else if (vl < 0 || vl > 14)
+				log_report(" Warning: Cached Option "
+					   "%s_vlarb_%s:vl=%ld out of range\n",
+					   prefix, suffix, vl);
+
+			weight = strtol(weight_str, &end, 0);
+
+			if (*end)
+				log_report(" Warning: Cached Option "
+					   "%s_vlarb_%s:weight=%s "
+					   "improperly formatted\n",
+					   prefix, suffix, weight_str);
+			else if (weight < 0 || weight > 255)
+				log_report(" Warning: Cached Option "
+					   "%s_vlarb_%s:weight=%ld "
+					   "out of range\n",
+					   prefix, suffix, weight);
+		} else
+			log_report(" Warning: Cached Option "
+				   "%s_vlarb_%s:vl:weight=%s "
+				   "improperly formatted\n",
+				   prefix, suffix, tok);
+
+		count++;
+		tok = strtok_r(NULL, ",\n", &ptr);
+	}
+
+	if (count > 64)
+		log_report(" Warning: Cached Option %s_vlarb_%s: > 64 listed:"
+			   " excess vl:weight pairs will be dropped\n",
+			   prefix, suffix);
+
+	free(str);
+}
+
+static void subn_verify_sl2vl(char **sl2vl, const char *prefix, char *dflt)
+{
+	char *str, *tok, *end, *ptr;
+	int count = 0;
+
+	if (*sl2vl == NULL) {
+		log_report(" Invalid Cached Option: %s_sl2vl: Using Default\n",
+			   prefix);
+		*sl2vl = dflt;
+		return;
+	}
+
+	str = strdup(*sl2vl);
+
+	tok = strtok_r(str, ",\n", &ptr);
+	while (tok) {
+		long vl = strtol(tok, &end, 0);
+
+		if (*end)
+			log_report(" Warning: Cached Option %s_sl2vl:vl=%s "
+				   "improperly formatted\n", prefix, tok);
+		else if (vl < 0 || vl > 15)
+			log_report(" Warning: Cached Option %s_sl2vl:vl=%ld "
+				   "out of range\n", prefix, vl);
+
+		count++;
+		tok = strtok_r(NULL, ",\n", &ptr);
+	}
+
+	if (count < 16)
+		log_report(" Warning: Cached Option %s_sl2vl: < 16 VLs "
+			   "listed\n", prefix);
+
+	if (count > 16)
+		log_report(" Warning: Cached Option %s_sl2vl: > 16 listed: "
+			   "excess VLs will be dropped\n", prefix);
+
+	free(str);
+}
+
+static void subn_verify_qos_set(osm_qos_options_t *set, const char *prefix,
+				osm_qos_options_t *dflt)
+{
+	subn_verify_max_vls(&set->max_vls, prefix, dflt->max_vls);
+	subn_verify_high_limit(&set->high_limit, prefix, dflt->high_limit);
+	subn_verify_vlarb(&set->vlarb_low, prefix, "low", dflt->vlarb_low);
+	subn_verify_vlarb(&set->vlarb_high, prefix, "high", dflt->vlarb_high);
+	subn_verify_sl2vl(&set->sl2vl, prefix, dflt->sl2vl);
+}
+
+int osm_subn_verify_config(IN osm_subn_opt_t * const p_opts)
+{
+	if (p_opts->lmc > 7) {
+		log_report(" Invalid Cached Option Value:lmc = %u:"
+			   "Using Default:%u\n", p_opts->lmc, OSM_DEFAULT_LMC);
+		p_opts->lmc = OSM_DEFAULT_LMC;
+	}
+
+	if (15 < p_opts->sm_priority) {
+		log_report(" Invalid Cached Option Value:sm_priority = %u:"
+			   "Using Default:%u\n",
+			   p_opts->sm_priority, OSM_DEFAULT_SM_PRIORITY);
+		p_opts->sm_priority = OSM_DEFAULT_SM_PRIORITY;
+	}
+
+	if ((15 < p_opts->force_link_speed) ||
+	    (p_opts->force_link_speed > 7 && p_opts->force_link_speed < 15)) {
+		log_report(" Invalid Cached Option Value:force_link_speed = %u:"
+			   "Using Default:%u\n", p_opts->force_link_speed,
+			   IB_PORT_LINK_SPEED_ENABLED_MASK);
+		p_opts->force_link_speed = IB_PORT_LINK_SPEED_ENABLED_MASK;
+	}
+
+	if (strcmp(p_opts->console, OSM_DISABLE_CONSOLE)
+	    && strcmp(p_opts->console, OSM_LOCAL_CONSOLE)
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+	    && strcmp(p_opts->console, OSM_LOOPBACK_CONSOLE)
+	    && strcmp(p_opts->console, OSM_REMOTE_CONSOLE)
+#endif
+	    ) {
+		log_report(" Invalid Cached Option Value:console = %s"
+			   ", Using Default:%s\n",
+			   p_opts->console, OSM_DEFAULT_CONSOLE);
+		p_opts->console = OSM_DEFAULT_CONSOLE;
+	}
+
+	if (p_opts->qos) {
+		osm_qos_options_t dflt;
+
+		/* the default options in qos_options must be correct.
+		 * every other one need not be, b/c those will default
+		 * back to whatever is in qos_options.
+		 */
+
+		subn_set_default_qos_options(&dflt);
+
+		subn_verify_qos_set(&p_opts->qos_options, "qos", &dflt);
+		subn_verify_qos_set(&p_opts->qos_ca_options, "qos_ca",
+				    &p_opts->qos_options);
+		subn_verify_qos_set(&p_opts->qos_sw0_options, "qos_sw0",
+				    &p_opts->qos_options);
+		subn_verify_qos_set(&p_opts->qos_swe_options, "qos_swe",
+				    &p_opts->qos_options);
+		subn_verify_qos_set(&p_opts->qos_rtr_options, "qos_rtr",
+				    &p_opts->qos_options);
+	}
+
+#ifdef ENABLE_OSM_PERF_MGR
+	if (p_opts->perfmgr_sweep_time_s < 1) {
+		log_report(" Invalid Cached Option Value:perfmgr_sweep_time_s "
+			   "= %u Using Default:%u\n",
+			   p_opts->perfmgr_sweep_time_s,
+			   OSM_PERFMGR_DEFAULT_SWEEP_TIME_S);
+		p_opts->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
+	}
+	if (p_opts->perfmgr_max_outstanding_queries < 1) {
+		log_report(" Invalid Cached Option Value:"
+			   "perfmgr_max_outstanding_queries = %u"
+			   " Using Default:%u\n",
+			   p_opts->perfmgr_max_outstanding_queries,
+			   OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES);
+		p_opts->perfmgr_max_outstanding_queries =
+		    OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
+	}
+#endif
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_subn_parse_conf_file(char *file_name, osm_subn_opt_t * const p_opts)
+{
+	char line[1024];
+	FILE *opts_file;
+	char *p_key, *p_val;
+
+	opts_file = fopen(file_name, "r");
+	if (!opts_file) {
+		if (errno == ENOENT)
+			return 1;
+		printf("cannot open file \'%s\': %s\n",
+		       file_name, strerror(errno));
+		return -1;
+	}
+
+	printf(" Reading Cached Option File: %s\n", file_name);
+	cl_log_event("OpenSM", CL_LOG_INFO, line, NULL, 0);
+
+	p_opts->config_file = file_name;
+
+	while (fgets(line, 1023, opts_file) != NULL) {
+		/* get the first token */
+		p_key = strtok_r(line, " \t\n", &p_val);
+		if (!p_key)
+			continue;
+
+		p_val = clean_val(p_val);
+
+		opts_unpack_net64("guid", p_key, p_val, &p_opts->guid);
+
+		opts_unpack_net64("m_key", p_key, p_val, &p_opts->m_key);
+
+		opts_unpack_net64("sm_key", p_key, p_val, &p_opts->sm_key);
+
+		opts_unpack_net64("sa_key", p_key, p_val, &p_opts->sa_key);
+
+		opts_unpack_net64("subnet_prefix",
+				  p_key, p_val, &p_opts->subnet_prefix);
+
+		opts_unpack_net16("m_key_lease_period",
+				  p_key, p_val, &p_opts->m_key_lease_period);
+
+		opts_unpack_uint32("sweep_interval",
+				   p_key, p_val, &p_opts->sweep_interval);
+
+		opts_unpack_uint32("max_wire_smps",
+				   p_key, p_val, &p_opts->max_wire_smps);
+
+		opts_unpack_charp("console", p_key, p_val, &p_opts->console);
+
+		opts_unpack_uint16("console_port",
+				   p_key, p_val, &p_opts->console_port);
+
+		opts_unpack_uint32("transaction_timeout",
+				   p_key, p_val, &p_opts->transaction_timeout);
+
+		opts_unpack_uint32("max_msg_fifo_timeout",
+				   p_key, p_val, &p_opts->max_msg_fifo_timeout);
+
+		opts_unpack_uint8("sm_priority",
+				  p_key, p_val, &p_opts->sm_priority);
+
+		opts_unpack_uint8("lmc", p_key, p_val, &p_opts->lmc);
+
+		opts_unpack_boolean("lmc_esp0",
+				    p_key, p_val, &p_opts->lmc_esp0);
+
+		opts_unpack_uint8("max_op_vls",
+				  p_key, p_val, &p_opts->max_op_vls);
+
+		opts_unpack_uint8("force_link_speed",
+				  p_key, p_val, &p_opts->force_link_speed);
+
+		opts_unpack_boolean("reassign_lids",
+				    p_key, p_val, &p_opts->reassign_lids);
+
+		opts_unpack_boolean("ignore_other_sm",
+				    p_key, p_val, &p_opts->ignore_other_sm);
+
+		opts_unpack_boolean("single_thread",
+				    p_key, p_val, &p_opts->single_thread);
+
+		opts_unpack_boolean("disable_multicast",
+				    p_key, p_val, &p_opts->disable_multicast);
+
+		opts_unpack_boolean("force_log_flush",
+				    p_key, p_val, &p_opts->force_log_flush);
+
+		opts_unpack_uint8("subnet_timeout",
+				  p_key, p_val, &p_opts->subnet_timeout);
+
+		opts_unpack_uint8("packet_life_time",
+				  p_key, p_val, &p_opts->packet_life_time);
+
+		opts_unpack_uint8("vl_stall_count",
+				  p_key, p_val, &p_opts->vl_stall_count);
+
+		opts_unpack_uint8("leaf_vl_stall_count",
+				  p_key, p_val, &p_opts->leaf_vl_stall_count);
+
+		opts_unpack_uint8("head_of_queue_lifetime",
+				  p_key, p_val,
+				  &p_opts->head_of_queue_lifetime);
+
+		opts_unpack_uint8("leaf_head_of_queue_lifetime", p_key, p_val,
+				  &p_opts->leaf_head_of_queue_lifetime);
+
+		opts_unpack_uint8("local_phy_errors_threshold", p_key, p_val,
+				  &p_opts->local_phy_errors_threshold);
+
+		opts_unpack_uint8("overrun_errors_threshold",
+				  p_key, p_val,
+				  &p_opts->overrun_errors_threshold);
+
+		opts_unpack_uint32("sminfo_polling_timeout",
+				   p_key, p_val,
+				   &p_opts->sminfo_polling_timeout);
+
+		opts_unpack_uint32("polling_retry_number",
+				   p_key, p_val, &p_opts->polling_retry_number);
+
+		opts_unpack_boolean("force_heavy_sweep",
+				    p_key, p_val, &p_opts->force_heavy_sweep);
+
+		opts_unpack_uint8("log_flags",
+				  p_key, p_val, &p_opts->log_flags);
+
+		opts_unpack_charp("port_prof_ignore_file", p_key, p_val,
+				  &p_opts->port_prof_ignore_file);
+
+		opts_unpack_boolean("port_profile_switch_nodes", p_key, p_val,
+				    &p_opts->port_profile_switch_nodes);
+
+		opts_unpack_boolean("sweep_on_trap",
+				    p_key, p_val, &p_opts->sweep_on_trap);
+
+		opts_unpack_charp("routing_engine",
+				  p_key, p_val, &p_opts->routing_engine_names);
+
+		opts_unpack_boolean("connect_roots",
+				    p_key, p_val, &p_opts->connect_roots);
+
+		opts_unpack_boolean("use_ucast_cache",
+				    p_key, p_val, &p_opts->use_ucast_cache);
+
+		opts_unpack_charp("log_file", p_key, p_val, &p_opts->log_file);
+
+		opts_unpack_uint32("log_max_size",
+				   p_key, p_val,
+				   (void *) & p_opts->log_max_size);
+		p_opts->log_max_size *= 1024 * 1024; /* convert to MB */
+
+		opts_unpack_charp("partition_config_file",
+				  p_key, p_val, &p_opts->partition_config_file);
+
+		opts_unpack_boolean("no_partition_enforcement", p_key, p_val,
+				    &p_opts->no_partition_enforcement);
+
+		opts_unpack_boolean("qos", p_key, p_val, &p_opts->qos);
+
+		opts_unpack_charp("qos_policy_file",
+				  p_key, p_val, &p_opts->qos_policy_file);
+
+		opts_unpack_boolean("accum_log_file",
+				    p_key, p_val, &p_opts->accum_log_file);
+
+		opts_unpack_charp("dump_files_dir",
+				  p_key, p_val, &p_opts->dump_files_dir);
+
+		opts_unpack_charp("lid_matrix_dump_file",
+				  p_key, p_val, &p_opts->lid_matrix_dump_file);
+
+		opts_unpack_charp("lfts_file",
+				  p_key, p_val, &p_opts->lfts_file);
+
+		opts_unpack_charp("root_guid_file",
+				  p_key, p_val, &p_opts->root_guid_file);
+
+		opts_unpack_charp("cn_guid_file",
+				  p_key, p_val, &p_opts->cn_guid_file);
+
+		opts_unpack_charp("ids_guid_file",
+				  p_key, p_val, &p_opts->ids_guid_file);
+
+		opts_unpack_charp("guid_routing_order_file",
+				  p_key, p_val, &p_opts->guid_routing_order_file);
+
+		opts_unpack_charp("sa_db_file",
+				  p_key, p_val, &p_opts->sa_db_file);
+
+		opts_unpack_boolean("exit_on_fatal",
+				    p_key, p_val, &p_opts->exit_on_fatal);
+
+		opts_unpack_boolean("honor_guid2lid_file",
+				    p_key, p_val, &p_opts->honor_guid2lid_file);
+
+		opts_unpack_boolean("daemon", p_key, p_val, &p_opts->daemon);
+
+		opts_unpack_boolean("sm_inactive",
+				    p_key, p_val, &p_opts->sm_inactive);
+
+		opts_unpack_boolean("babbling_port_policy",
+				    p_key, p_val,
+				    &p_opts->babbling_port_policy);
+
+#ifdef ENABLE_OSM_PERF_MGR
+		opts_unpack_boolean("perfmgr", p_key, p_val, &p_opts->perfmgr);
+
+		opts_unpack_boolean("perfmgr_redir",
+				    p_key, p_val, &p_opts->perfmgr_redir);
+
+		opts_unpack_uint16("perfmgr_sweep_time_s",
+				   p_key, p_val, &p_opts->perfmgr_sweep_time_s);
+
+		opts_unpack_uint32("perfmgr_max_outstanding_queries",
+				   p_key, p_val,
+				   &p_opts->perfmgr_max_outstanding_queries);
+
+		opts_unpack_charp("event_db_dump_file",
+				  p_key, p_val, &p_opts->event_db_dump_file);
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+		opts_unpack_charp("event_plugin_name",
+				  p_key, p_val, &p_opts->event_plugin_name);
+
+		opts_unpack_charp("node_name_map_name",
+				  p_key, p_val, &p_opts->node_name_map_name);
+
+		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);
+
+		opts_unpack_boolean("enable_quirks",
+				    p_key, p_val, &p_opts->enable_quirks);
+
+		opts_unpack_boolean("no_clients_rereg",
+				    p_key, p_val, &p_opts->no_clients_rereg);
+
+		opts_unpack_charp("prefix_routes_file",
+				  p_key, p_val, &p_opts->prefix_routes_file);
+
+		opts_unpack_boolean("consolidate_ipv6_snm_req",
+				p_key, p_val, &p_opts->consolidate_ipv6_snm_req);
+	}
+	fclose(opts_file);
+
+	osm_subn_verify_config(p_opts);
+
+	return 0;
+}
+
+int osm_subn_rescan_conf_files(IN osm_subn_t * const p_subn)
+{
+	FILE *opts_file;
+	char line[1024];
+	char *p_key, *p_val, *p_last;
+
+	if (!p_subn->opt.config_file)
+		return 0;
+
+	opts_file = fopen(p_subn->opt.config_file, "r");
+	if (!opts_file) {
+		if (errno == ENOENT)
+			return 1;
+		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
+			"cannot open file \'%s\': %s\n",
+			p_subn->opt.config_file, strerror(errno));
+		return -1;
+	}
+
+	subn_init_qos_options(&p_subn->opt.qos_options);
+	subn_init_qos_options(&p_subn->opt.qos_ca_options);
+	subn_init_qos_options(&p_subn->opt.qos_sw0_options);
+	subn_init_qos_options(&p_subn->opt.qos_swe_options);
+	subn_init_qos_options(&p_subn->opt.qos_rtr_options);
+
+	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_subn->opt.qos_options);
+
+			subn_parse_qos_options("qos_ca", p_key, p_val,
+					       &p_subn->opt.qos_ca_options);
+
+			subn_parse_qos_options("qos_sw0", p_key, p_val,
+					       &p_subn->opt.qos_sw0_options);
+
+			subn_parse_qos_options("qos_swe", p_key, p_val,
+					       &p_subn->opt.qos_swe_options);
+
+			subn_parse_qos_options("qos_rtr", p_key, p_val,
+					       &p_subn->opt.qos_rtr_options);
+
+		}
+	}
+	fclose(opts_file);
+
+	osm_subn_verify_config(&p_subn->opt);
+
+	osm_parse_prefix_routes_file(p_subn);
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_subn_output_conf(FILE *out, IN osm_subn_opt_t *const p_opts)
+{
+	fprintf(out,
+		"#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
+		"# The port GUID on which the OpenSM is running\n"
+		"guid 0x%016" PRIx64 "\n\n"
+		"# M_Key value sent to all ports qualifying all Set(PortInfo)\n"
+		"m_key 0x%016" PRIx64 "\n\n"
+		"# The lease period used for the M_Key on this subnet in [sec]\n"
+		"m_key_lease_period %u\n\n"
+		"# SM_Key value of the SM used for SM authentication\n"
+		"sm_key 0x%016" PRIx64 "\n\n"
+		"# SM_Key value to qualify rcv SA queries as 'trusted'\n"
+		"sa_key 0x%016" PRIx64 "\n\n"
+		"# Note that for both values above (sm_key and sa_key)\n"
+		"# OpenSM version 3.2.1 and below used the default value '1'\n"
+		"# in a host byte order, it is fixed now but you may need to\n"
+		"# change the values to interoperate with old OpenSM running\n"
+		"# on a little endian machine.\n\n"
+		"# Subnet prefix used on this subnet\n"
+		"subnet_prefix 0x%016" PRIx64 "\n\n"
+		"# The LMC value used on this subnet\n"
+		"lmc %u\n\n"
+		"# lmc_esp0 determines whether LMC value used on subnet is used for\n"
+		"# enhanced switch port 0. If TRUE, LMC value for subnet is used for\n"
+		"# ESP0. Otherwise, LMC value for ESP0s is 0.\n"
+		"lmc_esp0 %s\n\n"
+		"# 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 PortInfo:LinkSpeedEnabled on switch ports\n"
+		"# If 0, don't modify PortInfo:LinkSpeedEnabled on switch port\n"
+		"# Otherwise, use value for PortInfo:LinkSpeedEnabled on switch port\n"
+		"# Values are (IB Spec 1.2.1, 14.2.5.6 Table 146 \"PortInfo\")\n"
+		"#    1: 2.5 Gbps\n"
+		"#    3: 2.5 or 5.0 Gbps\n"
+		"#    5: 2.5 or 10.0 Gbps\n"
+		"#    7: 2.5 or 5.0 or 10.0 Gbps\n"
+		"#    2,4,6,8-14 Reserved\n"
+		"#    Default 15: set to PortInfo:LinkSpeedSupported\n"
+		"force_link_speed %u\n\n"
+		"# 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 credit overrun errors for sending Trap 130\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->sa_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(out,
+		"#\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(out,
+		"#\n# SWEEP OPTIONS\n#\n"
+		"# The number of seconds between subnet sweeps (0 disables it)\n"
+		"sweep_interval %u\n\n"
+		"# If TRUE cause all lids to be reassigned\n"
+		"reassign_lids %s\n\n"
+		"# If TRUE forces every sweep to be a heavy sweep\n"
+		"force_heavy_sweep %s\n\n"
+		"# If TRUE every trap will cause a heavy sweep.\n"
+		"# NOTE: successive identical traps (>10) are suppressed\n"
+		"sweep_on_trap %s\n\n",
+		p_opts->sweep_interval,
+		p_opts->reassign_lids ? "TRUE" : "FALSE",
+		p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
+		p_opts->sweep_on_trap ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"#\n# ROUTING OPTIONS\n#\n"
+		"# If TRUE count switches as link subscriptions\n"
+		"port_profile_switch_nodes %s\n\n",
+		p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"# Name of file with port guids to be ignored by port profiling\n"
+		"port_prof_ignore_file %s\n\n", p_opts->port_prof_ignore_file ?
+		p_opts->port_prof_ignore_file : null_str);
+
+	fprintf(out,
+		"# Routing engine\n"
+		"# Multiple routing engines can be specified separated by\n"
+		"# commas so that specific ordering of routing algorithms will\n"
+		"# be tried if earlier routing engines fail.\n"
+		"# Supported engines: minhop, updn, file, ftree, lash, dor\n"
+		"routing_engine %s\n\n", p_opts->routing_engine_names ?
+		p_opts->routing_engine_names : null_str);
+
+	fprintf(out,
+		"# Connect roots (use FALSE if unsure)\n"
+		"connect_roots %s\n\n",
+		p_opts->connect_roots ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"# Use unicast routing cache (use FALSE if unsure)\n"
+		"use_ucast_cache %s\n\n",
+		p_opts->use_ucast_cache ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"# Lid matrix dump file name\n"
+		"lid_matrix_dump_file %s\n\n", p_opts->lid_matrix_dump_file ?
+		p_opts->lid_matrix_dump_file : null_str);
+
+	fprintf(out,
+		"# LFTs file name\nlfts_file %s\n\n",
+		p_opts->lfts_file ? p_opts->lfts_file : null_str);
+
+	fprintf(out,
+		"# The file holding the root node guids (for fat-tree or Up/Down)\n"
+		"# One guid in each line\nroot_guid_file %s\n\n",
+		p_opts->root_guid_file ? p_opts->root_guid_file : null_str);
+
+	fprintf(out,
+		"# The file holding the fat-tree compute node guids\n"
+		"# One guid in each line\ncn_guid_file %s\n\n",
+		p_opts->cn_guid_file ? p_opts->cn_guid_file : null_str);
+
+	fprintf(out,
+		"# The file holding the node ids which will be used by"
+		" Up/Down algorithm instead\n# of GUIDs (one guid and"
+		" id in each line)\nids_guid_file %s\n\n",
+		p_opts->ids_guid_file ? p_opts->ids_guid_file : null_str);
+
+	fprintf(out,
+		"# The file holding guid routing order guids (for MinHop and Up/Down)\n"
+		"guid_routing_order_file %s\n\n",
+		p_opts->guid_routing_order_file ? p_opts->guid_routing_order_file : null_str);
+
+	fprintf(out,
+		"# SA database file name\nsa_db_file %s\n\n",
+		p_opts->sa_db_file ? p_opts->sa_db_file : null_str);
+
+	fprintf(out,
+		"#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
+		"# SM priority used for deciding who is the master\n"
+		"# Range goes from 0 (lowest priority) to 15 (highest).\n"
+		"sm_priority %u\n\n"
+		"# If TRUE other SMs on the subnet should be ignored\n"
+		"ignore_other_sm %s\n\n"
+		"# Timeout in [msec] between two polls of active master SM\n"
+		"sminfo_polling_timeout %u\n\n"
+		"# Number of failing polls of remote SM that declares it dead\n"
+		"polling_retry_number %u\n\n"
+		"# If TRUE honor the guid2lid file when coming out of standby\n"
+		"# state, if such file exists and is valid\n"
+		"honor_guid2lid_file %s\n\n",
+		p_opts->sm_priority,
+		p_opts->ignore_other_sm ? "TRUE" : "FALSE",
+		p_opts->sminfo_polling_timeout,
+		p_opts->polling_retry_number,
+		p_opts->honor_guid2lid_file ? "TRUE" : "FALSE");
+
+	fprintf(out,
+		"#\n# TIMING AND THREADING OPTIONS\n#\n"
+		"# Maximum number of SMPs sent in parallel\n"
+		"max_wire_smps %u\n\n"
+		"# The maximum time in [msec] allowed for a transaction to complete\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(out,
+		"#\n# MISC OPTIONS\n#\n"
+		"# Daemon mode\n"
+		"daemon %s\n\n"
+		"# SM Inactive\n"
+		"sm_inactive %s\n\n"
+		"# Babbling Port Policy\n"
+		"babbling_port_policy %s\n\n",
+		p_opts->daemon ? "TRUE" : "FALSE",
+		p_opts->sm_inactive ? "TRUE" : "FALSE",
+		p_opts->babbling_port_policy ? "TRUE" : "FALSE");
+
+#ifdef ENABLE_OSM_PERF_MGR
+	fprintf(out,
+		"#\n# Performance Manager Options\n#\n"
+		"# perfmgr enable\n"
+		"perfmgr %s\n\n"
+		"# perfmgr redirection enable\n"
+		"perfmgr_redir %s\n\n"
+		"# sweep time in seconds\n"
+		"perfmgr_sweep_time_s %u\n\n"
+		"# Max outstanding queries\n"
+		"perfmgr_max_outstanding_queries %u\n\n",
+		p_opts->perfmgr ? "TRUE" : "FALSE",
+		p_opts->perfmgr_redir ? "TRUE" : "FALSE",
+		p_opts->perfmgr_sweep_time_s,
+		p_opts->perfmgr_max_outstanding_queries);
+
+	fprintf(out,
+		"#\n# Event DB Options\n#\n"
+		"# Dump file to dump the events to\n"
+		"event_db_dump_file %s\n\n", p_opts->event_db_dump_file ?
+		p_opts->event_db_dump_file : null_str);
+#endif				/* ENABLE_OSM_PERF_MGR */
+
+	fprintf(out,
+		"#\n# Event Plugin Options\n#\n"
+		"event_plugin_name %s\n\n", p_opts->event_plugin_name ?
+		p_opts->event_plugin_name : null_str);
+
+	fprintf(out,
+		"#\n# Node name map for mapping node's to more descriptive node descriptions\n"
+		"# (man ibnetdiscover for more information)\n#\n"
+		"node_name_map_name %s\n\n", p_opts->node_name_map_name ?
+		p_opts->node_name_map_name : null_str);
+
+	fprintf(out,
+		"#\n# DEBUG FEATURES\n#\n"
+		"# The log flags used\n"
+		"log_flags 0x%02x\n\n"
+		"# Force flush of the log file after each log message\n"
+		"force_log_flush %s\n\n"
+		"# Log file to be used\n"
+		"log_file %s\n\n"
+		"# Limit the size of the log file in MB. If overrun, log is restarted\n"
+		"log_max_size %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 disables client reregistration\n"
+		"no_clients_rereg %s\n\n"
+		"# If TRUE OpenSM should disable multicast support and\n"
+		"# no multicast routing is performed if TRUE\n"
+		"disable_multicast %s\n\n"
+		"# If TRUE opensm will exit on fatal initialization issues\n"
+		"exit_on_fatal %s\n\n" "# console [off|local"
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+		"|loopback|socket]\n"
+#else
+		"]\n"
+#endif
+		"console %s\n\n"
+		"# Telnet port for console (default %d)\n"
+		"console_port %d\n\n",
+		p_opts->log_flags,
+		p_opts->force_log_flush ? "TRUE" : "FALSE",
+		p_opts->log_file,
+		p_opts->log_max_size/1024/1024,
+		p_opts->accum_log_file ? "TRUE" : "FALSE",
+		p_opts->dump_files_dir,
+		p_opts->enable_quirks ? "TRUE" : "FALSE",
+		p_opts->no_clients_rereg ? "TRUE" : "FALSE",
+		p_opts->disable_multicast ? "TRUE" : "FALSE",
+		p_opts->exit_on_fatal ? "TRUE" : "FALSE",
+		p_opts->console,
+		OSM_DEFAULT_CONSOLE_PORT, p_opts->console_port);
+
+	fprintf(out,
+		"#\n# QoS OPTIONS\n#\n"
+		"# Enable QoS setup\n"
+		"qos %s\n\n"
+		"# QoS policy file to be used\n"
+		"qos_policy_file %s\n\n",
+		p_opts->qos ? "TRUE" : "FALSE", p_opts->qos_policy_file);
+
+	subn_dump_qos_options(out,
+			      "QoS default options", "qos",
+			      &p_opts->qos_options);
+	fprintf(out, "\n");
+	subn_dump_qos_options(out,
+			      "QoS CA options", "qos_ca",
+			      &p_opts->qos_ca_options);
+	fprintf(out, "\n");
+	subn_dump_qos_options(out,
+			      "QoS Switch Port 0 options", "qos_sw0",
+			      &p_opts->qos_sw0_options);
+	fprintf(out, "\n");
+	subn_dump_qos_options(out,
+			      "QoS Switch external ports options", "qos_swe",
+			      &p_opts->qos_swe_options);
+	fprintf(out, "\n");
+	subn_dump_qos_options(out,
+			      "QoS Router ports options", "qos_rtr",
+			      &p_opts->qos_rtr_options);
+	fprintf(out, "\n");
+
+	fprintf(out,
+		"# Prefix routes file name\n"
+		"prefix_routes_file %s\n\n",
+		p_opts->prefix_routes_file);
+
+	fprintf(out,
+		"#\n# IPv6 Solicited Node Multicast (SNM) Options\n#\n"
+		"consolidate_ipv6_snm_req %s\n\n",
+		p_opts->consolidate_ipv6_snm_req ? "TRUE" : "FALSE");
+
+	/* optional string attributes ... */
+
+	return 0;
+}
+
+int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t *const p_opts)
+{
+	FILE *opts_file;
+
+	opts_file = fopen(file_name, "w");
+	if (!opts_file) {
+		printf("cannot open file \'%s\' for writing: %s\n",
+			file_name, strerror(errno));
+		return -1;
+	}
+
+	if (osm_subn_output_conf(opts_file, p_opts) < 0)
+		return -1;
+
+	fclose(opts_file);
+
+	return 0;
+}
diff --git a/opensm/osm_sw_info_rcv.c b/opensm/osm_sw_info_rcv.c
new file mode 100644
index 0000000..ce86adb
--- /dev/null
+++ b/opensm/osm_sw_info_rcv.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_port_info(IN osm_sm_t * sm, IN osm_switch_t * const p_sw)
+{
+	osm_madw_context_t context;
+	uint8_t port_num;
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	uint8_t num_ports;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_sw);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+	/*
+	   Request PortInfo attribute for each port on the switch.
+	 */
+	p_physp = osm_node_get_physp_ptr(p_node, 0);
+
+	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
+	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
+	context.pi_context.set_method = FALSE;
+	context.pi_context.light_sweep = FALSE;
+	context.pi_context.active_transition = FALSE;
+
+	num_ports = osm_node_get_num_physp(p_node);
+
+	for (port_num = 0; port_num < num_ports; port_num++) {
+		status = osm_req_get(sm, 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)
+			/* continue the loop despite the error */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3602: "
+				"Failure initiating PortInfo request (%s)\n",
+				ib_get_err_str(status));
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+#if 0
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_fwd_tbl(IN osm_sm_t * sm, 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(sm->p_log);
+
+	CL_ASSERT(p_sw);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+	context.lft_context.node_guid = osm_node_get_node_guid(p_node);
+	context.lft_context.set_method = FALSE;
+
+	max_block_id_ho = osm_switch_get_max_block_id_in_use(p_sw);
+
+	p_physp = osm_node_get_physp_ptr(p_node, 0);
+	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
+
+	for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Retrieving FT block %u\n", block_id_ho);
+
+		status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_LIN_FWD_TBL,
+				     cl_hton32(block_id_ho),
+				     CL_DISP_MSGID_NONE, &context);
+		if (status != IB_SUCCESS)
+			/* continue the loop despite the error */
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3603: "
+				"Failure initiating PortInfo request (%s)\n",
+				ib_get_err_str(status));
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_mcast_fwd_tbl(IN osm_sm_t * sm, 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(sm->p_log);
+
+	CL_ASSERT(p_sw);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+	if (osm_switch_get_mcast_fwd_tbl_size(p_sw) == 0) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Multicast not supported by switch 0x%016" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+		goto Exit;
+	}
+
+	context.mft_context.node_guid = osm_node_get_node_guid(p_node);
+	context.mft_context.set_method = FALSE;
+
+	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
+	max_block_id_ho = osm_mcast_tbl_get_max_block(p_tbl);
+
+	if (max_block_id_ho > IB_MCAST_MAX_BLOCK_ID) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3609: "
+			"Out-of-range mcast block size = %u on switch 0x%016"
+			PRIx64 "\n", max_block_id_ho,
+			cl_ntoh64(osm_node_get_node_guid(p_node)));
+		goto Exit;
+	}
+
+	max_position = osm_mcast_tbl_get_max_position(p_tbl);
+
+	CL_ASSERT(max_position <= IB_MCAST_POSITION_MAX);
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Max MFT block = %u, Max position = %u\n", max_block_id_ho,
+		max_position);
+
+	p_physp = osm_node_get_physp_ptr(p_node, 0);
+	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
+
+	for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Retrieving MFT block %u\n", block_id_ho);
+
+		for (position = 0; position <= max_position; position++) {
+			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+				"Retrieving MFT position %u\n", position);
+
+			attr_mod_ho =
+			    block_id_ho | position << IB_MCAST_POSITION_SHIFT;
+			status =
+			    osm_req_get(sm, p_dr_path,
+					IB_MAD_ATTR_MCAST_FWD_TBL,
+					cl_hton32(attr_mod_ho),
+					CL_DISP_MSGID_NONE, &context);
+			if (status != IB_SUCCESS)
+				/* continue the loop despite the error */
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3607: "
+					"Failure initiating PortInfo request (%s)\n",
+					ib_get_err_str(status));
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+#endif
+
+/**********************************************************************
+   Lock must be held on entry to this function.
+**********************************************************************/
+static void
+__osm_si_rcv_process_new(IN osm_sm_t * sm,
+			 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(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl;
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_si = (ib_switch_info_t *) ib_smp_get_payload_ptr(p_smp);
+
+	osm_dump_switch_info(sm->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(sm->p_log, OSM_LOG_ERROR, "ERR 3608: "
+			"Unable to allocate new switch object\n");
+		goto Exit;
+	}
+
+	/* set subnet max mlid to the minimum MulticastFDBCap of all switches */
+	if (p_sw->mcast_tbl.max_mlid_ho < sm->p_subn->max_mcast_lid_ho) {
+		sm->p_subn->max_mcast_lid_ho = p_sw->mcast_tbl.max_mlid_ho;
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Subnet max multicast lid is 0x%X\n",
+			sm->p_subn->max_mcast_lid_ho);
+	}
+
+	/* set subnet max unicast lid to the minimum LinearFDBCap of all switches */
+	if (cl_ntoh16(p_si->lin_cap) < sm->p_subn->max_ucast_lid_ho) {
+		sm->p_subn->max_ucast_lid_ho = cl_ntoh16(p_si->lin_cap);
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Subnet max unicast lid is 0x%X\n",
+			sm->p_subn->max_ucast_lid_ho);
+	}
+
+	p_check = (osm_switch_t *) cl_qmap_insert(p_sw_guid_tbl,
+						  osm_node_get_node_guid
+						  (p_node), &p_sw->map_item);
+
+	if (p_check != p_sw) {
+		/*
+		   This shouldn't happen since we hold the lock!
+		 */
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3605: "
+			"Unable to add new switch object to database\n");
+		osm_switch_delete(&p_sw);
+		goto Exit;
+	}
+
+	p_node->sw = p_sw;
+
+	/*
+	   Update the switch info according to the
+	   info we just received.
+	 */
+	osm_switch_set_switch_info(p_sw, p_si);
+	p_sw->discovery_count++;
+
+	/*
+	   Get the PortInfo attribute for every port.
+	 */
+	__osm_si_rcv_get_port_info(sm, p_sw);
+
+	/*
+	   Don't bother retrieving the current unicast and multicast tables
+	   from the switches.  The current version of SM does
+	   not support silent take-over of an existing multicast
+	   configuration.
+
+	   Gathering the multicast tables can also generate large amounts
+	   of extra subnet-init traffic.
+
+	   The code to retrieve the tables was fully debugged.
+	 */
+#if 0
+	__osm_si_rcv_get_fwd_tbl(sm, p_sw);
+	if (!sm->p_subn->opt.disable_multicast)
+		__osm_si_rcv_get_mcast_fwd_tbl(sm, p_sw);
+#endif
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+   Lock must be held on entry to this function.
+   Return 1 if the caller is expected to send a change_detected event.
+   this can not be done internally as the event needs the lock...
+**********************************************************************/
+static boolean_t
+__osm_si_rcv_process_existing(IN osm_sm_t * sm,
+			      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(sm->p_log);
+
+	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) {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"Received logical SetResp()\n");
+
+		osm_switch_set_switch_info(p_sw, p_si);
+	} else {
+		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+			"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(sm->p_log, OSM_LOG_VERBOSE,
+					"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(sm->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.
+			 */
+			p_sw->discovery_count++;
+			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+				"discovery_count is:%u\n",
+				p_sw->discovery_count);
+
+			/* If this is the first discovery - then get the port_info */
+			if (p_sw->discovery_count == 1)
+				__osm_si_rcv_get_port_info(sm, p_sw);
+			else
+				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+					"Not discovering again through switch:0x%"
+					PRIx64 "\n",
+					osm_node_get_node_guid(p_sw->p_node));
+		}
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+	return is_change_detected;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_si_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_switch_info_t *p_si;
+	ib_smp_t *p_smp;
+	osm_node_t *p_node;
+	ib_net64_t node_guid;
+	osm_si_context_t *p_context;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+	p_si = (ib_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;
+
+	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+		"Switch GUID 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n",
+		cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+
+	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
+
+	p_node = osm_get_node_by_guid(sm->p_subn, node_guid);
+	if (!p_node)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 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(sm->p_log, OSM_LOG_ERROR, "ERR 3610: "
+				"\n\t\t\t\tBad LinearFDBTop value = 0x%X "
+				"on switch 0x%" PRIx64
+				"\n\t\t\t\tForcing internal correction to 0x%X\n",
+				cl_ntoh16(p_si->lin_top),
+				cl_ntoh64(osm_node_get_node_guid(p_node)), 0);
+
+			p_si->lin_top = 0;
+		}
+
+		/*
+		   Acquire the switch object for this switch.
+		 */
+		if (!p_node->sw) {
+			__osm_si_rcv_process_new(sm, p_node, p_madw);
+			/*
+			   A new switch was found during the sweep so we need
+			   to ignore the current LFT settings.
+			 */
+			sm->p_subn->ignore_existing_lfts = TRUE;
+		} else {
+			/* we might get back a request for signaling change was detected */
+			if (__osm_si_rcv_process_existing(sm, p_node, p_madw)) {
+				CL_PLOCK_RELEASE(sm->p_lock);
+				sm->p_subn->force_heavy_sweep = TRUE;
+				goto Exit;
+			}
+		}
+	}
+
+	CL_PLOCK_RELEASE(sm->p_lock);
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_switch.c b/opensm/osm_switch.c
new file mode 100644
index 0000000..9807791
--- /dev/null
+++ b/opensm/osm_switch.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_switch_t.
+ * This object represents an Infiniband switch.
+ * This object is part of the opensm family of objects.
+ */
+
+#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>
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+	if (lid_ho > p_sw->max_lid_ho)
+		return -1;
+	if (!p_sw->hops[lid_ho]) {
+		p_sw->hops[lid_ho] = malloc(p_sw->num_ports);
+		if (!p_sw->hops[lid_ho])
+			return -1;
+		memset(p_sw->hops[lid_ho], OSM_NO_PATH, p_sw->num_ports);
+	}
+
+	p_sw->hops[lid_ho][port_num] = num_hops;
+	if (p_sw->hops[lid_ho][0] > num_hops)
+		p_sw->hops[lid_ho][0] = num_hops;
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static 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;
+
+	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;
+	p_sw->num_ports = num_ports;
+	p_sw->need_update = 2;
+
+	/* Initiate the linear forwarding table */
+
+	if (!p_si->lin_cap) {
+		/* This switch does not support linear forwarding tables */
+		status = IB_UNSUPPORTED;
+		goto Exit;
+	}
+
+	p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);
+	if (!p_sw->lft) {
+		status = IB_INSUFFICIENT_MEMORY;
+		goto Exit;
+	}
+
+	/* Initialize the table to OSM_NO_PATH, which is "invalid port" */
+	memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+	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_delete(IN OUT osm_switch_t ** const pp_sw)
+{
+	osm_switch_t *p_sw = *pp_sw;
+	unsigned i;
+
+	osm_mcast_tbl_destroy(&p_sw->mcast_tbl);
+	free(p_sw->p_prof);
+	if (p_sw->lft)
+		free(p_sw->lft);
+	if (p_sw->new_lft)
+		free(p_sw->new_lft);
+	if (p_sw->hops) {
+		for (i = 0; i < p_sw->num_hops; i++)
+			if (p_sw->hops[i])
+				free(p_sw->hops[i]);
+		free(p_sw->hops);
+	}
+	free(*pp_sw);
+	*pp_sw = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
+			     IN const osm_madw_t * const p_madw)
+{
+	ib_api_status_t status;
+	osm_switch_t *p_sw;
+
+	CL_ASSERT(p_madw);
+	CL_ASSERT(p_node);
+
+	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_lft_block(IN const osm_switch_t * const p_sw,
+			 IN const uint16_t block_id,
+			 OUT uint8_t * const p_block)
+{
+	uint16_t base_lid_ho = block_id * IB_SMP_DATA_SIZE;
+
+	CL_ASSERT(p_sw);
+	CL_ASSERT(p_block);
+
+	if (base_lid_ho > p_sw->max_lid_ho)
+		return FALSE;
+
+	CL_ASSERT(base_lid_ho + IB_SMP_DATA_SIZE <= IB_LID_UCAST_END_HO);
+	memcpy(p_block, &(p_sw->lft[base_lid_ho]), IB_SMP_DATA_SIZE);
+	return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static struct osm_remote_node *
+osm_switch_find_guid_common(IN const osm_switch_t * const p_sw,
+			    IN struct osm_remote_guids_count *r,
+			    IN uint8_t port_num,
+			    IN int find_sys_guid,
+			    IN int find_node_guid)
+{
+	struct osm_remote_node *p_remote_guid = NULL;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_rem_physp;
+	osm_node_t *p_rem_node;
+	uint64_t sys_guid;
+	uint64_t node_guid;
+	int i;
+
+	CL_ASSERT(p_sw);
+
+	p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+	p_rem_physp = osm_physp_get_remote(p_physp);
+	p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+	sys_guid = p_rem_node->node_info.sys_guid;
+	node_guid = p_rem_node->node_info.node_guid;
+
+	for (i = 0; i < r->count; i++) {
+		if ((!find_sys_guid
+		     || r->guids[i].node->node_info.sys_guid == sys_guid)
+		    && (!find_node_guid
+			|| r->guids[i].node->node_info.node_guid == node_guid)) {
+			p_remote_guid = &r->guids[i];
+			break;
+		}
+	}
+
+	return p_remote_guid;
+}
+
+static struct osm_remote_node *
+osm_switch_find_sys_guid_count(IN const osm_switch_t * const p_sw,
+			       IN struct osm_remote_guids_count *r,
+			       IN uint8_t port_num)
+{
+	return osm_switch_find_guid_common(p_sw, r, port_num, 1, 0);
+}
+
+static struct osm_remote_node *
+osm_switch_find_node_guid_count(IN const osm_switch_t * const p_sw,
+				IN struct osm_remote_guids_count *r,
+				IN uint8_t port_num)
+{
+	return osm_switch_find_guid_common(p_sw, r, port_num, 0, 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_path(IN const osm_switch_t * const p_sw,
+			  IN osm_port_t * p_port,
+			  IN const uint16_t lid_ho,
+			  IN unsigned start_from,
+			  IN const boolean_t ignore_existing,
+			  IN const boolean_t dor)
+{
+	/*
+	   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 this procedure is provided with the tracking array
+	   and counter we can conduct this algorithm.
+	 */
+	boolean_t routing_for_lmc = (p_port->priv != NULL);
+	uint16_t base_lid;
+	uint8_t hops;
+	uint8_t least_hops;
+	uint8_t port_num;
+	uint8_t num_ports;
+	uint32_t least_paths = 0xFFFFFFFF;
+	unsigned i;
+	/*
+	   The follwing will track the least paths if the
+	   route should go through a new system/node
+	 */
+	uint32_t least_paths_other_sys = 0xFFFFFFFF;
+	uint32_t least_paths_other_nodes = 0xFFFFFFFF;
+	uint32_t least_forwarded_to = 0xFFFFFFFF;
+	uint32_t check_count;
+	uint8_t best_port = 0;
+	/*
+	   These vars track the best port if it connects to
+	   not used system/node.
+	 */
+	uint8_t best_port_other_sys = 0;
+	uint8_t best_port_other_node = 0;
+	boolean_t port_found = FALSE;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_rem_physp;
+	osm_node_t *p_rem_node;
+	osm_node_t *p_rem_node_first = NULL;
+	struct osm_remote_node *p_remote_guid = NULL;
+
+	CL_ASSERT(lid_ho > 0);
+
+	if (p_port->p_node->sw) {
+		if (p_port->p_node->sw == p_sw)
+			return 0;
+		base_lid = osm_port_get_base_lid(p_port);
+	} else {
+		p_physp = p_port->p_physp;
+		if (!p_physp || !p_physp->p_remote_physp ||
+		    !p_physp->p_remote_physp->p_node->sw)
+			return OSM_NO_PATH;
+
+		if (p_physp->p_remote_physp->p_node->sw == p_sw)
+			return p_physp->p_remote_physp->port_num;
+		base_lid =
+		    osm_node_get_base_lid(p_physp->p_remote_physp->p_node, 0);
+	}
+	base_lid = cl_ntoh16(base_lid);
+
+	num_ports = p_sw->num_ports;
+
+	least_hops = osm_switch_get_least_hops(p_sw, base_lid);
+	if (least_hops == OSM_NO_PATH)
+		return (OSM_NO_PATH);
+
+	/*
+	   First, inquire with the forwarding table for an existing
+	   route.  If one is found, honor it unless:
+	   1. the ignore existing flag is set.
+	   2. the physical port is not a valid one or not healthy
+	   3. the physical port has a remote port (the link is up)
+	   4. the port has min-hops to the target (avoid loops)
+	 */
+	if (!ignore_existing) {
+		port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
+
+		if (port_num != OSM_NO_PATH) {
+			CL_ASSERT(port_num < num_ports);
+
+			p_physp =
+			    osm_node_get_physp_ptr(p_sw->p_node, port_num);
+			/*
+			   Don't be too trusting of the current forwarding table!
+			   Verify that the port number is legal and that the
+			   LID is reachable through this port.
+			 */
+			if (p_physp && osm_physp_is_healthy(p_physp) &&
+			    osm_physp_get_remote(p_physp)) {
+				hops =
+				    osm_switch_get_hop_count(p_sw, base_lid,
+							     port_num);
+				/*
+				   If we aren't using pre-defined user routes
+				   function, then we need to make sure that the
+				   current path is the minimum one. In case of
+				   having such a user function - this check will
+				   not be done, and the old routing will be used.
+				   Note: This means that it is the user's job to
+				   clean all data in the forwarding tables that
+				   he wants to be overridden by the minimum
+				   hop function.
+				 */
+				if (hops == least_hops)
+					return (port_num);
+			}
+		}
+	}
+
+	/*
+	   This algorithm selects a port based on a static load balanced
+	   selection across equal hop-count ports.
+	   There is lots of room for improved sophistication here,
+	   possibly guided by user configuration info.
+	 */
+
+	/*
+	   OpenSM routing is "local" - not considering a full lid to lid
+	   path. As such we can not guarantee a path will not loop if we
+	   do not always follow least hops.
+	   So we must abort if not least hops.
+	 */
+
+	/* port number starts with one and num_ports is 1 + num phys ports */
+	for (i = start_from; i < start_from + num_ports; i++) {
+		port_num = i%num_ports;
+		if (!port_num ||
+		    osm_switch_get_hop_count(p_sw, base_lid, port_num) !=
+		    least_hops)
+			continue;
+
+		/* let us make sure it is not down or unhealthy */
+		p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+		if (!p_physp || !osm_physp_is_healthy(p_physp) ||
+		    /*
+		       we require all - non sma ports to be linked
+		       to be routed through
+		     */
+		    !osm_physp_get_remote(p_physp))
+			continue;
+
+		/*
+		   We located a least-hop port, possibly one of many.
+		   For this port, check the running total count of
+		   the number of paths through this port.  Select
+		   the port routing the least number of paths.
+		 */
+		check_count =
+		    osm_port_prof_path_count_get(&p_sw->p_prof[port_num]);
+
+		/*
+		   Advanced LMC routing requires tracking of the
+		   best port by the node connected to the other side of
+		   it.
+		 */
+		if (routing_for_lmc) {
+			/* Is the sys guid already used ? */
+			p_remote_guid = osm_switch_find_sys_guid_count(p_sw,
+								       p_port->priv,
+								       port_num);
+
+			/* If not update the least hops for this case */
+			if (!p_remote_guid) {
+				if (check_count < least_paths_other_sys) {
+					least_paths_other_sys = check_count;
+					best_port_other_sys = port_num;
+					least_forwarded_to = 0;
+				}
+			} else {	/* same sys found - try node */
+				/* Else is the node guid already used ? */
+				p_remote_guid = osm_switch_find_node_guid_count(p_sw,
+										p_port->priv,
+										port_num);
+
+				/* If not update the least hops for this case */
+				if (!p_remote_guid
+				    && check_count < least_paths_other_nodes) {
+					least_paths_other_nodes = check_count;
+					best_port_other_node = port_num;
+					least_forwarded_to = 0;
+				}
+				/* else prior sys and node guid already used */
+
+			}	/* same sys found */
+		}
+
+		/* routing for LMC mode */
+		/*
+		   the count is min but also lower then the max subscribed
+		 */
+		if (check_count < least_paths) {
+			if (dor) {
+				/* Get the Remote Node */
+				p_rem_physp = osm_physp_get_remote(p_physp);
+				p_rem_node =
+				    osm_physp_get_node_ptr(p_rem_physp);
+				/* use the first dimension, but spread
+				 * traffic out among the group of ports
+				 * representing that dimension */
+				if (port_found) {
+					if (p_rem_node != p_rem_node_first)
+						continue;
+				} else
+					p_rem_node_first = p_rem_node;
+			}
+			port_found = TRUE;
+			best_port = port_num;
+			least_paths = check_count;
+			if (routing_for_lmc
+			    && p_remote_guid
+			    && p_remote_guid->forwarded_to < least_forwarded_to)
+				least_forwarded_to = p_remote_guid->forwarded_to;
+		} else if (routing_for_lmc
+			   && p_remote_guid
+			   && check_count == least_paths
+			   && p_remote_guid->forwarded_to < least_forwarded_to) {
+			least_forwarded_to = p_remote_guid->forwarded_to;
+			best_port = port_num;
+		}
+	}
+
+	if (port_found == FALSE)
+		return (OSM_NO_PATH);
+
+	/*
+	   if 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;
+	}
+
+	return (best_port);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_switch_clear_hops(IN osm_switch_t * p_sw)
+{
+	unsigned i;
+
+	for (i = 0; i < p_sw->num_hops; i++)
+		if (p_sw->hops[i])
+			memset(p_sw->hops[i], OSM_NO_PATH, p_sw->num_ports);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int
+osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids)
+{
+	uint8_t **hops;
+	unsigned i;
+
+	for (i = 0; i < p_sw->num_ports; i++)
+		osm_port_prof_construct(&p_sw->p_prof[i]);
+
+	osm_switch_clear_hops(p_sw);
+
+	if (!p_sw->new_lft &&
+	    !(p_sw->new_lft = malloc(IB_LID_UCAST_END_HO + 1)))
+		return IB_INSUFFICIENT_MEMORY;
+
+	memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+	if (!p_sw->hops) {
+		hops = malloc((max_lids + 1) * sizeof(hops[0]));
+		if (!hops)
+			return -1;
+		memset(hops, 0, (max_lids + 1) * sizeof(hops[0]));
+		p_sw->hops = hops;
+		p_sw->num_hops = max_lids + 1;
+	} else if (max_lids + 1 > p_sw->num_hops) {
+		uint8_t **old_hops;
+
+		hops = malloc((max_lids + 1) * sizeof(hops[0]));
+		if (!hops)
+			return -1;
+		memcpy(hops, p_sw->hops, p_sw->num_hops * sizeof(hops[0]));
+		memset(hops + p_sw->num_hops, 0,
+		       (max_lids + 1 - p_sw->num_hops) * sizeof(hops[0]));
+		old_hops = p_sw->hops;
+		p_sw->hops = hops;
+		p_sw->num_hops = max_lids + 1;
+		free(old_hops);
+	}
+	p_sw->max_lid_ho = max_lids;
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_get_port_least_hops(IN const osm_switch_t * const p_sw,
+			       IN const osm_port_t * p_port)
+{
+	uint16_t lid;
+
+	if (p_port->p_node->sw) {
+		if (p_port->p_node->sw == p_sw)
+			return 0;
+		lid = osm_node_get_base_lid(p_port->p_node, 0);
+		return osm_switch_get_least_hops(p_sw, cl_ntoh16(lid));
+	} else {
+		osm_physp_t *p = p_port->p_physp;
+		uint8_t hops;
+
+		if (!p || !p->p_remote_physp || !p->p_remote_physp->p_node->sw)
+			return OSM_NO_PATH;
+		if (p->p_remote_physp->p_node->sw == p_sw)
+			return 1;
+		lid = osm_node_get_base_lid(p->p_remote_physp->p_node, 0);
+		hops = osm_switch_get_least_hops(p_sw, cl_ntoh16(lid));
+		return hops != OSM_NO_PATH ? hops + 1 : OSM_NO_PATH;
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_mcast_path(IN osm_switch_t * const p_sw,
+				IN osm_port_t * p_port,
+				IN uint16_t const mlid_ho,
+				IN boolean_t const ignore_existing)
+{
+	uint16_t base_lid;
+	uint8_t hops;
+	uint8_t port_num;
+	uint8_t num_ports;
+	uint8_t least_hops;
+
+	CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
+
+	if (p_port->p_node->sw) {
+		if (p_port->p_node->sw == p_sw)
+			return 0;
+		base_lid = osm_port_get_base_lid(p_port);
+	} else {
+		osm_physp_t *p_physp = p_port->p_physp;
+		if (!p_physp || !p_physp->p_remote_physp ||
+		    !p_physp->p_remote_physp->p_node->sw)
+			return OSM_NO_PATH;
+		if (p_physp->p_remote_physp->p_node->sw == p_sw)
+			return p_physp->p_remote_physp->port_num;
+		base_lid =
+		    osm_node_get_base_lid(p_physp->p_remote_physp->p_node, 0);
+	}
+	base_lid = cl_ntoh16(base_lid);
+	num_ports = p_sw->num_ports;
+
+	/*
+	   If the user wants us to ignore existing multicast routes,
+	   then simply return the shortest hop count path to the
+	   target port.
+
+	   Otherwise, return the first port that has a path to the target,
+	   picking from the ports that are already in the multicast group.
+	 */
+	if (!ignore_existing) {
+		for (port_num = 1; port_num < num_ports; port_num++) {
+			if (!osm_mcast_tbl_is_port
+			    (&p_sw->mcast_tbl, mlid_ho, port_num))
+				continue;
+			/*
+			   Don't be too trusting of the current forwarding table!
+			   Verify that the LID is reachable through this port.
+			 */
+			hops =
+			    osm_switch_get_hop_count(p_sw, base_lid, port_num);
+			if (hops != OSM_NO_PATH)
+				return (port_num);
+		}
+	}
+
+	/*
+	   Either no existing mcast paths reach this port or we are
+	   ignoring existing paths.
+
+	   Determine the best multicast path to the target.  Note that this
+	   algorithm is slightly different from the one used for unicast route
+	   recommendation.  In this case (multicast), we must NOT
+	   perform any sort of load balancing.  We MUST take the FIRST
+	   port found that has <= the lowest hop count path.  This prevents
+	   more than one multicast path to the same remote switch which
+	   prevents a multicast loop.  Multicast loops are bad since the same
+	   multicast packet will go around and around, inevitably creating
+	   a black hole that will destroy the Earth in a firey conflagration.
+	 */
+	least_hops = osm_switch_get_least_hops(p_sw, base_lid);
+	for (port_num = 1; port_num < num_ports; port_num++)
+		if (osm_switch_get_hop_count(p_sw, base_lid, port_num) ==
+		    least_hops)
+			break;
+
+	CL_ASSERT(port_num < num_ports);
+	return (port_num);
+}
diff --git a/opensm/osm_trap_rcv.c b/opensm/osm_trap_rcv.c
new file mode 100644
index 0000000..46fbad7
--- /dev/null
+++ b/opensm/osm_trap_rcv.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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_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>
+
+extern void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t *p_physp);
+
+/**********************************************************************
+ *
+ * TRAP HANDLING:
+ *
+ * Assuming traps can be caused by bad hardware we should provide
+ * a mechanism for filtering their propagation into the actual logic
+ * of OpenSM such that it is not overloaded by them.
+ *
+ * We will provide a trap filtering mechanism with "Aging" capability.
+ * This mechanism will track incoming traps, clasify them by their
+ * source and content and provide back their age.
+ *
+ * A timer running in the background will toggle a timer counter
+ * that should be referenced by the aging algorithm.
+ * To provide an efficient handling of aging. We also track all traps
+ * in a sorted list by their aging.
+ *
+ * The generic Aging Tracker mechanism is implemented in the
+ * cl_aging_tracker object.
+ *
+ **********************************************************************/
+
+typedef struct osm_trap_agingracker_context {
+	osm_log_t *p_log;
+	osm_physp_t *p_physp;
+} osm_trap_aging_tracker_context_t;
+
+/**********************************************************************
+ **********************************************************************/
+static osm_physp_t *get_physp_by_lid_and_num(IN osm_sm_t * sm,
+					     IN uint16_t lid, IN uint8_t num)
+{
+	cl_ptr_vector_t *p_vec = &(sm->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_node_get_num_physp(p_port->p_node) < num)
+		return NULL;
+
+	return osm_node_get_physp_ptr(p_port->p_node, num);
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(IN uint64_t key,
+				    IN uint32_t num_regs, IN void *context)
+{
+	osm_sm_t *sm = context;
+	uint16_t lid;
+	uint8_t port_num;
+	osm_physp_t *p_physp;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	if (osm_exit_flag)
+		/* We got an exit flag - do nothing */
+		return 0;
+
+	lid = cl_ntoh16((uint16_t) ((key & 0x0000FFFF00000000ULL) >> 32));
+	port_num = (uint8_t) ((key & 0x00FF000000000000ULL) >> 48);
+
+	p_physp = get_physp_by_lid_and_num(sm, lid, port_num);
+	if (!p_physp)
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Cannot find port num:%u with lid:%u\n",
+			port_num, lid);
+	/* make sure the physp is still valid */
+	/* If the health port was false - set it to true */
+	else if (!osm_physp_is_healthy(p_physp)) {
+		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+			"Clearing health bit of port num:%u with lid:%u\n",
+			port_num, lid);
+
+		/* Clear its health bit */
+		osm_physp_set_health(p_physp, TRUE);
+	}
+
+	OSM_LOG_EXIT(sm->p_log);
+
+	/* We want to remove the event from the tracker - so
+	   need to return zero. */
+	return 0;
+}
+
+/**********************************************************************
+ * CRC calculation for notice identification
+ **********************************************************************/
+
+#define CRC32_POLYNOMIAL   0xEDB88320L
+
+/* calculate the crc for a given buffer */
+static uint32_t __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 int disable_port(osm_sm_t *sm, osm_physp_t *p)
+{
+	uint8_t payload[IB_SMP_DATA_SIZE];
+	osm_madw_context_t context;
+	ib_port_info_t *pi = (ib_port_info_t *)payload;
+	int ret;
+
+	/* select the nearest port to master opensm */
+	if (p->p_remote_physp &&
+	    p->dr_path.hop_count > p->p_remote_physp->dr_path.hop_count)
+		p = p->p_remote_physp;
+
+	/* If trap 131, might want to disable peer port if available */
+	/* but peer port has been observed not to respond to SM requests */
+
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3810: "
+		"Disabling physical port 0x%016" PRIx64 " num:%u\n",
+		cl_ntoh64(osm_physp_get_port_guid(p)), p->port_num);
+
+	memcpy(payload, &p->port_info, sizeof(ib_port_info_t));
+
+	/* Set port to disabled/down */
+	ib_port_info_set_port_state(pi, IB_LINK_DOWN);
+	ib_port_info_set_port_phys_state(IB_PORT_PHYS_STATE_DISABLED, pi);
+
+	/* Issue set of PortInfo */
+	context.pi_context.node_guid = osm_node_get_node_guid(p->p_node);
+	context.pi_context.port_guid = osm_physp_get_port_guid(p);
+	context.pi_context.set_method = TRUE;
+	context.pi_context.light_sweep = FALSE;
+	context.pi_context.active_transition = FALSE;
+
+	ret = osm_req_set(sm, osm_physp_get_dr_path_ptr(p),
+			  payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
+			  cl_hton32(osm_physp_get_port_num(p)),
+			  CL_DISP_MSGID_NONE, &context);
+	if (ret)
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3811: "
+			"Request to set PortInfo failed\n");
+
+	return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_trap_rcv_process_request(IN osm_sm_t * sm,
+			       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(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	if (osm_exit_flag)
+		/*
+		   We got an exit flag - do nothing
+		   Otherwise we start a sweep on the trap 144 caused by
+		   cleaning up SM Cap bit...
+		 */
+		goto 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(sm->p_log, OSM_LOG_ERROR, "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 (sm->p_subn->sm_base_lid == 0) {
+				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+					"Received SLID=0 Trap with local LID=0. Ignoring MAD\n");
+				goto Exit;
+			}
+			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
+				"Received SLID=0 Trap. Using local LID:%u instead\n",
+				cl_ntoh16(sm->p_subn->sm_base_lid));
+			tmp_madw.mad_addr.addr_type.smi.source_lid =
+			    sm->p_subn->sm_base_lid;
+		}
+
+		source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid;
+
+		/* Print some info about the incoming Trap */
+		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(sm->p_log, OSM_LOG_ERROR,
+					"Received Generic Notice type:%u "
+					"num:%u (%s) Producer:%u (%s) "
+					"from LID:%u Port %d TID:0x%016"
+					PRIx64 "\n", ib_notice_get_type(p_ntci),
+					cl_ntoh16(p_ntci->g_or_v.generic.
+						  trap_num),
+					ib_get_trap_str(p_ntci->g_or_v.generic.
+							trap_num),
+					cl_ntoh32(ib_notice_get_prod_type
+						  (p_ntci)),
+					ib_get_producer_type_str
+					(ib_notice_get_prod_type(p_ntci)),
+					cl_hton16(source_lid),
+					p_ntci->data_details.ntc_129_131.
+					port_num, cl_ntoh64(p_smp->trans_id));
+			else
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+					"Received Generic Notice type:%u "
+					"num:%u (%s) Producer:%u (%s) "
+					"from LID:%u TID:0x%016" PRIx64
+					"\n", ib_notice_get_type(p_ntci),
+					cl_ntoh16(p_ntci->g_or_v.generic.
+						  trap_num),
+					ib_get_trap_str(p_ntci->g_or_v.generic.
+							trap_num),
+					cl_ntoh32(ib_notice_get_prod_type
+						  (p_ntci)),
+					ib_get_producer_type_str
+					(ib_notice_get_prod_type(p_ntci)),
+					cl_hton16(source_lid),
+					cl_ntoh64(p_smp->trans_id));
+		} else
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+				"Received Vendor Notice type:%u vend:0x%06X "
+				"dev:%u from LID:%u TID:0x%016" PRIx64 "\n",
+				ib_notice_get_type(p_ntci),
+				cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
+				cl_ntoh16(p_ntci->g_or_v.vend.dev_id),
+				cl_ntoh16(source_lid),
+				cl_ntoh64(p_smp->trans_id));
+	}
+
+	osm_dump_notice(sm->p_log, p_ntci, OSM_LOG_VERBOSE);
+
+	p_physp = osm_get_physp_by_mad_addr(sm->p_log,
+					    sm->p_subn, &tmp_madw.mad_addr);
+	if (p_physp)
+		p_smp->m_key = p_physp->port_info.m_key;
+	else
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3809: "
+			"Failed to find source physical port for trap\n");
+
+	status = osm_resp_send(sm, &tmp_madw, 0, payload);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3802: "
+			"Error sending response (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * We would like to filter out recurring Traps so we track them by
+	 * their source lid and content. If the same trap was already
+	 * received within the aging time window more than 10 times,
+	 * we simply ignore it. This is done only if we are in smi mode
+	 */
+
+	if (is_gsi == FALSE) {
+		if (ib_notice_is_generic(p_ntci) &&
+		    ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(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 physp_change_trap flag as TRUE.
+			 */
+			physp_change_trap = TRUE;
+			/* The source_lid should be based on the source_lid from the trap */
+			source_lid = p_ntci->data_details.ntc_129_131.lid;
+		}
+
+		/* 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(&sm->trap_aging_tracker,
+					    trap_key);
+
+		/* Now we know how many times it provided this trap */
+		if (num_received > 10) {
+			if (__print_num_received(num_received))
+				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "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(sm,
+								   cl_ntoh16
+								   (p_ntci->
+								    data_details.
+								    ntc_129_131.
+								    lid),
+								   port_num);
+
+				if (!p_physp)
+					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+						"ERR 3805: "
+						"Failed to find physical port by lid:%u num:%u\n",
+						cl_ntoh16(p_ntci->data_details.
+							  ntc_129_131.lid),
+						p_ntci->data_details.
+						ntc_129_131.port_num);
+				else {
+					/* When babbling port policy option is enabled and
+					   Threshold for disabling a "babbling" port is exceeded */
+					if (sm->p_subn->opt.
+					    babbling_port_policy
+					    && num_received >= 250
+					    && disable_port(sm, p_physp) == 0)
+						goto Exit;
+
+					OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+						"Marking unhealthy physical port by lid:%u 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(&sm->trap_aging_tracker, trap_key, cl_get_time_stamp() + event_wheel_timeout, osm_trap_rcv_aging_tracker_callback,	/* no callback */
+					   sm	/* no context */ );
+		else
+			cl_event_wheel_reg(&sm->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(sm->p_log, OSM_LOG_VERBOSE,
+					"Continuously received this trap %u times. Ignoring\n",
+					num_received);
+			goto Exit;
+		}
+	}
+
+	/* Check for node description update. IB Spec v1.2.1 pg 823 */
+	if ((p_ntci->data_details.ntc_144.local_changes & TRAP_144_MASK_OTHER_LOCAL_CHANGES) &&
+		(p_ntci->data_details.ntc_144.change_flgs & TRAP_144_MASK_NODE_DESCRIPTION_CHANGE)
+		) {
+		OSM_LOG(sm->p_log, OSM_LOG_INFO, "Trap 144 Node description update\n");
+
+		if (p_physp) {
+			CL_PLOCK_ACQUIRE(sm->p_lock);
+			osm_req_get_node_desc(sm, p_physp);
+			CL_PLOCK_RELEASE(sm->p_lock);
+		} else {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+				"ERR 3812: No physical port found for "
+				"trap 144: \"node description update\"\n");
+		}
+	}
+
+	/* do a sweep if we received a trap */
+	if (sm->p_subn->opt.sweep_on_trap) {
+		/* if this is trap number 128 or run_heavy_sweep is TRUE - update the
+		   force_single_heavy_sweep flag of the subnet.
+		   Sweep also on traps 144/145 - these traps signal a change of 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(sm->p_log, OSM_LOG_VERBOSE,
+				"Forcing heavy sweep. Received trap:%u\n",
+				cl_ntoh16(p_ntci->g_or_v.generic.trap_num));
+
+			sm->p_subn->force_heavy_sweep = TRUE;
+		}
+		osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
+	}
+
+	/* If we reached here due to trap 129/130/131 - do not need to do
+	   the notice report. Just goto exit. We know this is the case
+	   if physp_change_trap is TRUE. */
+	if (physp_change_trap == TRUE)
+		goto Exit;
+
+	/* Add a call to osm_report_notice */
+	/* We are going to report the notice - so need to fix the IssuerGID
+	   accordingly. See IBA 1.2 p.739 or IBA 1.1 p.653 for details. */
+	if (is_gsi) {
+		if (!tmp_madw.mad_addr.addr_type.gsi.global_route) {
+			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3806: "
+				"Received gsi trap with global_route FALSE. "
+				"Cannot update issuer_gid!\n");
+			goto Exit;
+		}
+		memcpy(&(p_ntci->issuer_gid),
+		       &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid),
+		       sizeof(ib_gid_t));
+	} else {
+		/* Need to use the IssuerLID */
+		p_tbl = &sm->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(sm->p_log, OSM_LOG_VERBOSE,
+				"source lid is out of range:%u\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(sm->p_log, OSM_LOG_VERBOSE,
+				"Cannot find port corresponding to lid:%u\n",
+				cl_ntoh16(source_lid));
+
+			goto Exit;
+		}
+
+		p_ntci->issuer_gid.unicast.prefix =
+		    sm->p_subn->opt.subnet_prefix;
+		p_ntci->issuer_gid.unicast.interface_id = p_port->guid;
+	}
+
+	/* we need a lock here as the InformInfo DB must be stable */
+	CL_PLOCK_ACQUIRE(sm->p_lock);
+	status = osm_report_notice(sm->p_log, sm->p_subn, p_ntci);
+	CL_PLOCK_RELEASE(sm->p_lock);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3803: "
+			"Error sending trap reports (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+#if 0
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_sm(IN osm_sm_t * sm,
+			  IN const osm_remote_sm_t * const p_sm)
+{
+	/* const ib_sm_info_t*        p_smi; */
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3807: "
+		"This function is not supported yet\n");
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+#endif
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_response(IN osm_sm_t * sm,
+				IN const osm_madw_t * const p_madw)
+{
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3808: "
+		"This function is not supported yet\n");
+
+	OSM_LOG_EXIT(sm->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_trap_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_smp_t *p_smp;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	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(sm, p_madw);
+	else
+		__osm_trap_rcv_process_request(sm, p_madw);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/osm_ucast_cache.c b/opensm/osm_ucast_cache.c
new file mode 100644
index 0000000..c89e24d
--- /dev/null
+++ b/opensm/osm_ucast_cache.c
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2008      Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM Cached Unicast 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_ucast_mgr.h>
+#include <opensm/osm_ucast_cache.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+
+#define CACHE_SW_PORTS 36
+
+typedef struct cache_port {
+	boolean_t is_leaf;
+	uint16_t remote_lid_ho;
+} cache_port_t;
+
+typedef struct cache_switch {
+	cl_map_item_t map_item;
+	boolean_t dropped;
+	uint16_t max_lid_ho;
+	uint16_t num_hops;
+	uint8_t **hops;
+	uint8_t *lft;
+	uint8_t num_ports;
+	cache_port_t ports[0];
+} cache_switch_t;
+
+/**********************************************************************
+ **********************************************************************/
+
+static uint16_t __cache_sw_get_base_lid_ho(cache_switch_t * p_sw)
+{
+	return p_sw->ports[0].remote_lid_ho;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static boolean_t __cache_sw_is_leaf(cache_switch_t * p_sw)
+{
+	return p_sw->ports[0].is_leaf;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __cache_sw_set_leaf(cache_switch_t * p_sw)
+{
+	p_sw->ports[0].is_leaf = TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static cache_switch_t *__cache_sw_new(uint16_t lid_ho, unsigned num_ports)
+{
+	cache_switch_t *p_cache_sw = malloc(sizeof(cache_switch_t) +
+					    num_ports * sizeof(cache_port_t));
+	if (!p_cache_sw)
+		return NULL;
+
+	memset(p_cache_sw, 0,
+	       sizeof(*p_cache_sw) + num_ports * sizeof(cache_port_t));
+
+	p_cache_sw->num_ports = num_ports;
+
+	/* port[0] fields represent this switch details - lid and type */
+	p_cache_sw->ports[0].remote_lid_ho = lid_ho;
+	p_cache_sw->ports[0].is_leaf = FALSE;
+
+	return p_cache_sw;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __cache_sw_destroy(cache_switch_t * p_sw)
+{
+	if (!p_sw)
+		return;
+
+	if (p_sw->lft)
+		free(p_sw->lft);
+	if (p_sw->hops)
+		free(p_sw->hops);
+	free(p_sw);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static cache_switch_t *__cache_get_sw(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho)
+{
+	cache_switch_t *p_cache_sw = (cache_switch_t *)
+	    cl_qmap_get(&p_mgr->cache_sw_tbl, lid_ho);
+	if (p_cache_sw == (cache_switch_t *)
+	    cl_qmap_end(&p_mgr->cache_sw_tbl))
+		p_cache_sw = NULL;
+
+	return p_cache_sw;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __cache_add_sw_link(osm_ucast_mgr_t * p_mgr, osm_physp_t *p,
+				uint16_t remote_lid_ho, boolean_t is_ca)
+{
+	cache_switch_t *p_cache_sw;
+	uint16_t lid_ho = cl_ntoh16(osm_node_get_base_lid(p->p_node, 0));
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!lid_ho || !remote_lid_ho || !p->port_num)
+		goto Exit;
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Caching switch port: lid %u [port %u] -> lid %u (%s)\n",
+		lid_ho, p->port_num, remote_lid_ho, (is_ca) ? "CA/RTR" : "SW");
+
+	p_cache_sw = __cache_get_sw(p_mgr, lid_ho);
+	if (!p_cache_sw) {
+		p_cache_sw = __cache_sw_new(lid_ho, p->p_node->sw->num_ports);
+		if (!p_cache_sw) {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
+				"ERR AD01: Out of memory - cache is invalid\n");
+			osm_ucast_cache_invalidate(p_mgr);
+			goto Exit;
+		}
+		cl_qmap_insert(&p_mgr->cache_sw_tbl, lid_ho,
+			       &p_cache_sw->map_item);
+	}
+
+	if (p->port_num >= p_cache_sw->num_ports) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
+			"ERR AD02: Wrong switch? - cache is invalid\n");
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	if (is_ca)
+		__cache_sw_set_leaf(p_cache_sw);
+
+	if (p_cache_sw->ports[p->port_num].remote_lid_ho == 0) {
+		/* cache this link only if it hasn't been already cached */
+		p_cache_sw->ports[p->port_num].remote_lid_ho = remote_lid_ho;
+		p_cache_sw->ports[p->port_num].is_leaf = is_ca;
+	}
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __cache_cleanup_switches(osm_ucast_mgr_t * p_mgr)
+{
+	cache_switch_t *p_sw;
+	cache_switch_t *p_next_sw;
+	unsigned port_num;
+	boolean_t found_port;
+
+	if (!p_mgr->cache_valid)
+		return;
+
+	p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
+	while (p_next_sw !=
+	       (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item);
+
+		found_port = FALSE;
+		for (port_num = 1; port_num < p_sw->num_ports; port_num++)
+			if (p_sw->ports[port_num].remote_lid_ho)
+				found_port = TRUE;
+
+		if (!found_port) {
+			cl_qmap_remove_item(&p_mgr->cache_sw_tbl,
+					    &p_sw->map_item);
+			__cache_sw_destroy(p_sw);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__cache_check_link_change(osm_ucast_mgr_t * p_mgr,
+			  osm_physp_t * p_physp_1, osm_physp_t * p_physp_2)
+{
+	OSM_LOG_ENTER(p_mgr->p_log);
+	CL_ASSERT(p_physp_1 && p_physp_2);
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	if (!p_physp_1->p_remote_physp && !p_physp_2->p_remote_physp)
+		/* both ports were down - new link */
+		goto Exit;
+
+	/* unicast cache cannot tolerate any link location change */
+
+	if ((p_physp_1->p_remote_physp &&
+	     p_physp_1->p_remote_physp->p_remote_physp) ||
+	    (p_physp_2->p_remote_physp &&
+	     p_physp_2->p_remote_physp->p_remote_physp)) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Link location change discovered - cache is invalid\n");
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __cache_remove_port(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho,
+				uint8_t port_num, uint16_t remote_lid_ho,
+				boolean_t is_ca)
+{
+	cache_switch_t *p_cache_sw;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	p_cache_sw = __cache_get_sw(p_mgr, lid_ho);
+	if (!p_cache_sw) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Found uncached switch/link (lid %u, port %u) - "
+			"cache is invalid\n", lid_ho, port_num);
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	if (port_num >= p_cache_sw->num_ports ||
+	    !p_cache_sw->ports[port_num].remote_lid_ho) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Found uncached switch link (lid %u, port %u) - "
+			"cache is invalid\n", lid_ho, port_num);
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	if (p_cache_sw->ports[port_num].remote_lid_ho != remote_lid_ho) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Remote lid change on switch lid %u, port %u "
+			"(was %u, now %u) - cache is invalid\n",
+			lid_ho, port_num,
+			p_cache_sw->ports[port_num].remote_lid_ho,
+			remote_lid_ho);
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	if ((p_cache_sw->ports[port_num].is_leaf && !is_ca) ||
+	    (!p_cache_sw->ports[port_num].is_leaf && is_ca)) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Remote node type change on switch lid %u, port %u - "
+			"cache is invalid\n", lid_ho, port_num);
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"New link from lid %u, port %u to lid %u - "
+		"found in cache\n", lid_ho, port_num, remote_lid_ho);
+
+	/* the new link was cached - clean it from the cache */
+
+	p_cache_sw->ports[port_num].remote_lid_ho = 0;
+	p_cache_sw->ports[port_num].is_leaf = FALSE;
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}				/* __cache_remove_port() */
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__cache_restore_ucast_info(osm_ucast_mgr_t * p_mgr,
+			   cache_switch_t * p_cache_sw, osm_switch_t * p_sw)
+{
+	if (!p_mgr->cache_valid)
+		return;
+
+	/* when seting unicast info, the cached port
+	   should have all the required info */
+	CL_ASSERT(p_cache_sw->max_lid_ho && p_cache_sw->lft &&
+		  p_cache_sw->num_hops && p_cache_sw->hops);
+
+	p_sw->max_lid_ho = p_cache_sw->max_lid_ho;
+
+	if (p_sw->new_lft)
+		free(p_sw->new_lft);
+	p_sw->new_lft = p_cache_sw->lft;
+	p_cache_sw->lft = NULL;
+
+	p_sw->num_hops = p_cache_sw->num_hops;
+	p_cache_sw->num_hops = 0;
+	if (p_sw->hops)
+		free(p_sw->hops);
+	p_sw->hops = p_cache_sw->hops;
+	p_cache_sw->hops = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void __ucast_cache_dump(osm_ucast_mgr_t * p_mgr)
+{
+	cache_switch_t *p_sw;
+	unsigned i;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!osm_log_is_active(p_mgr->p_log, OSM_LOG_DEBUG))
+		goto Exit;
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Dumping missing nodes/links as logged by unicast cache:\n");
+	for (p_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
+	     p_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
+	     p_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item)) {
+
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"\t Switch lid %u %s%s\n",
+			__cache_sw_get_base_lid_ho(p_sw),
+			(__cache_sw_is_leaf(p_sw)) ? "[leaf switch] " : "",
+			(p_sw->dropped) ? "[whole switch missing]" : "");
+
+		for (i = 1; i < p_sw->num_ports; i++)
+			if (p_sw->ports[i].remote_lid_ho > 0)
+				OSM_LOG(p_mgr->p_log,
+					OSM_LOG_DEBUG,
+					"\t     - port %u -> lid %u %s\n",
+					i, p_sw->ports[i].remote_lid_ho,
+					(p_sw->ports[i].is_leaf) ?
+					"[remote node is leaf]" : "");
+	}
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void osm_ucast_cache_invalidate(osm_ucast_mgr_t * p_mgr)
+{
+	cache_switch_t *p_sw;
+	cache_switch_t *p_next_sw;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Invalidating unicast cache\n");
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	p_mgr->cache_valid = FALSE;
+
+	p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
+	while (p_next_sw !=
+	       (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item);
+		__cache_sw_destroy(p_sw);
+	}
+	cl_qmap_remove_all(&p_mgr->cache_sw_tbl);
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr)
+{
+	cache_switch_t *p_cache_sw;
+	cache_switch_t *p_remote_cache_sw;
+	unsigned port_num;
+	unsigned max_ports;
+	uint8_t remote_node_type;
+	uint16_t lid_ho;
+	uint16_t remote_lid_ho;
+	osm_switch_t *p_sw;
+	osm_switch_t *p_remote_sw;
+	osm_node_t *p_node;
+	osm_physp_t *p_physp;
+	osm_physp_t *p_remote_physp;
+	osm_port_t *p_remote_port;
+	cl_qmap_t *p_sw_tbl;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	/* If there are no switches in the subnet, we are done */
+	p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+	if (cl_qmap_count(p_sw_tbl) == 0) {
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	/*
+	 * Scan all the physical switch ports in the subnet.
+	 * If the port need_update flag is on, check whether
+	 * it's just some node/port reset or a cached topology
+	 * change. Otherwise the cache is invalid.
+	 */
+	for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
+	     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl);
+	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {
+
+		p_node = p_sw->p_node;
+
+		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
+		p_cache_sw = __cache_get_sw(p_mgr, lid_ho);
+
+		max_ports = osm_node_get_num_physp(p_node);
+
+		/* skip port 0 */
+		for (port_num = 1; port_num < max_ports; port_num++) {
+
+			p_physp = osm_node_get_physp_ptr(p_node, port_num);
+
+			if (!p_physp || !p_physp->p_remote_physp ||
+			    !osm_physp_link_exists(p_physp,
+						   p_physp->p_remote_physp))
+				/* no valid link */
+				continue;
+
+			/*
+			 * While scanning all the physical ports in the subnet,
+			 * mark corresponding leaf switches in the cache.
+			 */
+			if (p_cache_sw &&
+			    !p_cache_sw->dropped &&
+			    !__cache_sw_is_leaf(p_cache_sw) &&
+			    p_physp->p_remote_physp->p_node &&
+			    osm_node_get_type(p_physp->p_remote_physp->
+					      p_node) != IB_NODE_TYPE_SWITCH)
+				__cache_sw_set_leaf(p_cache_sw);
+
+			if (!p_physp->need_update)
+				continue;
+
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"Checking switch lid %u, port %u\n",
+				lid_ho, port_num);
+
+			p_remote_physp = osm_physp_get_remote(p_physp);
+			remote_node_type =
+			    osm_node_get_type(p_remote_physp->p_node);
+
+			if (remote_node_type == IB_NODE_TYPE_SWITCH)
+				remote_lid_ho =
+				    cl_ntoh16(osm_node_get_base_lid
+					      (p_remote_physp->p_node, 0));
+			else
+				remote_lid_ho =
+				    cl_ntoh16(osm_node_get_base_lid
+					      (p_remote_physp->p_node,
+					       osm_physp_get_port_num
+					       (p_remote_physp)));
+
+			if (!p_cache_sw ||
+			    port_num >= p_cache_sw->num_ports ||
+			    !p_cache_sw->ports[port_num].remote_lid_ho) {
+				/*
+				 * There is some uncached change on the port.
+				 * In general, the reasons might be as follows:
+				 *  - switch reset
+				 *  - port reset (or port down/up)
+				 *  - quick connection location change
+				 *  - new link (or new switch)
+				 *
+				 * First two reasons allow cache usage, while
+				 * the last two reasons should invalidate cache.
+				 *
+				 * In case of quick connection location change,
+				 * cache would have been invalidated by
+				 * osm_ucast_cache_check_new_link() function.
+				 *
+				 * In case of new link between two known nodes,
+				 * cache also would have been invalidated by
+				 * osm_ucast_cache_check_new_link() function.
+				 *
+				 * Another reason is cached link between two
+				 * known switches went back. In this case the
+				 * osm_ucast_cache_check_new_link() function would
+				 * clear both sides of the link from the cache
+				 * during the discovery process, so effectively
+				 * this would be equivalent to port reset.
+				 *
+				 * So three possible reasons remain:
+				 *  - switch reset
+				 *  - port reset (or port down/up)
+				 *  - link of a new switch
+				 *
+				 * To validate cache, we need to check only the
+				 * third reason - link of a new node/switch:
+				 *  - If this is the local switch that is new,
+				 *    then it should have (p_sw->need_update == 2).
+				 *  - If the remote node is switch and it's new,
+				 *    then it also should have
+				 *    (p_sw->need_update == 2).
+				 *  - If the remote node is CA/RTR and it's new,
+				 *    then its port should have is_new flag on.
+				 */
+				if (p_sw->need_update == 2) {
+					OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+						"New switch found (lid %u) - "
+						"cache is invalid\n", lid_ho);
+					osm_ucast_cache_invalidate(p_mgr);
+					goto Exit;
+				}
+
+				if (remote_node_type == IB_NODE_TYPE_SWITCH) {
+
+					p_remote_sw =
+					    p_remote_physp->p_node->sw;
+					if (p_remote_sw->need_update == 2) {
+						/* this could also be case of
+						   switch coming back with an
+						   additional link that it
+						   didn't have before */
+						OSM_LOG(p_mgr->p_log,
+							OSM_LOG_INFO,
+							"New switch/link found (lid %u) - "
+							"cache is invalid\n",
+							remote_lid_ho);
+						osm_ucast_cache_invalidate
+						    (p_mgr);
+						goto Exit;
+					}
+				} else {
+					/*
+					 * Remote node is CA/RTR.
+					 * Get p_port of the remote node and
+					 * check its p_port->is_new flag.
+					 */
+					p_remote_port =
+					    osm_get_port_by_guid(p_mgr->p_subn,
+								 osm_physp_get_port_guid
+								 (p_remote_physp));
+					if (p_remote_port->is_new) {
+						OSM_LOG(p_mgr->p_log,
+							OSM_LOG_INFO,
+							"New CA/RTR found (lid %u) - "
+							"cache is invalid\n",
+							remote_lid_ho);
+						osm_ucast_cache_invalidate
+						    (p_mgr);
+						goto Exit;
+					}
+				}
+			} else {
+				/*
+				 * The change on the port is cached.
+				 * In general, the reasons might be as follows:
+				 *  - link between two known nodes went back
+				 *  - one or more nodes went back, causing all
+				 *    the links to reappear
+				 *
+				 * If it was link that went back, then this case
+				 * would have been taken care of during the
+				 * discovery by osm_ucast_cache_check_new_link(),
+				 * so it's some node that went back.
+				 */
+				if ((p_cache_sw->ports[port_num].is_leaf &&
+				     remote_node_type == IB_NODE_TYPE_SWITCH) ||
+				    (!p_cache_sw->ports[port_num].is_leaf &&
+				     remote_node_type != IB_NODE_TYPE_SWITCH)) {
+					OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+						"Remote node type change on switch lid %u, port %u - "
+						"cache is invalid\n",
+						lid_ho, port_num);
+					osm_ucast_cache_invalidate(p_mgr);
+					goto Exit;
+				}
+
+				if (p_cache_sw->ports[port_num].remote_lid_ho !=
+				    remote_lid_ho) {
+					OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+						"Remote lid change on switch lid %u, port %u"
+						"(was %u, now %u) - cache is invalid\n",
+						lid_ho, port_num,
+						p_cache_sw->ports[port_num].
+						remote_lid_ho, remote_lid_ho);
+					osm_ucast_cache_invalidate(p_mgr);
+					goto Exit;
+				}
+
+				/*
+				 * We don't care who is the node that has
+				 * reappeared in the subnet (local or remote).
+				 * What's important that the cached link matches
+				 * the real fabrics link.
+				 * Just clean it from cache.
+				 */
+
+				p_cache_sw->ports[port_num].remote_lid_ho = 0;
+				p_cache_sw->ports[port_num].is_leaf = FALSE;
+				if (p_cache_sw->dropped) {
+					__cache_restore_ucast_info(p_mgr,
+								   p_cache_sw,
+								   p_sw);
+					p_cache_sw->dropped = FALSE;
+				}
+
+				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+					"Restored link from cache: lid %u, port %u to lid %u\n",
+					lid_ho, port_num, remote_lid_ho);
+			}
+		}
+	}
+
+	/* Remove all the cached switches that
+	   have all their ports restored */
+	__cache_cleanup_switches(p_mgr);
+
+	/*
+	 * Done scanning all the physical switch ports in the subnet.
+	 * Now we need to check the other side:
+	 * Scan all the cached switches and their ports:
+	 *  - If the cached switch is missing in the subnet
+	 *    (dropped flag is on), check that it's a leaf switch.
+	 *    If it's not a leaf, the cache is invalid, because
+	 *    cache can tolerate only leaf switch removal.
+	 *  - If the cached switch exists in fabric, check all
+	 *    its cached ports. These cached ports represent
+	 *    missing link in the fabric.
+	 *    The missing links that can be tolerated are:
+	 *      + link to missing CA/RTR
+	 *      + link to missing leaf switch
+	 */
+	for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
+	     p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
+	     p_cache_sw =
+	     (cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) {
+
+		if (p_cache_sw->dropped) {
+			if (!__cache_sw_is_leaf(p_cache_sw)) {
+				OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+					"Missing non-leaf switch (lid %u) - "
+					"cache is invalid\n",
+					__cache_sw_get_base_lid_ho(p_cache_sw));
+				osm_ucast_cache_invalidate(p_mgr);
+				goto Exit;
+			}
+
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"Missing leaf switch (lid %u) - "
+				"continuing validation\n",
+				__cache_sw_get_base_lid_ho(p_cache_sw));
+			continue;
+		}
+
+		for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) {
+			if (!p_cache_sw->ports[port_num].remote_lid_ho)
+				continue;
+
+			if (p_cache_sw->ports[port_num].is_leaf) {
+				CL_ASSERT(__cache_sw_is_leaf(p_cache_sw));
+				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+					"Switch lid %u, port %u: missing link to CA/RTR - "
+					"continuing validation\n",
+					__cache_sw_get_base_lid_ho(p_cache_sw),
+					port_num);
+				continue;
+			}
+
+			p_remote_cache_sw = __cache_get_sw(p_mgr,
+							   p_cache_sw->
+							   ports[port_num].
+							   remote_lid_ho);
+
+			if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) {
+				OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+					"Switch lid %u, port %u: missing link to existing switch - "
+					"cache is invalid\n",
+					__cache_sw_get_base_lid_ho(p_cache_sw),
+					port_num);
+				osm_ucast_cache_invalidate(p_mgr);
+				goto Exit;
+			}
+
+			if (!__cache_sw_is_leaf(p_remote_cache_sw)) {
+				OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+					"Switch lid %u, port %u: missing link to non-leaf switch - "
+					"cache is invalid\n",
+					__cache_sw_get_base_lid_ho(p_cache_sw),
+					port_num);
+				osm_ucast_cache_invalidate(p_mgr);
+				goto Exit;
+			}
+
+			/*
+			 * At this point we know that the missing link is to
+			 * a leaf switch. However, one case deserves a special
+			 * treatment. If there was a link between two leaf
+			 * switches, then missing leaf switch might break
+			 * routing. It is possible that there are routes
+			 * that use leaf switches to get from switch to switch
+			 * and not just to get to the CAs behind the leaf switch.
+			 */
+			if (__cache_sw_is_leaf(p_cache_sw) &&
+			    __cache_sw_is_leaf(p_remote_cache_sw)) {
+				OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+					"Switch lid %u, port %u: missing leaf-2-leaf link - "
+					"cache is invalid\n",
+					__cache_sw_get_base_lid_ho(p_cache_sw),
+					port_num);
+				osm_ucast_cache_invalidate(p_mgr);
+				goto Exit;
+			}
+
+			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+				"Switch lid %u, port %u: missing remote leaf switch - "
+				"continuing validation\n",
+				__cache_sw_get_base_lid_ho(p_cache_sw),
+				port_num);
+		}
+	}
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n");
+	__ucast_cache_dump(p_mgr);
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}				/* osm_ucast_cache_validate() */
+
+/**********************************************************************
+ **********************************************************************/
+
+void osm_ucast_cache_check_new_link(osm_ucast_mgr_t * p_mgr,
+				    osm_node_t * p_node_1, uint8_t port_num_1,
+				    osm_node_t * p_node_2, uint8_t port_num_2)
+{
+	uint16_t lid_ho_1;
+	uint16_t lid_ho_2;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	__cache_check_link_change(p_mgr,
+				  osm_node_get_physp_ptr(p_node_1, port_num_1),
+				  osm_node_get_physp_ptr(p_node_2, port_num_2));
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH &&
+	    osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Found CA/RTR-2-CA/RTR link - cache is invalid\n");
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	/* for code simplicity, we want the first node to be switch */
+	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) {
+		osm_node_t *tmp_node = p_node_1;
+		uint8_t tmp_port_num = port_num_1;
+		p_node_1 = p_node_2;
+		port_num_1 = port_num_2;
+		p_node_2 = tmp_node;
+		port_num_2 = tmp_port_num;
+	}
+
+	lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0));
+
+	if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH)
+		lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0));
+	else
+		lid_ho_2 =
+		    cl_ntoh16(osm_node_get_base_lid(p_node_2, port_num_2));
+
+	if (!lid_ho_1 || !lid_ho_2) {
+		/*
+		 * No lid assigned, which means that one of the nodes is new.
+		 * Need to wait for lid manager to process this node.
+		 * The switches and their links will be checked later when
+		 * the whole cache validity will be verified.
+		 */
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Link port %u <-> %u reveals new node - cache will "
+			"be validated later\n", port_num_1, port_num_2);
+		goto Exit;
+	}
+
+	__cache_remove_port(p_mgr, lid_ho_1, port_num_1, lid_ho_2,
+			    (osm_node_get_type(p_node_2) !=
+			     IB_NODE_TYPE_SWITCH));
+
+	/* if node_2 is a switch, the link should be cleaned from its cache */
+
+	if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH)
+		__cache_remove_port(p_mgr, lid_ho_2,
+				    port_num_2, lid_ho_1, FALSE);
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}				/* osm_ucast_cache_check_new_link() */
+
+/**********************************************************************
+ **********************************************************************/
+
+void osm_ucast_cache_add_link(osm_ucast_mgr_t * p_mgr,
+			      osm_physp_t * p_physp1, osm_physp_t * p_physp2)
+{
+	osm_node_t *p_node_1 = p_physp1->p_node, *p_node_2 = p_physp2->p_node;
+	uint16_t lid_ho_1, lid_ho_2;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH &&
+	    osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+			"Dropping CA-2-CA link - cache invalid\n");
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	if ((osm_node_get_type(p_node_1) == IB_NODE_TYPE_SWITCH &&
+	     !osm_node_get_physp_ptr(p_node_1, 0)) ||
+	    (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH &&
+	     !osm_node_get_physp_ptr(p_node_2, 0))) {
+		/* we're caching a link when one of the nodes
+		   has already been dropped and cached */
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Port %u <-> port %u: port0 on one of the nodes "
+			"has already been dropped and cached\n",
+			p_physp1->port_num, p_physp2->port_num);
+		goto Exit;
+	}
+
+	/* One of the nodes is switch. Just for code
+	   simplicity, make sure that it's the first node. */
+
+	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) {
+		osm_physp_t *tmp = p_physp1;
+		p_physp1 = p_physp2;
+		p_physp2 = tmp;
+		p_node_1 = p_physp1->p_node;
+		p_node_2 = p_physp2->p_node;
+	}
+
+	if (!p_node_1->sw) {
+		/* something is wrong - we'd better not use cache */
+		osm_ucast_cache_invalidate(p_mgr);
+		goto Exit;
+	}
+
+	lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0));
+
+	if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) {
+
+		if (!p_node_2->sw) {
+			/* something is wrong - we'd better not use cache */
+			osm_ucast_cache_invalidate(p_mgr);
+			goto Exit;
+		}
+
+		lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0));
+
+		/* lost switch-2-switch link - cache both sides */
+		__cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, FALSE);
+		__cache_add_sw_link(p_mgr, p_physp2, lid_ho_1, FALSE);
+	} else {
+		lid_ho_2 = cl_ntoh16(osm_physp_get_base_lid(p_physp2));
+
+		/* lost link to CA/RTR - cache only switch side */
+		__cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, TRUE);
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}				/* osm_ucast_cache_add_link() */
+
+/**********************************************************************
+ **********************************************************************/
+
+void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node)
+{
+	uint16_t lid_ho;
+	uint8_t max_ports;
+	uint8_t port_num;
+	osm_physp_t *p_physp;
+	cache_switch_t *p_cache_sw;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	if (!p_mgr->cache_valid)
+		goto Exit;
+
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {
+
+		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
+
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Caching dropped switch lid %u\n", lid_ho);
+
+		if (!p_node->sw) {
+			/* something is wrong - forget about cache */
+			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
+				"ERR AD03: no switch info for node lid %u - "
+				"clearing cache\n", lid_ho);
+			osm_ucast_cache_invalidate(p_mgr);
+			goto Exit;
+		}
+
+		/* unlink (add to cache) all the ports of this switch */
+		max_ports = osm_node_get_num_physp(p_node);
+		for (port_num = 1; port_num < max_ports; port_num++) {
+
+			p_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (!p_physp || !p_physp->p_remote_physp)
+				continue;
+
+			osm_ucast_cache_add_link(p_mgr, p_physp,
+						 p_physp->p_remote_physp);
+		}
+
+		/*
+		 * All the ports have been dropped (cached).
+		 * If one of the ports was connected to CA/RTR,
+		 * then the cached switch would be marked as leaf.
+		 * If it isn't, then the dropped switch isn't a leaf,
+		 * and cache can't handle it.
+		 */
+
+		p_cache_sw = __cache_get_sw(p_mgr, lid_ho);
+		CL_ASSERT(p_cache_sw);
+
+		if (!__cache_sw_is_leaf(p_cache_sw)) {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+				"Dropped non-leaf switch (lid %u) - "
+				"cache is invalid\n", lid_ho);
+			osm_ucast_cache_invalidate(p_mgr);
+			goto Exit;
+		}
+
+		p_cache_sw->dropped = TRUE;
+
+		if (!p_node->sw->num_hops || !p_node->sw->hops) {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+				"No LID matrices for switch lid %u - "
+				"cache is invalid\n", lid_ho);
+			osm_ucast_cache_invalidate(p_mgr);
+			goto Exit;
+		}
+
+		/* lid matrices */
+
+		p_cache_sw->num_hops = p_node->sw->num_hops;
+		p_node->sw->num_hops = 0;
+		p_cache_sw->hops = p_node->sw->hops;
+		p_node->sw->hops = NULL;
+
+		/* linear forwarding table */
+
+		if (p_node->sw->new_lft) {
+			/* LFT buffer exists - we use it, because
+			   it is more updated than the switch's LFT */
+			p_cache_sw->lft = p_node->sw->new_lft;
+			p_node->sw->new_lft = NULL;
+		} else {
+			/* no LFT buffer, so we use the switch's LFT */
+			p_cache_sw->lft = p_node->sw->lft;
+			p_node->sw->lft = NULL;
+		}
+		p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho;
+	} else {
+		/* dropping CA/RTR: add to cache all the ports of this node */
+		max_ports = osm_node_get_num_physp(p_node);
+		for (port_num = 1; port_num < max_ports; port_num++) {
+
+			p_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (!p_physp || !p_physp->p_remote_physp)
+				continue;
+
+			CL_ASSERT(osm_node_get_type
+				  (p_physp->p_remote_physp->p_node) ==
+				  IB_NODE_TYPE_SWITCH);
+
+			osm_ucast_cache_add_link(p_mgr,
+						 p_physp->p_remote_physp,
+						 p_physp);
+		}
+	}
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}				/* osm_ucast_cache_add_node() */
+
+/**********************************************************************
+ **********************************************************************/
+
+int osm_ucast_cache_process(osm_ucast_mgr_t * p_mgr)
+{
+	cl_qmap_t *tbl = &p_mgr->p_subn->sw_guid_tbl;
+	cl_map_item_t *item;
+	osm_switch_t *p_sw;
+
+	if (!p_mgr->p_subn->opt.use_ucast_cache)
+		return 1;
+
+	ucast_cache_validate(p_mgr);
+	if (!p_mgr->cache_valid)
+		return 1;
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+		"Configuring switch tables using cached routing\n");
+
+	for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *) item;
+
+		if (p_sw->need_update && !p_sw->new_lft) {
+			/* no new routing was recently calculated for this
+			   switch, but the LFT needs to be updated anyway */
+			p_sw->new_lft = p_sw->lft;
+			p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);
+			if (!p_sw->lft)
+				return IB_INSUFFICIENT_MEMORY;
+			memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+		}
+
+		osm_ucast_mgr_set_fwd_table(p_mgr, p_sw);
+	}
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
diff --git a/opensm/osm_ucast_file.c b/opensm/osm_ucast_file.c
new file mode 100644
index 0000000..2505c46
--- /dev/null
+++ b/opensm/osm_ucast_file.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2006,2007 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2008      Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM unicast routing module which loads
+ *    routes from the dump file
+ */
+
+#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_get_port_by_guid(&p_osm->subn, guid);
+	if (!p_port) {
+		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+			"cannot find port guid 0x%016" PRIx64
+			" , will use the same lid\n", cl_ntoh64(guid));
+		return lid;
+	}
+
+	osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
+	if (min_lid <= lid && lid <= max_lid)
+		return lid;
+
+	lmc = osm_port_get_lmc(p_port);
+	return min_lid + (lid & ((1 << lmc) - 1));
+}
+
+static void add_path(osm_opensm_t * p_osm,
+		     osm_switch_t * p_sw, uint16_t lid, uint8_t port_num,
+		     ib_net64_t port_guid)
+{
+	uint16_t new_lid;
+	uint8_t old_port;
+
+	new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid;
+	old_port = osm_switch_get_port_by_lid(p_sw, new_lid);
+	if (old_port != OSM_NO_PATH && old_port != port_num) {
+		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+			"LID collision is detected on switch "
+			"0x016%" PRIx64 ", will overwrite LID %u entry\n",
+			cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)),
+			new_lid);
+	}
+
+	p_sw->new_lft[new_lid] = port_num;
+	if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid &&
+	      osm_get_switch_by_guid(&p_osm->subn, port_guid)))
+		osm_switch_count_path(p_sw, port_num);
+
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+		"route 0x%04x(was 0x%04x) %u 0x%016" PRIx64
+		" is added to switch 0x%016" PRIx64 "\n",
+		new_lid, lid, port_num, cl_ntoh64(port_guid),
+		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
+}
+
+static void add_lid_hops(osm_opensm_t * p_osm, osm_switch_t * p_sw,
+			 uint16_t lid, ib_net64_t guid,
+			 uint8_t hops[], unsigned len)
+{
+	uint16_t new_lid;
+	uint8_t i;
+
+	new_lid = guid ? remap_lid(p_osm, lid, guid) : lid;
+	if (len > p_sw->num_ports)
+		len = p_sw->num_ports;
+
+	for (i = 0; i < len; i++)
+		osm_switch_set_hops(p_sw, lid, i, hops[i]);
+}
+
+static int do_ucast_file_load(void *context)
+{
+	char line[1024];
+	char *file_name;
+	FILE *file;
+	ib_net64_t sw_guid, port_guid;
+	osm_opensm_t *p_osm = context;
+	osm_switch_t *p_sw;
+	uint16_t lid;
+	uint8_t port_num;
+	unsigned lineno;
+
+	file_name = p_osm->subn.opt.lfts_file;
+	if (!file_name) {
+		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+			"LFTs file name is not given; "
+			"using default routing algorithm\n");
+		return 1;
+	}
+
+	file = fopen(file_name, "r");
+	if (!file) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6302: "
+			"cannot open ucast dump file \'%s\': %m\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,
+				"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,
+					"cannot find switch %016" PRIx64 "\n",
+					cl_ntoh64(sw_guid));
+				continue;
+			}
+			memset(p_sw->new_lft, OSM_NO_PATH,
+			       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_VERBOSE,
+			"lid matrix file name is not given; "
+			"using default lid matrix generation algorithm\n");
+		return 1;
+	}
+
+	file = fopen(file_name, "r");
+	if (!file) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6305: "
+			"cannot open lid matrix file \'%s\': %m\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,
+					"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(struct osm_routing_engine *r, osm_opensm_t *osm)
+{
+	r->context = osm;
+	r->build_lid_matrices = do_lid_matrix_file_load;
+	r->ucast_build_fwd_tables = do_ucast_file_load;
+	return 0;
+}
diff --git a/opensm/osm_ucast_ftree.c b/opensm/osm_ucast_ftree.c
new file mode 100644
index 0000000..aa51d23
--- /dev/null
+++ b/opensm/osm_ucast_ftree.c
@@ -0,0 +1,3669 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM FatTree routing
+ */
+
+#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_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 paths,
+ *    so no need to use FatTree routing.
+ *  - Why maximum rank is 8:
+ *    Each node (switch) is assigned a unique tuple.
+ *    Switches are stored in two cl_qmaps - one is
+ *    ordered by guid, and the other by a key that is
+ *    generated from tuple. Since cl_qmap supports only
+ *    a 64-bit key, the maximal tuple 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;
+
+struct guid_list_item {
+	cl_list_item_t list;
+	uint64_t guid;
+};
+
+/***************************************************
+ **
+ **  ftree_sw_table_element_t definition
+ **
+ ***************************************************/
+
+typedef struct {
+	cl_map_item_t map_item;
+	struct ftree_sw_t_ *p_sw;
+} ftree_sw_tbl_element_t;
+
+/***************************************************
+ **
+ **  ftree_port_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_port_t_ {
+	cl_map_item_t map_item;
+	uint8_t port_num;	/* port number on the current node */
+	uint8_t remote_port_num;	/* port number on the remote node */
+	uint32_t counter_up;	/* number of allocated routs upwards */
+	uint32_t counter_down;	/* number of allocated routs downwards */
+} ftree_port_t;
+
+/***************************************************
+ **
+ **  ftree_port_group_t definition
+ **
+ ***************************************************/
+
+typedef union ftree_hca_or_sw_ {
+	struct ftree_hca_t_ *p_hca;
+	struct ftree_sw_t_ *p_sw;
+} ftree_hca_or_sw;
+
+typedef struct ftree_port_group_t_ {
+	cl_map_item_t map_item;
+	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 node_guid;	/* this node's guid */
+	uint8_t node_type;	/* this node's type */
+	ib_net64_t remote_port_guid;	/* port guid of the remote port */
+	ib_net64_t remote_node_guid;	/* node guid of the remote node */
+	uint8_t remote_node_type;	/* IB_NODE_TYPE_{CA,SWITCH,ROUTER,...} */
+	ftree_hca_or_sw hca_or_sw;	/* pointer to this hca/switch */
+	ftree_hca_or_sw remote_hca_or_sw;	/* pointer to remote hca/switch */
+	cl_ptr_vector_t ports;	/* vector of ports to the same lid */
+	boolean_t is_cn;	/* whether this port is a compute node */
+	uint32_t counter_down;	/* number of allocated routs downwards */
+} ftree_port_group_t;
+
+/***************************************************
+ **
+ **  ftree_sw_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_sw_t_ {
+	cl_map_item_t map_item;
+	osm_switch_t *p_osm_sw;
+	uint32_t rank;
+	ftree_tuple_t tuple;
+	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;
+	boolean_t is_leaf;
+	int down_port_groups_idx;
+} 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;
+	unsigned cn_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;
+	cl_qlist_t root_guid_list;
+	cl_qmap_t cn_guid_tbl;
+	unsigned cn_num;
+	uint8_t leaf_switch_rank;
+	uint8_t max_switch_rank;
+	ftree_sw_t **leaf_switches;
+	uint32_t leaf_switches_num;
+	uint16_t max_cn_per_leaf;
+	uint16_t lft_max_lid_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.
+						   p_sw),
+						  &((*pp_g2)->remote_hca_or_sw.
+						    p_sw));
+}
+
+/***************************************************
+ **
+ ** 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));
+
+	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 port_guid,
+			      IN ib_net64_t node_guid,
+			      IN uint8_t node_type,
+		              IN void *p_hca_or_sw,
+			      IN ib_net64_t remote_port_guid,
+			      IN ib_net64_t remote_node_guid,
+			      IN uint8_t remote_node_type,
+			      IN void *p_remote_hca_or_sw,
+			      IN boolean_t is_cn)
+{
+	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, &port_guid, sizeof(ib_net64_t));
+	memcpy(&p_group->node_guid, &node_guid, sizeof(ib_net64_t));
+	memcpy(&p_group->remote_port_guid, &remote_port_guid,
+	       sizeof(ib_net64_t));
+	memcpy(&p_group->remote_node_guid, &remote_node_guid,
+	       sizeof(ib_net64_t));
+
+	p_group->node_type = node_type;
+	switch (node_type) {
+	case IB_NODE_TYPE_CA:
+		p_group->hca_or_sw.p_hca = (ftree_hca_t *) p_hca_or_sw;
+		break;
+	case IB_NODE_TYPE_SWITCH:
+		p_group->hca_or_sw.p_sw = (ftree_sw_t *) p_hca_or_sw;
+		break;
+	default:
+		/* we shouldn't get here - port is created only in hca or switch */
+		CL_ASSERT(0);
+	}
+
+	p_group->remote_node_type = remote_node_type;
+	switch (remote_node_type) {
+	case IB_NODE_TYPE_CA:
+		p_group->remote_hca_or_sw.p_hca =
+		    (ftree_hca_t *) p_remote_hca_or_sw;
+		break;
+	case IB_NODE_TYPE_SWITCH:
+		p_group->remote_hca_or_sw.p_sw =
+		    (ftree_sw_t *) p_remote_hca_or_sw;
+		break;
+	default:
+		/* we shouldn't get here - port is created only in hca or switch */
+		CL_ASSERT(0);
+	}
+
+	cl_ptr_vector_init(&p_group->ports, 0,	/* min size */
+			   8);	/* grow size */
+	p_group->is_cn = is_cn;
+	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,
+		"    Port Group of size %u, port(s): %s, direction: %s\n"
+		"                  Local <--> Remote GUID (LID):"
+		"0x%016" PRIx64 " (0x%04x) <--> 0x%016" PRIx64 " (0x%04x)\n",
+		size,
+		buff,
+		(direction == FTREE_DIRECTION_DOWN) ? "DOWN" : "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 (p_osm_sw->num_ports == 1)
+		return NULL;
+
+	p_sw = (ftree_sw_t *) malloc(sizeof(ftree_sw_t));
+	if (p_sw == NULL)
+		return NULL;
+	memset(p_sw, 0, sizeof(ftree_sw_t));
+
+	p_sw->p_osm_sw = p_osm_sw;
+	p_sw->rank = 0xFFFFFFFF;
+	__osm_ftree_tuple_init(p_sw->tuple);
+
+	p_sw->base_lid = osm_node_get_base_lid(p_sw->p_osm_sw->p_node, 0);
+
+	ports_num = osm_node_get_num_physp(p_sw->p_osm_sw->p_node);
+	p_sw->down_port_groups =
+	    (ftree_port_group_t **) malloc(ports_num *
+					   sizeof(ftree_port_group_t *));
+	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 */
+	memset(p_osm_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+	p_sw->down_port_groups_idx = -1;
+
+	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);
+
+	free(p_sw);
+}				/* __osm_ftree_sw_destroy() */
+
+/***************************************************/
+
+static uint64_t __osm_ftree_sw_get_guid_no(IN ftree_sw_t * p_sw)
+{
+	if (!p_sw)
+		return 0;
+	return osm_node_get_node_guid(p_sw->p_osm_sw->p_node);
+}
+
+/***************************************************/
+
+static uint64_t __osm_ftree_sw_get_guid_ho(IN ftree_sw_t * p_sw)
+{
+	return cl_ntoh64(__osm_ftree_sw_get_guid_no(p_sw));
+}
+
+/***************************************************/
+
+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,
+		"Switch index: %s, GUID: 0x%016" PRIx64
+		", Ports: %u DOWN, %u UP\n",
+		__osm_ftree_tuple_to_str(p_sw->tuple),
+		__osm_ftree_sw_get_guid_ho(p_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 != 0xFFFFFFFF);
+}
+
+/***************************************************/
+
+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,
+							__osm_ftree_sw_get_guid_no
+							(p_sw),
+							IB_NODE_TYPE_SWITCH,
+							p_sw, remote_port_guid,
+							remote_node_guid,
+							remote_node_type,
+							p_remote_hca_or_sw,
+							FALSE);
+		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 cl_status_t
+__osm_ftree_sw_set_hops(IN ftree_sw_t * p_sw,
+			IN uint16_t lid_ho, IN uint8_t port_num,
+			IN uint8_t hops)
+{
+	/* 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 uint64_t __osm_ftree_hca_get_guid_no(IN ftree_hca_t * p_hca)
+{
+	if (!p_hca)
+		return 0;
+	return osm_node_get_node_guid(p_hca->p_osm_node);
+}
+
+/***************************************************/
+
+static uint64_t __osm_ftree_hca_get_guid_ho(IN ftree_hca_t * p_hca)
+{
+	return cl_ntoh64(__osm_ftree_hca_get_guid_no(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,
+		"CA GUID: 0x%016" PRIx64 ", Ports: %u UP\n",
+		__osm_ftree_hca_get_guid_ho(p_hca), 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, IN boolean_t is_cn)
+{
+	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,
+							__osm_ftree_hca_get_guid_no
+							(p_hca),
+							IB_NODE_TYPE_CA, p_hca,
+							remote_port_guid,
+							remote_node_guid,
+							remote_node_type,
+							p_remote_hca_or_sw,
+							is_cn);
+		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()
+{
+	ftree_fabric_t *p_ftree =
+	    (ftree_fabric_t *) malloc(sizeof(ftree_fabric_t));
+	if (p_ftree == NULL)
+		return NULL;
+
+	memset(p_ftree, 0, sizeof(ftree_fabric_t));
+
+	cl_qmap_init(&p_ftree->hca_tbl);
+	cl_qmap_init(&p_ftree->sw_tbl);
+	cl_qmap_init(&p_ftree->sw_by_tuple_tbl);
+	cl_qmap_init(&p_ftree->cn_guid_tbl);
+
+	cl_qlist_init(&p_ftree->root_guid_list);
+
+	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;
+	name_map_item_t *p_guid_element, *p_next_guid_element;
+
+	if (!p_ftree)
+		return;
+
+	/* remove all the elements of hca_tbl */
+
+	p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+	while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) {
+		p_hca = p_next_hca;
+		p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item);
+		__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);
+
+	/* remove all the elements of cn_guid_tbl */
+	p_next_guid_element =
+	    (name_map_item_t *) cl_qmap_head(&p_ftree->cn_guid_tbl);
+	while (p_next_guid_element !=
+	       (name_map_item_t *) cl_qmap_end(&p_ftree->cn_guid_tbl)) {
+		p_guid_element = p_next_guid_element;
+		p_next_guid_element =
+		    (name_map_item_t *) cl_qmap_next(&p_guid_element->item);
+		free(p_guid_element);
+	}
+	cl_qmap_remove_all(&p_ftree->cn_guid_tbl);
+
+	/* remove all the elements of root_guid_list */
+	while (!cl_is_qlist_empty(&p_ftree->root_guid_list))
+		free(cl_qlist_remove_head(&p_ftree->root_guid_list));
+
+	/* free the leaf switches array */
+	if ((p_ftree->leaf_switches_num > 0) && (p_ftree->leaf_switches))
+		free(p_ftree->leaf_switches);
+
+	p_ftree->leaf_switches_num = 0;
+	p_ftree->cn_num = 0;
+	p_ftree->leaf_switch_rank = 0;
+	p_ftree->max_switch_rank = 0;
+	p_ftree->max_cn_per_leaf = 0;
+	p_ftree->lft_max_lid_ho = 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);
+	free(p_ftree);
+}
+
+/***************************************************/
+
+static uint8_t __osm_ftree_fabric_get_rank(ftree_fabric_t * p_ftree)
+{
+	return p_ftree->leaf_switch_rank + 1;
+}
+
+/***************************************************/
+
+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 ftree_sw_t *__osm_ftree_fabric_get_sw_by_guid(IN ftree_fabric_t *
+						     p_ftree, IN uint64_t guid)
+{
+	ftree_sw_t *p_sw;
+	p_sw = (ftree_sw_t *) cl_qmap_get(&p_ftree->sw_tbl, guid);
+	if (p_sw == (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl))
+		return NULL;
+	return p_sw;
+}
+
+/***************************************************/
+
+static ftree_hca_t *__osm_ftree_fabric_get_hca_by_guid(IN ftree_fabric_t *
+						       p_ftree,
+						       IN uint64_t guid)
+{
+	ftree_hca_t *p_hca;
+	p_hca = (ftree_hca_t *) cl_qmap_get(&p_ftree->hca_tbl, guid);
+	if (p_hca == (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl))
+		return NULL;
+	return p_hca;
+}
+
+/***************************************************/
+
+static void __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, "\n"
+		"                       |-------------------------------|\n"
+		"                       |-  Full fabric topology dump  -|\n"
+		"                       |-------------------------------|\n\n");
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "-- CAs:\n");
+
+	for (p_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+	     p_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl);
+	     p_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item)) {
+		__osm_ftree_hca_dump(p_ftree, p_hca);
+	}
+
+	for (i = 0; i < p_ftree->max_switch_rank; i++) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"-- Rank %u switches\n", i);
+		for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl);
+		     p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl);
+		     p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) {
+			if (p_sw->rank == i)
+				__osm_ftree_sw_dump(p_ftree, p_sw);
+		}
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "\n"
+		"                       |---------------------------------------|\n"
+		"                       |- Full fabric topology dump completed -|\n"
+		"                       |---------------------------------------|\n\n");
+}				/* __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;
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"General fabric topology info\n");
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"============================\n");
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"  - FatTree rank (roots to leaf switches): %u\n",
+		p_ftree->leaf_switch_rank + 1);
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"  - FatTree max switch rank: %u\n", p_ftree->max_switch_rank);
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"  - Fabric has %u CAs (%u of them CNs), %u switches\n",
+		cl_qmap_count(&p_ftree->hca_tbl), p_ftree->cn_num,
+		cl_qmap_count(&p_ftree->sw_tbl));
+
+	CL_ASSERT(cl_qmap_count(&p_ftree->hca_tbl) >= p_ftree->cn_num);
+
+	for (i = 0; i <= p_ftree->max_switch_rank; i++) {
+		j = 0;
+		for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl);
+		     p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl);
+		     p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) {
+			if (p_sw->rank == i)
+				j++;
+		}
+		if (i == 0)
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+				"  - Fabric has %u switches at rank %u (roots)\n",
+				j, i);
+		else if (i == p_ftree->leaf_switch_rank)
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+				"  - Fabric has %u switches at rank %u (%u of them leafs)\n",
+				j, i, p_ftree->leaf_switches_num);
+		else
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+				"  - Fabric has %u switches at rank %u\n", j,
+				i);
+	}
+
+	if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_VERBOSE)) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+			"  - Root switches:\n");
+		for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl);
+		     p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl);
+		     p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) {
+			if (p_sw->rank == 0)
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+					"      GUID: 0x%016" PRIx64
+					", LID: %u, Index %s\n",
+					__osm_ftree_sw_get_guid_ho(p_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,
+			"  - Leaf switches (sorted by index):\n");
+		for (i = 0; i < p_ftree->leaf_switches_num; i++) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+				"      GUID: 0x%016" PRIx64
+				", LID: %u, Index %s\n",
+				__osm_ftree_sw_get_guid_ho(p_ftree->
+							   leaf_switches[i]),
+				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_on_sw;
+	ftree_port_group_t *p_group_on_hca;
+	uint32_t i;
+	uint32_t j;
+	unsigned printed_hcas_on_leaf;
+
+	char path[1024];
+	FILE *p_hca_ordering_file;
+	char *filename = "opensm-ftree-ca-order.dump";
+
+	snprintf(path, sizeof(path), "%s/%s",
+		 p_ftree->p_osm->subn.opt.dump_files_dir, filename);
+	p_hca_ordering_file = fopen(path, "w");
+	if (!p_hca_ordering_file) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB01: "
+			"cannot open file \'%s\': %s\n", filename,
+			strerror(errno));
+		return;
+	}
+
+	/* for each leaf switch (in indexing order) */
+	for (i = 0; i < p_ftree->leaf_switches_num; i++) {
+		p_sw = p_ftree->leaf_switches[i];
+		printed_hcas_on_leaf = 0;
+
+		/* for each real CA (CNs and not) connected to this switch */
+		for (j = 0; j < p_sw->down_port_groups_num; j++) {
+			p_group_on_sw = p_sw->down_port_groups[j];
+
+			if (p_group_on_sw->remote_node_type != IB_NODE_TYPE_CA)
+				continue;
+
+			p_hca = p_group_on_sw->remote_hca_or_sw.p_hca;
+			p_group_on_hca =
+			    __osm_ftree_hca_get_port_group_by_remote_lid(p_hca,
+									 p_group_on_sw->
+									 base_lid);
+
+			/* treat non-compute nodes as dummies */
+			if (!p_group_on_hca->is_cn)
+				continue;
+
+			fprintf(p_hca_ordering_file, "0x%04x\t%s\n",
+				cl_ntoh16(p_group_on_hca->base_lid),
+				p_hca->p_osm_node->print_desc);
+
+			printed_hcas_on_leaf++;
+		}
+
+		/* now print missing HCAs */
+		for (j = 0;
+		     j < (p_ftree->max_cn_per_leaf - printed_hcas_on_leaf); j++)
+			fprintf(p_hca_ordering_file, "0xFFFF\tDUMMY\n");
+
+	}
+	/* done going through all the leaf switches */
+
+	fclose(p_hca_ordering_file);
+}				/* __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] = (uint8_t) 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 inline boolean_t __osm_ftree_fabric_roots_provided(IN ftree_fabric_t *
+							  p_ftree)
+{
+	return (p_ftree->p_osm->subn.opt.root_guid_file != NULL);
+}
+
+/***************************************************/
+
+static inline boolean_t __osm_ftree_fabric_cns_provided(IN ftree_fabric_t *
+							p_ftree)
+{
+	return (p_ftree->p_osm->subn.opt.cn_guid_file != NULL);
+}
+
+/***************************************************/
+
+static int __osm_ftree_fabric_mark_leaf_switches(IN ftree_fabric_t * p_ftree)
+{
+	ftree_sw_t *p_sw;
+	ftree_hca_t *p_hca;
+	ftree_hca_t *p_next_hca;
+	unsigned i;
+	int res = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Marking leaf switches in fabric\n");
+
+	/* Scan all the CAs, if they have CNs - find CN port and mark switch
+	   that is connected to this port as leaf switch.
+	   Also, ensure that this marked leaf has rank of p_ftree->leaf_switch_rank. */
+	p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+	while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) {
+		p_hca = p_next_hca;
+		p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item);
+		if (!p_hca->cn_num)
+			continue;
+
+		for (i = 0; i < p_hca->up_port_groups_num; i++) {
+			if (!p_hca->up_port_groups[i]->is_cn)
+				continue;
+
+			/* In CAs, port group alway has one port, and since this
+			   port group is CN, we know that this port is compute node */
+			CL_ASSERT(p_hca->up_port_groups[i]->remote_node_type ==
+				  IB_NODE_TYPE_SWITCH);
+			p_sw = p_hca->up_port_groups[i]->remote_hca_or_sw.p_sw;
+
+			/* check if this switch was already processed */
+			if (p_sw->is_leaf)
+				continue;
+			p_sw->is_leaf = TRUE;
+
+			/* ensure that this leaf switch is at the correct tree level */
+			if (p_sw->rank != p_ftree->leaf_switch_rank) {
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB26: CN port 0x%" PRIx64
+					" is connected to switch 0x%" PRIx64
+					" with rank %u, "
+					"while FatTree leaf rank is %u\n",
+					cl_ntoh64(p_hca->up_port_groups[i]->
+						  port_guid),
+					__osm_ftree_sw_get_guid_ho(p_sw),
+					p_sw->rank, p_ftree->leaf_switch_rank);
+				res = -1;
+				goto Exit;
+
+			}
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_fabric_mark_leaf_switches() */
+
+/***************************************************/
+
+static void __osm_ftree_fabric_make_indexing(IN ftree_fabric_t * p_ftree)
+{
+	ftree_sw_t *p_remote_sw;
+	ftree_sw_t *p_sw = NULL;
+	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_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Starting FatTree indexing\n");
+
+	/* using the first leaf switch 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->is_leaf)
+			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,
+		"Indexing starting point:\n"
+		"                                            - Switch rank  : %u\n"
+		"                                            - Switch index : %s\n"
+		"                                            - Node LID     : %u\n"
+		"                                            - Node GUID    : 0x%016"
+		PRIx64 "\n", p_sw->rank, __osm_ftree_tuple_to_str(p_sw->tuple),
+		cl_ntoh16(p_sw->base_lid), __osm_ftree_sw_get_guid_ho(p_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 >= p_ftree->leaf_switch_rank) {
+			/* whether downward ports are pointing to CAs or switches,
+			   we don't assign indexes to switches that are located
+			   lower than leaf switches */
+		} else {
+			/* This is not the leaf switch */
+			for (i = 0; i < p_sw->down_port_groups_num; i++) {
+				/* Work with port groups that are pointing to switches only.
+				   No need to assign indexing to HCAs */
+				if (p_sw->down_port_groups[i]->
+				    remote_node_type != IB_NODE_TYPE_SWITCH)
+					continue;
+
+				p_remote_sw =
+				    p_sw->down_port_groups[i]->remote_hca_or_sw.
+				    p_sw;
+				if (__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.
+				    p_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 */
+	}
+	cl_list_destroy(&bfs_list);
+
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+}				/* __osm_ftree_fabric_make_indexing() */
+
+/***************************************************/
+
+static int __osm_ftree_fabric_create_leaf_switch_array(IN ftree_fabric_t *
+						       p_ftree)
+{
+	ftree_sw_t *p_sw;
+	ftree_sw_t *p_next_sw;
+	ftree_sw_t **all_switches_at_leaf_level;
+	unsigned i;
+	unsigned all_leaf_idx = 0;
+	unsigned first_leaf_idx;
+	unsigned last_leaf_idx;
+	int res = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	/* create array of ALL the switches that have leaf rank */
+	all_switches_at_leaf_level = (ftree_sw_t **)
+	    malloc(cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *));
+	if (!all_switches_at_leaf_level) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fat-tree routing: Memory allocation failed\n");
+		res = -1;
+		goto Exit;
+	}
+	memset(all_switches_at_leaf_level, 0,
+	       cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *));
+
+	p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl);
+	while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item);
+		if (p_sw->rank == p_ftree->leaf_switch_rank) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Adding switch 0x%" PRIx64
+				" to full leaf switch array\n",
+				__osm_ftree_sw_get_guid_ho(p_sw));
+			all_switches_at_leaf_level[all_leaf_idx++] = p_sw;
+
+		}
+	}
+
+	/* quick-sort array of leaf switches by index */
+	qsort(all_switches_at_leaf_level,	/* array */
+	      all_leaf_idx,	/* number of elements */
+	      sizeof(ftree_sw_t *),	/* size of each element */
+	      __osm_ftree_compare_switches_by_index);	/* comparator */
+
+	/* check the first and the last REAL leaf (the one
+	   that has CNs) in the array of all the leafs */
+
+	first_leaf_idx = all_leaf_idx;
+	last_leaf_idx = 0;
+	for (i = 0; i < all_leaf_idx; i++) {
+		if (all_switches_at_leaf_level[i]->is_leaf) {
+			if (i < first_leaf_idx)
+				first_leaf_idx = i;
+			last_leaf_idx = i;
+		}
+	}
+	CL_ASSERT(first_leaf_idx < last_leaf_idx);
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+		"Full leaf array info: first_leaf_idx = %u, last_leaf_idx = %u\n",
+		first_leaf_idx, last_leaf_idx);
+
+	/* Create array of REAL leaf switches, sorted by index.
+	   This array may contain switches at the same rank w/o CNs,
+	   in case this is the order of indexing. */
+	p_ftree->leaf_switches_num = last_leaf_idx - first_leaf_idx + 1;
+	p_ftree->leaf_switches = (ftree_sw_t **)
+	    malloc(p_ftree->leaf_switches_num * sizeof(ftree_sw_t *));
+	if (!p_ftree->leaf_switches) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fat-tree routing: Memory allocation failed\n");
+		res = -1;
+		goto Exit;
+	}
+
+	memcpy(p_ftree->leaf_switches,
+	       &(all_switches_at_leaf_level[first_leaf_idx]),
+	       p_ftree->leaf_switches_num * sizeof(ftree_sw_t *));
+
+	free(all_switches_at_leaf_level);
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+		"Created array of %u leaf switches\n",
+		p_ftree->leaf_switches_num);
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_fabric_create_leaf_switch_array() */
+
+/***************************************************/
+
+static void __osm_ftree_fabric_set_max_cn_per_leaf(IN ftree_fabric_t * p_ftree)
+{
+	unsigned i;
+	unsigned j;
+	unsigned cns_on_this_leaf;
+	ftree_sw_t *p_sw;
+	ftree_port_group_t *p_group;
+
+	for (i = 0; i < p_ftree->leaf_switches_num; i++) {
+		p_sw = p_ftree->leaf_switches[i];
+		cns_on_this_leaf = 0;
+		for (j = 0; j < p_sw->down_port_groups_num; j++) {
+			p_group = p_sw->down_port_groups[j];
+			if (p_group->remote_node_type != IB_NODE_TYPE_CA)
+				continue;
+			cns_on_this_leaf +=
+			    p_group->remote_hca_or_sw.p_hca->cn_num;
+		}
+		if (cns_on_this_leaf > p_ftree->max_cn_per_leaf)
+			p_ftree->max_cn_per_leaf = cns_on_this_leaf;
+	}
+}				/* __osm_ftree_fabric_set_max_cn_per_leaf() */
+
+/***************************************************/
+
+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_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Validating fabric topology\n");
+
+	reference_sw_arr =
+	    (ftree_sw_t **) malloc(tree_rank * sizeof(ftree_sw_t *));
+	if (reference_sw_arr == NULL) {
+		osm_log(&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,
+					"ERR AB09: Different number of upward port groups on switches:\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, Index %s - %u groups\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, Index %s - %u groups\n",
+					__osm_ftree_sw_get_guid_ho
+					(reference_sw_arr[p_sw->rank]),
+					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,
+					__osm_ftree_sw_get_guid_ho(p_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 != (tree_rank - 1) &&
+			    reference_sw_arr[p_sw->rank]->
+			    down_port_groups_num !=
+			    p_sw->down_port_groups_num) {
+				/* we're allowing some hca's to be missing */
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB0A: Different number of downward port groups on switches:\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, Index %s - %u port groups\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, Index %s - %u port groups\n",
+					__osm_ftree_sw_get_guid_ho
+					(reference_sw_arr[p_sw->rank]),
+					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,
+					__osm_ftree_sw_get_guid_ho(p_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,
+							"ERR AB0B: Different number of ports in an upward port group on switches:\n"
+							"       GUID 0x%016"
+							PRIx64
+							", LID %u, Index %s - %u ports\n"
+							"       GUID 0x%016"
+							PRIx64
+							", LID %u, Index %s - %u ports\n",
+							__osm_ftree_sw_get_guid_ho
+							(reference_sw_arr
+							 [p_sw->rank]),
+							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),
+							__osm_ftree_sw_get_guid_ho
+							(p_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,
+							"ERR AB0C: Different number of ports in an downward port group on switches:\n"
+							"       GUID 0x%016"
+							PRIx64
+							", LID %u, Index %s - %u ports\n"
+							"       GUID 0x%016"
+							PRIx64
+							", LID %u, Index %s - %u ports\n",
+							__osm_ftree_sw_get_guid_ho
+							(reference_sw_arr
+							 [p_sw->rank]),
+							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),
+							__osm_ftree_sw_get_guid_ho
+							(p_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,
+			"Fabric topology has been identified as FatTree\n");
+	else
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+			"ERR AB0D: Fabric topology hasn't been identified as FatTree\n");
+
+	free(reference_sw_arr);
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __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;
+
+	p_sw->p_osm_sw->max_lid_ho = p_ftree->lft_max_lid_ho;
+	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;
+	uint16_t k;
+
+	/* we shouldn't enter here if both real_lid and main_path are false */
+	CL_ASSERT(is_real_lid || is_main_path);
+
+	/* if there is no down-going ports */
+	if (p_sw->down_port_groups_num == 0)
+		return;
+
+	/* promote the index that indicates which group should we
+	   start with when going through all the downgoing groups */
+	p_sw->down_port_groups_idx =
+		(p_sw->down_port_groups_idx + 1) % p_sw->down_port_groups_num;
+
+	/* foreach down-going port group (in indexing order) */
+	i = p_sw->down_port_groups_idx;
+	for (k = 0; k < p_sw->down_port_groups_num; k++) {
+
+		p_group = p_sw->down_port_groups[i];
+		i = (i + 1) % p_sw->down_port_groups_num;
+
+		/* Skip this port group unless it points to a switch */
+		if (p_group->remote_node_type != IB_NODE_TYPE_SWITCH)
+			continue;
+
+		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.p_sw;
+
+		if (osm_switch_get_least_hops(p_remote_sw->p_osm_sw,
+					      cl_ntoh16(target_lid)) !=
+		    OSM_NO_PATH) {
+			/* Loop in the fabric - we already routed the remote switch
+			   on our way UP, and now we see it again on our way DOWN */
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Loop of lenght %d in the fabric:\n                             "
+				"Switch %s (LID %u) closes loop through switch %s (LID %u)\n",
+				(p_remote_sw->rank - highest_rank_in_route) * 2,
+				__osm_ftree_tuple_to_str(p_remote_sw->tuple),
+				cl_ntoh16(p_group->base_lid),
+				__osm_ftree_tuple_to_str(p_sw->tuple),
+				cl_ntoh16(p_group->remote_base_lid));
+			continue;
+		}
+
+		/* 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 (lower) 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 (lower)
+		   switch has been already configured for this target LID */
+		if (is_real_lid && !is_main_path &&
+		    p_remote_sw->p_osm_sw->new_lft[cl_ntoh16(target_lid)] != OSM_NO_PATH)
+			continue;
+
+		/* setting fwd tbl port only if this is real LID */
+		if (is_real_lid) {
+			p_remote_sw->p_osm_sw->new_lft[cl_ntoh16(target_lid)] =
+				p_min_port->remote_port_num;
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Switch %s: set path to CA LID %u through port %u\n",
+				__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,
+							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 */
+		__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-ascending-up
+ * Given   : a switch and a LID
+ * Pseudo code:
+ *    find the least loaded port of all the upgoing groups (scan in indexing order)
+ *    assign the LFT(LID) of remote switch to that port
+ *    track that port usage
+ *    assign-up-going-port-by-descending-down on CURRENT switch
+ *    assign-down-going-port-by-ascending-up on REMOTE switch (recursion)
+ */
+
+static 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);
+
+	/* Assign upgoing ports by stepping down, starting on THIS switch */
+	__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 upgoing port group */
+	p_min_group = NULL;
+	for (i = 0; i < p_sw->up_port_groups_num; i++) {
+		p_group = p_sw->up_port_groups[i];
+		if (!p_min_group) {
+			/* first group that we're checking - use
+			   it as a group with the lowest load */
+			p_min_group = p_group;
+		} else if (p_group->counter_down < p_min_group->counter_down) {
+			/* this group is less loaded - use it as min */
+			p_min_group = p_group;
+		}
+	}
+
+	/* Find the least loaded upgoing port in the selected group */
+	p_min_port = NULL;
+	ports_num = (uint16_t) cl_ptr_vector_get_size(&p_min_group->ports);
+	for (j = 0; j < ports_num; j++) {
+		cl_ptr_vector_at(&p_min_group->ports, j, (void *)&p_port);
+		if (!p_min_port) {
+			/* first port that we're checking - use
+			   it as a port with the lowest load */
+			p_min_port = p_port;
+		} else if (p_port->counter_down < p_min_port->counter_down) {
+			/* this port is less loaded - use it as min */
+			p_min_port = p_port;
+		}
+	}
+
+	/* At this point we have selected a group and port with the
+	   lowest load of downgoing routes.
+	   Set on the remote switch how to get to the target_lid -
+	   set LFT(target_lid) on the remote switch to the remote port */
+	p_remote_sw = p_min_group->remote_hca_or_sw.p_sw;
+
+	/* Four possible cases:
+	 *
+	 *  1. is_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->is_leaf) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				" - Routing MAIN path for %s CA LID %u: %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_group->counter_down p_port->counter_down counters of the
+		   group and port that belong to the lower side of the link
+		   (on switch with higher rank) */
+		p_min_group->counter_down++;
+		p_min_port->counter_down++;
+		if (is_real_lid) {
+			p_remote_sw->p_osm_sw->new_lft[cl_ntoh16(target_lid)] =
+				p_min_port->remote_port_num;
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Switch %s: set path to CA LID %u through port %u\n",
+				__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,
+							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.p_sw;
+
+		/* skip if target lid has been already set on remote switch fwd tbl */
+		if (p_remote_sw->p_osm_sw->new_lft[cl_ntoh16(target_lid)] != OSM_NO_PATH)
+			continue;
+
+		if (p_sw->is_leaf) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				" - Routing SECONDARY path for LID %u: %s --> %s\n",
+				cl_ntoh16(target_lid),
+				__osm_ftree_tuple_to_str(p_sw->tuple),
+				__osm_ftree_tuple_to_str(p_remote_sw->tuple));
+		}
+
+		/* Routing REAL lids on SECONDARY path means routing
+		   switch-to-switch or switch-to-CA paths.
+		   We can safely assume that switch will initiate very
+		   few traffic, so there's no point waisting runtime on
+		   trying to balance these routes - always pick port 0. */
+
+		cl_ptr_vector_at(&p_group->ports, 0, (void *)&p_port);
+		p_remote_sw->p_osm_sw->new_lft[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,
+						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-ascending-up(TRUE,TRUE) on CURRENT switch
+ *       for each MISSING compute node
+ *          call assign-down-going-port-by-ascending-up(FALSE,TRUE) on CURRENT switch
+ */
+
+static void __osm_ftree_fabric_route_to_cns(IN ftree_fabric_t * p_ftree)
+{
+	ftree_sw_t *p_sw;
+	ftree_hca_t *p_hca;
+	ftree_port_group_t *p_leaf_port_group;
+	ftree_port_group_t *p_hca_port_group;
+	ftree_port_t *p_port;
+	uint32_t i;
+	uint32_t j;
+	ib_net16_t hca_lid;
+	unsigned routed_targets_on_leaf;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	/* for each leaf switch (in indexing order) */
+	for (i = 0; i < p_ftree->leaf_switches_num; i++) {
+		p_sw = p_ftree->leaf_switches[i];
+		routed_targets_on_leaf = 0;
+
+		/* for each HCA connected to this switch */
+		for (j = 0; j < p_sw->down_port_groups_num; j++) {
+			p_leaf_port_group = p_sw->down_port_groups[j];
+
+			/* work with this port group only if the remote node is CA */
+			if (p_leaf_port_group->remote_node_type !=
+			    IB_NODE_TYPE_CA)
+				continue;
+
+			p_hca = p_leaf_port_group->remote_hca_or_sw.p_hca;
+
+			/* work with this port group only if remote HCA has CNs */
+			if (!p_hca->cn_num)
+				continue;
+
+			p_hca_port_group =
+			    __osm_ftree_hca_get_port_group_by_remote_lid(p_hca,
+									 p_leaf_port_group->
+									 base_lid);
+			CL_ASSERT(p_hca_port_group);
+
+			/* work with this port group only if remote port is CN */
+			if (!p_hca_port_group->is_cn)
+				continue;
+
+			/* obtain the LID of HCA port */
+			hca_lid = p_leaf_port_group->remote_base_lid;
+
+			/* set local LFT(LID) to the port that is connected to HCA */
+			cl_ptr_vector_at(&p_leaf_port_group->ports, 0,
+					 (void *)&p_port);
+			p_sw->p_osm_sw->new_lft[cl_ntoh16(hca_lid)] = p_port->port_num;
+
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Switch %s: set path to CN LID %u through port %u\n",
+				__osm_ftree_tuple_to_str(p_sw->tuple),
+				cl_ntoh16(hca_lid), p_port->port_num);
+
+			/* set local min hop table(LID) to route to the CA */
+			__osm_ftree_sw_set_hops(p_sw,
+						cl_ntoh16(hca_lid),
+						p_port->port_num, 1);
+
+			/* Assign downgoing ports by stepping up.
+			   Since we're routing here only CNs, we're routing it as REAL
+			   LID and updating fat-tree balancing counters. */
+			__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 */
+								       hca_lid,	/* LID that we're routing to */
+								       p_sw->rank + 1,	/* 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 */
+
+			/* count how many real targets have been routed from this leaf switch */
+			routed_targets_on_leaf++;
+		}
+
+		/* We're done with the real targets (all CNs) of this leaf switch.
+		   Now route the dummy HCAs that are missing or that are non-CNs.
+		   When routing to dummy HCAs we don't fill lid matrices. */
+
+		if (p_ftree->max_cn_per_leaf > routed_targets_on_leaf) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Routing %u dummy CAs\n",
+				p_ftree->max_cn_per_leaf -
+				p_sw->down_port_groups_num);
+			for (j = 0;
+			     ((int)j) <
+			     (p_ftree->max_cn_per_leaf -
+			      routed_targets_on_leaf); 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_cns() */
+
+/***************************************************/
+
+/*
+ * Pseudo code:
+ *    foreach HCA non-CN port in fabric
+ *       obtain the LID of the HCA port
+ *       get switch that is connected to this HCA port
+ *       set switch LFT(LID) to the port connecting to compute node
+ *       call assign-down-going-port-by-ascending-up(TRUE,FALSE) on CURRENT switch
+ *
+ * Routing to these HCAs is routing a REAL hca lid on SECONDARY path.
+ * However, we do want to allow load-leveling of the traffic to the non-CNs,
+ * because such nodes may include IO nodes with heavy usage
+ *   - we should set fwd tables
+ *   - we should update port counters
+ * Routing to non-CNs is done after routing to CNs, so updated port
+ * counters will not affect CN-to-CN routing.
+ */
+
+static void __osm_ftree_fabric_route_to_non_cns(IN ftree_fabric_t * p_ftree)
+{
+	ftree_sw_t *p_sw;
+	ftree_hca_t *p_hca;
+	ftree_hca_t *p_next_hca;
+	ftree_port_t *p_hca_port;
+	ftree_port_group_t *p_hca_port_group;
+	ib_net16_t hca_lid;
+	unsigned port_num_on_switch;
+	unsigned i;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+	while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) {
+		p_hca = p_next_hca;
+		p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item);
+
+		for (i = 0; i < p_hca->up_port_groups_num; i++) {
+			p_hca_port_group = p_hca->up_port_groups[i];
+
+			/* skip this port if it's CN, in which case it has been already routed */
+			if (p_hca_port_group->is_cn)
+				continue;
+
+			/* skip this port if it is not connected to switch */
+			if (p_hca_port_group->remote_node_type !=
+			    IB_NODE_TYPE_SWITCH)
+				continue;
+
+			p_sw = p_hca_port_group->remote_hca_or_sw.p_sw;
+			hca_lid = p_hca_port_group->base_lid;
+
+			/* set switches  LFT(LID) to the port that is connected to HCA */
+			cl_ptr_vector_at(&p_hca_port_group->ports, 0,
+					 (void *)&p_hca_port);
+			port_num_on_switch = p_hca_port->remote_port_num;
+			p_sw->p_osm_sw->new_lft[cl_ntoh16(hca_lid)] = port_num_on_switch;
+
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Switch %s: set path to non-CN HCA LID %u through port %u\n",
+				__osm_ftree_tuple_to_str(p_sw->tuple),
+				cl_ntoh16(hca_lid), port_num_on_switch);
+
+			/* set local min hop table(LID) to route to the CA */
+			__osm_ftree_sw_set_hops(p_sw, cl_ntoh16(hca_lid),
+						port_num_on_switch,	/* port num */
+						1);	/* hops */
+
+			/* Assign downgoing ports by stepping up.
+			   We're routing REAL targets. They are not CNs and not included
+			   in the leafs array, but we treat them as MAIN path to allow load
+			   leveling, which means that the counters will be updated. */
+			__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 */
+								       hca_lid,	/* LID that we're routing to */
+								       p_sw->rank + 1,	/* 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 */
+		}
+		/* done with all the port groups of this HCA - go to next HCA */
+	}
+
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+}				/* __osm_ftree_fabric_route_to_non_cns() */
+
+/***************************************************/
+
+/*
+ * Pseudo code:
+ *    foreach switch in fabric
+ *       obtain its LID
+ *       set local LFT(LID) to port 0
+ *       call assign-down-going-port-by-ascending-up(TRUE,FALSE) on CURRENT switch
+ *
+ * Routing to switch is similar to routing a REAL hca lid on SECONDARY path:
+ *   - we should set fwd tables
+ *   - we should NOT update port counters
+ */
+
+static void __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);
+
+	p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl);
+	while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item);
+
+		/* set local LFT(LID) to 0 (route to itself) */
+		p_sw->p_osm_sw->new_lft[cl_ntoh16(p_sw->base_lid)] = 0;
+
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Switch %s (LID %u): routing switch-to-switch paths\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, 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_nodes(IN ftree_fabric_t * p_ftree)
+{
+	osm_node_t *p_osm_node;
+	osm_node_t *p_next_osm_node;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	p_next_osm_node =
+	    (osm_node_t *) cl_qmap_head(&p_ftree->p_osm->subn.node_guid_tbl);
+	while (p_next_osm_node !=
+	       (osm_node_t *) cl_qmap_end(&p_ftree->p_osm->subn.
+					  node_guid_tbl)) {
+		p_osm_node = p_next_osm_node;
+		p_next_osm_node =
+		    (osm_node_t *) cl_qmap_next(&p_osm_node->map_item);
+		switch (osm_node_get_type(p_osm_node)) {
+		case IB_NODE_TYPE_CA:
+			__osm_ftree_fabric_add_hca(p_ftree, p_osm_node);
+			break;
+		case IB_NODE_TYPE_ROUTER:
+			break;
+		case IB_NODE_TYPE_SWITCH:
+			__osm_ftree_fabric_add_sw(p_ftree, p_osm_node->sw);
+			break;
+		default:
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0E: "
+				"Node GUID 0x%016" PRIx64
+				" - Unknown node type: %s\n",
+				cl_ntoh64(osm_node_get_node_guid(p_osm_node)),
+				ib_get_node_type_str(osm_node_get_type
+						     (p_osm_node)));
+			OSM_LOG_EXIT(&p_ftree->p_osm->log);
+			return -1;
+		}
+	}
+
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return 0;
+}				/* __osm_ftree_fabric_populate_nodes() */
+
+/***************************************************
+ ***************************************************/
+
+static boolean_t __osm_ftree_sw_update_rank(IN ftree_sw_t * p_sw,
+					    IN uint32_t new_rank)
+{
+	if (__osm_ftree_sw_ranked(p_sw) && p_sw->rank <= new_rank)
+		return FALSE;
+	p_sw->rank = new_rank;
+	return TRUE;
+
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_rank_switches_from_leafs(IN ftree_fabric_t * p_ftree,
+				     IN cl_list_t * p_ranking_bfs_list)
+{
+	ftree_sw_t *p_sw;
+	ftree_sw_t *p_remote_sw;
+	osm_node_t *p_node;
+	osm_node_t *p_remote_node;
+	osm_physp_t *p_osm_port;
+	uint8_t i;
+	unsigned max_rank = 0;
+
+	while (!cl_is_list_empty(p_ranking_bfs_list)) {
+		p_sw = (ftree_sw_t *) cl_list_remove_head(p_ranking_bfs_list);
+		p_node = p_sw->p_osm_sw->p_node;
+
+		/* note: skipping port 0 on switches */
+		for (i = 1; i < osm_node_get_num_physp(p_node); i++) {
+			p_osm_port = osm_node_get_physp_ptr(p_node, i);
+			if (!p_osm_port || !osm_link_is_healthy(p_osm_port))
+				continue;
+
+			p_remote_node =
+			    osm_node_get_remote_node(p_node, i, NULL);
+			if (!p_remote_node)
+				continue;
+			if (osm_node_get_type(p_remote_node) !=
+			    IB_NODE_TYPE_SWITCH)
+				continue;
+
+			p_remote_sw = __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+									osm_node_get_node_guid
+									(p_remote_node));
+			if (!p_remote_sw) {
+				/* remote node is not a switch */
+				continue;
+			}
+
+			/* if needed, rank the remote switch and add it to the BFS list */
+			if (__osm_ftree_sw_update_rank
+			    (p_remote_sw, p_sw->rank + 1)) {
+				max_rank = p_remote_sw->rank;
+				cl_list_insert_tail(p_ranking_bfs_list,
+						    p_remote_sw);
+			}
+		}
+	}
+
+	/* set FatTree maximal switch rank */
+	p_ftree->max_switch_rank = max_rank;
+
+}				/* __osm_ftree_rank_switches_from_leafs() */
+
+/***************************************************/
+
+static int
+__osm_ftree_rank_leaf_switches(IN ftree_fabric_t * p_ftree,
+			       IN ftree_hca_t * p_hca,
+			       IN cl_list_t * p_ranking_bfs_list)
+{
+	ftree_sw_t *p_sw;
+	osm_node_t *p_osm_node = p_hca->p_osm_node;
+	osm_node_t *p_remote_osm_node;
+	osm_physp_t *p_osm_port;
+	static uint8_t i = 0;
+	int res = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	for (i = 0; i < osm_node_get_num_physp(p_osm_node); i++) {
+		p_osm_port = osm_node_get_physp_ptr(p_osm_node, i);
+		if (!p_osm_port || !osm_link_is_healthy(p_osm_port))
+			continue;
+
+		p_remote_osm_node =
+		    osm_node_get_remote_node(p_osm_node, i, NULL);
+		if (!p_remote_osm_node)
+			continue;
+
+		switch (osm_node_get_type(p_remote_osm_node)) {
+		case IB_NODE_TYPE_CA:
+			/* HCA connected directly to another HCA - not FatTree */
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0F: "
+				"CA conected directly to another CA: "
+				"0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n",
+				__osm_ftree_hca_get_guid_ho(p_hca),
+				cl_ntoh64(osm_node_get_node_guid
+					  (p_remote_osm_node)));
+			res = -1;
+			goto Exit;
+
+		case IB_NODE_TYPE_ROUTER:
+			/* leaving this port - proceeding to the next one */
+			continue;
+
+		case IB_NODE_TYPE_SWITCH:
+			/* continue with this port */
+			break;
+
+		default:
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+				"ERR AB10: Node GUID 0x%016" PRIx64
+				" - Unknown node type: %s\n",
+				cl_ntoh64(osm_node_get_node_guid
+					  (p_remote_osm_node)),
+				ib_get_node_type_str(osm_node_get_type
+						     (p_remote_osm_node)));
+			res = -1;
+			goto Exit;
+		}
+
+		/* remote node is switch */
+
+		p_sw = __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+							 osm_node_get_node_guid
+							 (p_osm_port->
+							  p_remote_physp->
+							  p_node));
+		CL_ASSERT(p_sw);
+
+		/* if needed, rank the remote switch and add it to the BFS list */
+
+		if (!__osm_ftree_sw_update_rank(p_sw, 0))
+			continue;
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Marking rank of switch that is directly connected to CA:\n"
+			"                                            - CA guid    : 0x%016"
+			PRIx64 "\n"
+			"                                            - Switch guid: 0x%016"
+			PRIx64 "\n"
+			"                                            - Switch LID : %u\n",
+			__osm_ftree_hca_get_guid_ho(p_hca),
+			__osm_ftree_sw_get_guid_ho(p_sw),
+			cl_ntoh16(p_sw->base_lid));
+		cl_list_insert_tail(p_ranking_bfs_list, p_sw);
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_rank_leaf_switches() */
+
+/***************************************************/
+
+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 = p_ftree->max_switch_rank - p_sw->rank;
+}
+
+/***************************************************
+ ***************************************************/
+
+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;
+	boolean_t is_cn = FALSE;
+	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 (!p_osm_port || !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, "ERR AB11: "
+				"CA conected directly to another CA: "
+				"0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n",
+				cl_ntoh64(osm_node_get_node_guid(p_node)),
+				cl_ntoh64(remote_node_guid));
+			res = -1;
+			goto Exit;
+
+		case IB_NODE_TYPE_SWITCH:
+			/* continue with this port */
+			break;
+
+		default:
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+				"ERR AB12: Node GUID 0x%016" PRIx64
+				" - Unknown node type: %s\n",
+				cl_ntoh64(remote_node_guid),
+				ib_get_node_type_str(remote_node_type));
+			res = -1;
+			goto Exit;
+		}
+
+		/* remote node is switch */
+
+		p_remote_sw =
+		    __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+						      remote_node_guid);
+		CL_ASSERT(p_remote_sw);
+
+		/* If CN file is not supplied, then all the CAs considered as Compute Nodes.
+		   Otherwise all the CAs are not CNs, and only guids that are present in the
+		   CN file will be marked as compute nodes. */
+		if (!__osm_ftree_fabric_cns_provided(p_ftree)) {
+			is_cn = TRUE;
+		} else {
+			name_map_item_t *p_elem =
+			    (name_map_item_t *) cl_qmap_get(&p_ftree->
+							    cn_guid_tbl,
+							    cl_ntoh64(osm_physp_get_port_guid
+							    (p_osm_port)));
+			if (p_elem !=
+			    (name_map_item_t *) cl_qmap_end(&p_ftree->
+							    cn_guid_tbl))
+				is_cn = TRUE;
+		}
+
+		if (is_cn) {
+			p_ftree->cn_num++;
+			p_hca->cn_num++;
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Marking CN port GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_osm_port)));
+		} else {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Marking non-CN port GUID 0x%016" PRIx64 "\n",
+				cl_ntoh64(osm_physp_get_port_guid(p_osm_port)));
+		}
+
+		__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 */
+					 is_cn);	/* whether this port is compute node */
+	}
+
+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 = p_sw->p_osm_sw->p_node;
+	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 = 1; i < osm_node_get_num_physp(p_node); i++) {
+		osm_physp_t *p_osm_port = osm_node_get_physp_ptr(p_node, i);
+		if (!p_osm_port || !osm_link_is_healthy(p_osm_port))
+			continue;
+
+		p_remote_osm_port = osm_physp_get_remote(p_osm_port);
+		if (!p_remote_osm_port)
+			continue;
+
+		p_remote_node =
+		    osm_node_get_remote_node(p_node, i, &remote_port_num);
+
+		/* ignore any loopback connection on switch */
+		if (p_node == p_remote_node) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+				"Ignoring loopback on switch GUID 0x%016" PRIx64
+				", LID %u, rank %u\n",
+				__osm_ftree_sw_get_guid_ho(p_sw),
+				cl_ntoh16(p_sw->base_lid),
+				p_sw->rank);
+			continue;
+		}
+
+		remote_node_type = osm_node_get_type(p_remote_node);
+		remote_node_guid = osm_node_get_node_guid(p_remote_node);
+
+		switch (remote_node_type) {
+		case IB_NODE_TYPE_ROUTER:
+			/* leaving this port - proceeding to the next one */
+			continue;
+
+		case IB_NODE_TYPE_CA:
+			/* switch connected to hca */
+
+			p_remote_hca =
+			    __osm_ftree_fabric_get_hca_by_guid(p_ftree,
+							       remote_node_guid);
+			CL_ASSERT(p_remote_hca);
+
+			p_remote_hca_or_sw = (void *)p_remote_hca;
+			direction = FTREE_DIRECTION_DOWN;
+
+			remote_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 =
+			    __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+							      remote_node_guid);
+			CL_ASSERT(p_remote_sw);
+
+			p_remote_hca_or_sw = (void *)p_remote_sw;
+
+			if (abs(p_sw->rank - p_remote_sw->rank) != 1) {
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+					"ERR AB16: "
+					"Illegal link between switches with ranks %u and %u:\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, rank %u\n"
+					"       GUID 0x%016" PRIx64
+					", LID %u, rank %u\n", p_sw->rank,
+					p_remote_sw->rank,
+					__osm_ftree_sw_get_guid_ho(p_sw),
+					cl_ntoh16(p_sw->base_lid), p_sw->rank,
+					__osm_ftree_sw_get_guid_ho(p_remote_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,
+				"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() */
+
+/***************************************************
+ ***************************************************/
+
+static int __osm_ftree_fabric_rank_from_roots(IN ftree_fabric_t * p_ftree)
+{
+	osm_node_t *p_osm_node;
+	osm_node_t *p_remote_osm_node;
+	osm_physp_t *p_osm_physp;
+	ftree_sw_t *p_sw;
+	ftree_sw_t *p_remote_sw;
+	cl_list_t ranking_bfs_list;
+	struct guid_list_item *item;
+	int res = 0;
+	unsigned num_roots;
+	unsigned max_rank = 0;
+	unsigned i;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+	cl_list_init(&ranking_bfs_list, 10);
+
+	/* Rank all the roots and add them to list */
+	for (item = (void *)cl_qlist_head(&p_ftree->root_guid_list);
+	     item != (void *)cl_qlist_end(&p_ftree->root_guid_list);
+	     item = (void *)cl_qlist_next(&item->list)) {
+		p_sw =
+		    __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+						      cl_hton64(item->guid));
+		if (!p_sw) {
+			/* the specified root guid wasn't found in the fabric */
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB24: "
+				"Root switch GUID 0x%" PRIx64 " not found\n",
+				item->guid);
+			continue;
+		}
+
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Ranking root switch with GUID 0x%" PRIx64 "\n",
+			item->guid);
+		p_sw->rank = 0;
+		cl_list_insert_tail(&ranking_bfs_list, p_sw);
+	}
+
+	num_roots = cl_list_count(&ranking_bfs_list);
+	if (!num_roots) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB25: "
+			"No valid roots supplied\n");
+		res = -1;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Ranked %u valid root switches\n", num_roots);
+
+	/* Now the list has all the roots.
+	   BFS the subnet and update rank on all the switches. */
+
+	while (!cl_is_list_empty(&ranking_bfs_list)) {
+		p_sw = (ftree_sw_t *) cl_list_remove_head(&ranking_bfs_list);
+		p_osm_node = p_sw->p_osm_sw->p_node;
+
+		/* note: skipping port 0 on switches */
+		for (i = 1; i < osm_node_get_num_physp(p_osm_node); i++) {
+			p_osm_physp = osm_node_get_physp_ptr(p_osm_node, i);
+			if (!p_osm_physp  || !osm_link_is_healthy(p_osm_physp))
+				continue;
+
+			p_remote_osm_node =
+			    osm_node_get_remote_node(p_osm_node, i, NULL);
+			if (!p_remote_osm_node)
+				continue;
+
+			if (osm_node_get_type(p_remote_osm_node) !=
+			    IB_NODE_TYPE_SWITCH)
+				continue;
+
+			p_remote_sw = __osm_ftree_fabric_get_sw_by_guid(p_ftree,
+									osm_node_get_node_guid
+									(p_remote_osm_node));
+			CL_ASSERT(p_remote_sw);
+
+			/* if needed, rank the remote switch and add it to the BFS list */
+			if (__osm_ftree_sw_update_rank
+			    (p_remote_sw, p_sw->rank + 1)) {
+				OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+					"Ranking switch 0x%" PRIx64
+					" with rank %u\n",
+					__osm_ftree_sw_get_guid_ho(p_remote_sw),
+					p_remote_sw->rank);
+				max_rank = p_remote_sw->rank;
+				cl_list_insert_tail(&ranking_bfs_list,
+						    p_remote_sw);
+			}
+		}
+		/* done with ports of this switch - go to the next switch in the list */
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Subnet ranking completed. Max Node Rank = %u\n", max_rank);
+
+	/* set FatTree maximal switch rank */
+	p_ftree->max_switch_rank = max_rank;
+
+Exit:
+	cl_list_destroy(&ranking_bfs_list);
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_fabric_rank_from_roots() */
+
+/***************************************************
+ ***************************************************/
+
+static int __osm_ftree_fabric_rank_from_hcas(IN ftree_fabric_t * p_ftree)
+{
+	ftree_hca_t *p_hca;
+	ftree_hca_t *p_next_hca;
+	cl_list_t ranking_bfs_list;
+	int res = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	cl_list_init(&ranking_bfs_list, 10);
+
+	/* Mark REVERSED rank of all the switches in the subnet.
+	   Start from switches that are connected to hca's, and
+	   scan all the switches in the subnet. */
+	p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+	while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) {
+		p_hca = p_next_hca;
+		p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item);
+		if (__osm_ftree_rank_leaf_switches
+		    (p_ftree, p_hca, &ranking_bfs_list) != 0) {
+			res = -1;
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB14: "
+				"Subnet ranking failed - subnet is not FatTree");
+			goto Exit;
+		}
+	}
+
+	/* Now rank rest of the switches in the fabric, while the
+	   list already contains all the ranked leaf switches */
+	__osm_ftree_rank_switches_from_leafs(p_ftree, &ranking_bfs_list);
+
+	/* fix ranking of the switches by reversing the ranking direction */
+	cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_sw_reverse_rank,
+			   (void *)p_ftree);
+
+Exit:
+	cl_list_destroy(&ranking_bfs_list);
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_fabric_rank_from_hcas() */
+
+/***************************************************
+ ***************************************************/
+
+static int __osm_ftree_fabric_rank(IN ftree_fabric_t * p_ftree)
+{
+	int res = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	if (__osm_ftree_fabric_roots_provided(p_ftree))
+		res = __osm_ftree_fabric_rank_from_roots(p_ftree);
+	else
+		res = __osm_ftree_fabric_rank_from_hcas(p_ftree);
+
+	if (res)
+		goto Exit;
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"FatTree max switch rank is %u\n", p_ftree->max_switch_rank);
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return res;
+}				/* __osm_ftree_fabric_rank() */
+
+/***************************************************
+ ***************************************************/
+
+static void __osm_ftree_fabric_set_leaf_rank(IN ftree_fabric_t * p_ftree)
+{
+	unsigned i;
+	ftree_sw_t *p_sw;
+	ftree_hca_t *p_hca = NULL;
+	ftree_hca_t *p_next_hca;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	if (!__osm_ftree_fabric_roots_provided(p_ftree)) {
+		/* If root file is not provided, the fabric has to be pure fat-tree
+		   in terms of ranking. Thus, leaf switches rank is the max rank. */
+		p_ftree->leaf_switch_rank = p_ftree->max_switch_rank;
+	} else {
+		/* Find the first CN and set the leaf_switch_rank to the rank
+		   of the switch that is connected to this CN. Later we will
+		   ensure that all the leaf switches have the same rank. */
+		p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl);
+		while (p_next_hca !=
+		       (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) {
+			p_hca = p_next_hca;
+			if (p_hca->cn_num)
+				break;
+			p_next_hca =
+			    (ftree_hca_t *) cl_qmap_next(&p_hca->map_item);
+		}
+		/* we know that there are CNs in the fabric, so just to be sure... */
+		CL_ASSERT(p_next_hca !=
+			  (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl));
+
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Selected CN port GUID 0x%" PRIx64 "\n",
+			__osm_ftree_hca_get_guid_ho(p_hca));
+
+		for (i = 0; (i < p_hca->up_port_groups_num)
+		     && (!p_hca->up_port_groups[i]->is_cn); i++) ;
+		CL_ASSERT(i < p_hca->up_port_groups_num);
+		CL_ASSERT(p_hca->up_port_groups[i]->remote_node_type ==
+			  IB_NODE_TYPE_SWITCH);
+
+		p_sw = p_hca->up_port_groups[i]->remote_hca_or_sw.p_sw;
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Selected leaf switch GUID 0x%" PRIx64 ", rank %u\n",
+			__osm_ftree_sw_get_guid_ho(p_sw), p_sw->rank);
+		p_ftree->leaf_switch_rank = p_sw->rank;
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO,
+		"FatTree leaf switch rank is %u\n", p_ftree->leaf_switch_rank);
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+}				/* __osm_ftree_fabric_set_leaf_rank() */
+
+/***************************************************
+ ***************************************************/
+
+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);
+
+	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 add_guid_item_to_list(void *cxt, uint64_t guid, char *p)
+{
+	cl_qlist_t *list = cxt;
+	struct guid_list_item *item;
+
+	item = malloc(sizeof(*item));
+	if (!item)
+		return -1;
+
+	item->guid = guid;
+	cl_qlist_insert_tail(list, &item->list);
+
+	return 0;
+}
+
+static int add_guid_item_to_map(void *cxt, uint64_t guid, char *p)
+{
+	cl_qmap_t *map = cxt;
+	name_map_item_t *item;
+
+	item = malloc(sizeof(*item));
+	if (!item)
+		return -1;
+
+	item->guid = guid;
+	cl_qmap_insert(map, guid, &item->item);
+
+	return 0;
+}
+
+static int __osm_ftree_fabric_read_guid_files(IN ftree_fabric_t * p_ftree)
+{
+	int status = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	if (__osm_ftree_fabric_roots_provided(p_ftree)) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Fetching root nodes from file %s\n",
+			p_ftree->p_osm->subn.opt.root_guid_file);
+
+		if (parse_node_map(p_ftree->p_osm->subn.opt.root_guid_file,
+				   add_guid_item_to_list,
+				   &p_ftree->root_guid_list)) {
+			status = -1;
+			goto Exit;
+		}
+
+		if (!cl_qlist_count(&p_ftree->root_guid_list)) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB22: "
+				"Root guids file has no valid guids\n");
+			status = -1;
+			goto Exit;
+		}
+	}
+
+	if (__osm_ftree_fabric_cns_provided(p_ftree)) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+			"Fetching compute nodes from file %s\n",
+			p_ftree->p_osm->subn.opt.cn_guid_file);
+
+		if (parse_node_map(p_ftree->p_osm->subn.opt.cn_guid_file,
+				   add_guid_item_to_map,
+				   &p_ftree->cn_guid_tbl)) {
+			status = -1;
+			goto Exit;
+		}
+
+		if (!cl_qmap_count(&p_ftree->cn_guid_tbl)) {
+			OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB23: "
+				"Compute node guids file has no valid guids\n");
+			status = -1;
+			goto Exit;
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return status;
+} /*__osm_ftree_fabric_read_guid_files() */
+
+/***************************************************
+ ***************************************************/
+
+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_fabric_clear(p_ftree);
+
+	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, "\n"
+		"                       |----------------------------------------|\n"
+		"                       |- Starting FatTree fabric construction -|\n"
+		"                       |----------------------------------------|\n\n");
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Populating FatTree Switch and CA tables\n");
+	if (__osm_ftree_fabric_populate_nodes(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,
+		"Reading guid files provided by user\n");
+	if (__osm_ftree_fabric_read_guid_files(p_ftree) != 0) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Failed reading guid files - "
+			"falling back to default routing\n");
+		status = -1;
+		goto Exit;
+	}
+
+	if (cl_qmap_count(&p_ftree->hca_tbl) < 2) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fabric has %u CAa - topology is not fat-tree.\n"
+			"Falling back to default routing\n",
+			cl_qmap_count(&p_ftree->hca_tbl));
+		status = -1;
+		goto Exit;
+	}
+
+	/* Rank all the switches in the fabric.
+	   After that we will know only fabric max switch rank.
+	   We will be able to check leaf switches rank and the
+	   whole tree rank after filling ports and marking CNs. */
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Ranking FatTree\n");
+	if (__osm_ftree_fabric_rank(p_ftree) != 0) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Failed ranking the tree\n");
+		status = -1;
+		goto Exit;
+	}
+
+	/* For each hca and switch, construct array of ports.
+	   This is done after the whole FatTree data structure is ready,
+	   because we want the ports to have pointers to ftree_{sw,hca}_t
+	   objects, and we need the switches to be already ranked because
+	   that's how the port direction is determined. */
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Populating CA & switch ports\n");
+	if (__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\n");
+		status = -1;
+		goto Exit;
+	} else if (p_ftree->cn_num == 0) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fabric has no valid compute nodes\n");
+		status = -1;
+		goto Exit;
+	}
+
+	/* Now that the CA ports have been created and CNs were marked,
+	   we can complete the fabric ranking - set leaf switches rank. */
+	__osm_ftree_fabric_set_leaf_rank(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_SYS,
+			"Fabric 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);
+		status = -1;
+		goto Exit;
+	}
+
+	/* Mark all the switches in the fabric with rank equal to
+	   p_ftree->leaf_switch_rank and that are also connected to CNs.
+	   As a by-product, this function also runs basic topology
+	   validation - it checks that all the CNs are at the same rank. */
+	if (__osm_ftree_fabric_mark_leaf_switches(p_ftree)) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fabric topology is not a fat-tree\n");
+		status = -1;
+		goto Exit;
+	}
+
+	/* Assign index to all the switches in the fabric.
+	   This function also sorts leaf switch array by the switch index,
+	   sorts all the port arrays of the indexed switches by remote
+	   switch index, and creates switch-by-tuple table (sw_by_tuple_tbl) */
+	__osm_ftree_fabric_make_indexing(p_ftree);
+
+	/* Create leaf switch array sorted by index.
+	   This array contains switches with rank equal to p_ftree->leaf_switch_rank
+	   and that are also connected to CNs (REAL leafs), and it may contain
+	   switches at the same leaf rank w/o CNs, if this is the order of indexing.
+	   In any case, the first and the last switches in the array are REAL leafs. */
+	if (__osm_ftree_fabric_create_leaf_switch_array(p_ftree)) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fabric topology is not a fat-tree\n");
+		status = -1;
+		goto Exit;
+	}
+
+	/* calculate and set ftree.max_cn_per_leaf field */
+	__osm_ftree_fabric_set_max_cn_per_leaf(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);
+
+	/* the fabric is required to be PURE fat-tree only if the root
+	   guid file hasn't been provided by user */
+	if (!__osm_ftree_fabric_roots_provided(p_ftree) &&
+	    !__osm_ftree_fabric_validate_topology(p_ftree)) {
+		osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+			"Fabric topology is not a fat-tree\n");
+		status = -1;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Max LID in switch LFTs: %u\n",
+		p_ftree->lft_max_lid_ho);
+
+Exit:
+	if (status != 0) {
+		OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+			"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, "\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;
+	int status = 0;
+
+	OSM_LOG_ENTER(&p_ftree->p_osm->log);
+
+	if (!p_ftree->fabric_built) {
+		status = -1;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Starting FatTree routing\n");
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Filling switch forwarding tables for Compute Nodes\n");
+	__osm_ftree_fabric_route_to_cns(p_ftree);
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Filling switch forwarding tables for non-CN targets\n");
+	__osm_ftree_fabric_route_to_non_cns(p_ftree);
+
+	OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+		"Filling switch forwarding tables for switch-to-switch paths\n");
+	__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,
+		"FatTree routing is done\n");
+
+Exit:
+	OSM_LOG_EXIT(&p_ftree->p_osm->log);
+	return status;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void __osm_ftree_delete(IN void *context)
+{
+	if (!context)
+		return;
+	__osm_ftree_fabric_destroy((ftree_fabric_t *) context);
+}
+
+/***************************************************
+ ***************************************************/
+
+int osm_ucast_ftree_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm)
+{
+	ftree_fabric_t *p_ftree = __osm_ftree_fabric_create();
+	if (!p_ftree)
+		return -1;
+
+	p_ftree->p_osm = p_osm;
+
+	r->context = (void *)p_ftree;
+	r->build_lid_matrices = __osm_ftree_construct_fabric;
+	r->ucast_build_fwd_tables = __osm_ftree_do_routing;
+	r->delete = __osm_ftree_delete;
+
+	return 0;
+}
diff --git a/opensm/osm_ucast_lash.c b/opensm/osm_ucast_lash.c
new file mode 100644
index 0000000..f6795f6
--- /dev/null
+++ b/opensm/osm_ucast_lash.c
@@ -0,0 +1,1356 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2007      Simula Research Laboratory. All rights reserved.
+ * Copyright (c) 2007      Silicon Graphics Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *      Implementation of LASH algorithm Calculation functions
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+
+/* //////////////////////////// */
+/*  Local types                 */
+/* //////////////////////////// */
+
+enum {
+	UNQUEUED,
+	Q_MEMBER,
+	MST_MEMBER,
+	MAX_INT = 9999,
+	NONE = MAX_INT
+};
+
+typedef struct _cdg_vertex {
+	int num_dependencies;
+	struct _cdg_vertex **dependency;
+	int from;
+	int to;
+	int seen;
+	int temp;
+	int visiting_number;
+	struct _cdg_vertex *next;
+	int num_temp_depend;
+	int num_using_vertex;
+	int *num_using_this_depend;
+} cdg_vertex_t;
+
+typedef struct _reachable_dest {
+	int switch_id;
+	struct _reachable_dest *next;
+} reachable_dest_t;
+
+typedef struct _switch {
+	osm_switch_t *p_sw;
+	int *dij_channels;
+	int id;
+	int used_channels;
+	int q_state;
+	struct routing_table {
+		unsigned out_link;
+		unsigned lane;
+	} *routing_table;
+	unsigned int num_connections;
+	int *virtual_physical_port_table;
+	int *phys_connections;
+} switch_t;
+
+typedef struct _lash {
+	osm_opensm_t *p_osm;
+	int num_switches;
+	uint8_t vl_min;
+	int balance_limit;
+	switch_t **switches;
+	cdg_vertex_t ****cdg_vertex_matrix;
+	int *num_mst_in_lane;
+	int ***virtual_location;
+} lash_t;
+
+static cdg_vertex_t *create_cdg_vertex(unsigned num_switches)
+{
+	cdg_vertex_t *cdg_vertex = (cdg_vertex_t *) malloc(sizeof(cdg_vertex_t));
+
+	cdg_vertex->dependency = malloc((num_switches - 1) * sizeof(cdg_vertex_t *));
+	cdg_vertex->num_using_this_depend = (int *)malloc((num_switches - 1) * sizeof(int));
+	return cdg_vertex;
+}
+
+static void connect_switches(lash_t * p_lash, int sw1, int sw2, int phy_port_1)
+{
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	unsigned num = p_lash->switches[sw1]->num_connections;
+
+	p_lash->switches[sw1]->phys_connections[num] = sw2;
+	p_lash->switches[sw1]->virtual_physical_port_table[num] = phy_port_1;
+	p_lash->switches[sw1]->num_connections++;
+
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"LASH connect: %d, %d, %d\n", sw1, sw2,
+		phy_port_1);
+
+}
+
+static osm_switch_t *get_osm_switch_from_port(osm_port_t * port)
+{
+	osm_physp_t *p = port->p_physp;
+	if (p->p_node->sw)
+		return p->p_node->sw;
+	else if (p->p_remote_physp->p_node->sw)
+		return p->p_remote_physp->p_node->sw;
+	return NULL;
+}
+
+#if 0
+static int randint(int high)
+{
+	int r;
+
+	if (high == 0)
+		return 0;
+	r = rand();
+	high++;
+	return (r % high);
+}
+#endif
+
+static int cycle_exists(cdg_vertex_t * start, cdg_vertex_t * current,
+			cdg_vertex_t * prev, int visit_num)
+{
+	cdg_vertex_t *h;
+	int i, new_visit_num;
+	int cycle_found = 0;
+
+	if (current != NULL && current->visiting_number > 0) {
+		if (visit_num > current->visiting_number && current->seen == 0) {
+			h = start;
+			cycle_found = 1;
+		}
+	} else {
+		if (current == NULL) {
+			current = start;
+			CL_ASSERT(prev == NULL);
+		}
+
+		current->visiting_number = visit_num;
+
+		if (prev != NULL) {
+			prev->next = current;
+			CL_ASSERT(prev->to == current->from);
+			CL_ASSERT(prev->visiting_number > 0);
+		}
+
+		new_visit_num = visit_num + 1;
+
+		for (i = 0; i < current->num_dependencies; i++) {
+			cycle_found =
+			    cycle_exists(start, current->dependency[i], current,
+					 new_visit_num);
+			if (cycle_found == 1)
+				i = current->num_dependencies;
+		}
+
+		current->seen = 1;
+		if (prev != NULL)
+			prev->next = NULL;
+	}
+
+	return cycle_found;
+}
+
+static void remove_semipermanent_depend_for_sp(lash_t * p_lash, int sw,
+					       int dest_switch, int lane)
+{
+	switch_t **switches = p_lash->switches;
+	cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
+	int i_next_switch, output_link, i, next_link, i_next_next_switch,
+	    depend = 0;
+	cdg_vertex_t *v;
+	int found;
+
+	output_link = switches[sw]->routing_table[dest_switch].out_link;
+	i_next_switch = switches[sw]->phys_connections[output_link];
+
+	while (sw != dest_switch) {
+		v = cdg_vertex_matrix[lane][sw][i_next_switch];
+		CL_ASSERT(v != NULL);
+
+		if (v->num_using_vertex == 1) {
+
+			cdg_vertex_matrix[lane][sw][i_next_switch] = NULL;
+
+			free(v);
+		} else {
+			v->num_using_vertex--;
+			if (i_next_switch != dest_switch) {
+				next_link =
+				    switches[i_next_switch]->routing_table[dest_switch].out_link;
+				i_next_next_switch =
+				    switches[i_next_switch]->phys_connections[next_link];
+				found = 0;
+
+				for (i = 0; i < v->num_dependencies; i++)
+					if (v->dependency[i] ==
+					    cdg_vertex_matrix[lane][i_next_switch]
+					    [i_next_next_switch]) {
+						found = 1;
+						depend = i;
+					}
+
+				CL_ASSERT(found);
+
+				if (v->num_using_this_depend[depend] == 1) {
+					for (i = depend;
+					     i < v->num_dependencies - 1; i++) {
+						v->dependency[i] =
+						    v->dependency[i + 1];
+						v->num_using_this_depend[i] =
+						    v->num_using_this_depend[i +
+									     1];
+					}
+
+					v->num_dependencies--;
+				} else
+					v->num_using_this_depend[depend]--;
+			}
+		}
+
+		sw = i_next_switch;
+		output_link = switches[sw]->routing_table[dest_switch].out_link;
+
+		if (sw != dest_switch)
+			i_next_switch =
+			    switches[sw]->phys_connections[output_link];
+	}
+}
+
+inline static void enqueue(cl_list_t * bfsq, switch_t * sw)
+{
+	CL_ASSERT(sw->q_state == UNQUEUED);
+	sw->q_state = Q_MEMBER;
+	cl_list_insert_tail(bfsq, sw);
+}
+
+inline static void dequeue(cl_list_t * bfsq, switch_t ** sw)
+{
+	*sw = (switch_t *) cl_list_remove_head(bfsq);
+	CL_ASSERT((*sw)->q_state == Q_MEMBER);
+	(*sw)->q_state = MST_MEMBER;
+}
+
+static int get_phys_connection(switch_t *sw, int switch_to)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < sw->num_connections; i++)
+		if (sw->phys_connections[i] == switch_to)
+			return i;
+	return i;
+}
+
+static void shortest_path(lash_t * p_lash, int ir)
+{
+	switch_t **switches = p_lash->switches, *sw, *swi;
+	unsigned int i;
+	cl_list_t bfsq;
+
+	cl_list_construct(&bfsq);
+	cl_list_init(&bfsq, 20);
+
+	enqueue(&bfsq, switches[ir]);
+
+	while (!cl_is_list_empty(&bfsq)) {
+		dequeue(&bfsq, &sw);
+		for (i = 0; i < sw->num_connections; i++) {
+			swi = switches[sw->phys_connections[i]];
+			if (swi->q_state == UNQUEUED) {
+				enqueue(&bfsq, swi);
+				sw->dij_channels[sw->used_channels++] = swi->id;
+			}
+		}
+	}
+
+	cl_list_destroy(&bfsq);
+}
+
+static void generate_routing_func_for_mst(lash_t * p_lash, int sw_id,
+					  reachable_dest_t ** destinations)
+{
+	int i, next_switch;
+	switch_t *sw = p_lash->switches[sw_id];
+	int num_channels = sw->used_channels;
+	reachable_dest_t *dest, *i_dest, *concat_dest = NULL, *prev;
+
+	for (i = 0; i < num_channels; i++) {
+		next_switch = sw->dij_channels[i];
+		generate_routing_func_for_mst(p_lash, next_switch, &dest);
+
+		i_dest = dest;
+		prev = i_dest;
+
+		while (i_dest != NULL) {
+			if (sw->routing_table[i_dest->switch_id].out_link ==
+			    NONE) {
+				sw->routing_table[i_dest->switch_id].out_link =
+				    get_phys_connection(sw, next_switch);
+			}
+
+			prev = i_dest;
+			i_dest = i_dest->next;
+		}
+
+		CL_ASSERT(prev->next == NULL);
+		prev->next = concat_dest;
+		concat_dest = dest;
+	}
+
+	i_dest = (reachable_dest_t *) malloc(sizeof(reachable_dest_t));
+	i_dest->switch_id = sw->id;
+	i_dest->next = concat_dest;
+	*destinations = i_dest;
+}
+
+static void generate_cdg_for_sp(lash_t * p_lash, int sw, int dest_switch,
+				int lane)
+{
+	unsigned num_switches = p_lash->num_switches;
+	switch_t **switches = p_lash->switches;
+	cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
+	int next_switch, output_link, j, exists;
+	cdg_vertex_t *v, *prev = NULL;
+
+	output_link = switches[sw]->routing_table[dest_switch].out_link;
+	next_switch = switches[sw]->phys_connections[output_link];
+
+	while (sw != dest_switch) {
+
+		if (cdg_vertex_matrix[lane][sw][next_switch] == NULL) {
+			unsigned i;
+			v = create_cdg_vertex(num_switches);
+
+			for (i = 0; i < num_switches - 1; i++) {
+				v->dependency[i] = NULL;
+				v->num_using_this_depend[i] = 0;
+			}
+
+			v->num_using_vertex = 0;
+			v->num_dependencies = 0;
+			v->from = sw;
+			v->to = next_switch;
+			v->seen = 0;
+			v->visiting_number = 0;
+			v->next = NULL;
+			v->temp = 1;
+			v->num_temp_depend = 0;
+
+			cdg_vertex_matrix[lane][sw][next_switch] = v;
+		} else
+			v = cdg_vertex_matrix[lane][sw][next_switch];
+
+		v->num_using_vertex++;
+
+		if (prev != NULL) {
+			exists = 0;
+
+			for (j = 0; j < prev->num_dependencies; j++)
+				if (prev->dependency[j] == v) {
+					exists = 1;
+					prev->num_using_this_depend[j]++;
+				}
+
+			if (exists == 0) {
+				prev->dependency[prev->num_dependencies] = v;
+				prev->num_using_this_depend[prev->num_dependencies]++;
+				prev->num_dependencies++;
+
+				CL_ASSERT(prev->num_dependencies < (int)num_switches);
+
+				if (prev->temp == 0)
+					prev->num_temp_depend++;
+
+			}
+		}
+
+		sw = next_switch;
+		output_link = switches[sw]->routing_table[dest_switch].out_link;
+
+		if (sw != dest_switch) {
+			CL_ASSERT(output_link != NONE);
+			next_switch = switches[sw]->phys_connections[output_link];
+		}
+
+		prev = v;
+	}
+}
+
+static void set_temp_depend_to_permanent_for_sp(lash_t * p_lash, int sw,
+						int dest_switch, int lane)
+{
+	switch_t **switches = p_lash->switches;
+	cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
+	int next_switch, output_link;
+	cdg_vertex_t *v;
+
+	output_link = switches[sw]->routing_table[dest_switch].out_link;
+	next_switch = switches[sw]->phys_connections[output_link];
+
+	while (sw != dest_switch) {
+		v = cdg_vertex_matrix[lane][sw][next_switch];
+		CL_ASSERT(v != NULL);
+
+		if (v->temp == 1)
+			v->temp = 0;
+		else
+			v->num_temp_depend = 0;
+
+		sw = next_switch;
+		output_link = switches[sw]->routing_table[dest_switch].out_link;
+
+		if (sw != dest_switch)
+			next_switch =
+			    switches[sw]->phys_connections[output_link];
+	}
+
+}
+
+static void remove_temp_depend_for_sp(lash_t * p_lash, int sw, int dest_switch,
+				      int lane)
+{
+	switch_t **switches = p_lash->switches;
+	cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
+	int next_switch, output_link, i;
+	cdg_vertex_t *v;
+
+	output_link = switches[sw]->routing_table[dest_switch].out_link;
+	next_switch = switches[sw]->phys_connections[output_link];
+
+	while (sw != dest_switch) {
+		v = cdg_vertex_matrix[lane][sw][next_switch];
+		CL_ASSERT(v != NULL);
+
+		if (v->temp == 1) {
+			cdg_vertex_matrix[lane][sw][next_switch] = NULL;
+			free(v);
+		} else {
+			CL_ASSERT(v->num_temp_depend <= v->num_dependencies);
+			v->num_dependencies =
+			    v->num_dependencies - v->num_temp_depend;
+			v->num_temp_depend = 0;
+			v->num_using_vertex--;
+
+			for (i = v->num_dependencies;
+			     i < p_lash->num_switches - 1; i++)
+				v->num_using_this_depend[i] = 0;
+		}
+
+		sw = next_switch;
+		output_link = switches[sw]->routing_table[dest_switch].out_link;
+
+		if (sw != dest_switch)
+			next_switch =
+			    switches[sw]->phys_connections[output_link];
+
+	}
+}
+
+static void balance_virtual_lanes(lash_t * p_lash, unsigned lanes_needed)
+{
+	unsigned num_switches = p_lash->num_switches;
+	cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
+	int *num_mst_in_lane = p_lash->num_mst_in_lane;
+	int ***virtual_location = p_lash->virtual_location;
+	int min_filled_lane, max_filled_lane, medium_filled_lane, trials;
+	int old_min_filled_lane, old_max_filled_lane, new_num_min_lane,
+	    new_num_max_lane;
+	unsigned int i, j;
+	int src, dest, start, next_switch, output_link;
+	int next_switch2, output_link2;
+	int stop = 0, cycle_found;
+	int cycle_found2;
+
+	max_filled_lane = 0;
+	min_filled_lane = lanes_needed - 1;
+
+	if (max_filled_lane > 1)
+		medium_filled_lane = max_filled_lane - 1;
+
+	trials = num_mst_in_lane[max_filled_lane];
+	if (lanes_needed == 1)
+		stop = 1;
+
+	while (stop == 0) {
+		src = abs(rand()) % (num_switches);
+		dest = abs(rand()) % (num_switches);
+
+		while (virtual_location[src][dest][max_filled_lane] != 1) {
+			start = dest;
+			if (dest == num_switches - 1)
+				dest = 0;
+			else
+				dest++;
+
+			while (dest != start
+			       && virtual_location[src][dest][max_filled_lane]
+			       != 1) {
+				if (dest == num_switches - 1)
+					dest = 0;
+				else
+					dest++;
+			}
+
+			if (virtual_location[src][dest][max_filled_lane] != 1) {
+				if (src == num_switches - 1)
+					src = 0;
+				else
+					src++;
+			}
+		}
+
+		generate_cdg_for_sp(p_lash, src, dest, min_filled_lane);
+		generate_cdg_for_sp(p_lash, dest, src, min_filled_lane);
+
+		output_link = p_lash->switches[src]->routing_table[dest].out_link;
+		next_switch = p_lash->switches[src]->phys_connections[output_link];
+
+		output_link2 = p_lash->switches[dest]->routing_table[src].out_link;
+		next_switch2 = p_lash->switches[dest]->phys_connections[output_link2];
+
+		CL_ASSERT(cdg_vertex_matrix[min_filled_lane][src][next_switch] != NULL);
+		CL_ASSERT(cdg_vertex_matrix[min_filled_lane][dest][next_switch2] != NULL);
+
+		cycle_found =
+		    cycle_exists(cdg_vertex_matrix[min_filled_lane][src][next_switch], NULL, NULL,
+				 1);
+		cycle_found2 =
+		    cycle_exists(cdg_vertex_matrix[min_filled_lane][dest][next_switch2], NULL, NULL,
+				 1);
+
+		for (i = 0; i < num_switches; i++)
+			for (j = 0; j < num_switches; j++)
+				if (cdg_vertex_matrix[min_filled_lane][i][j] != NULL) {
+					cdg_vertex_matrix[min_filled_lane][i][j]->visiting_number =
+					    0;
+					cdg_vertex_matrix[min_filled_lane][i][j]->seen = 0;
+				}
+
+		if (cycle_found == 1 || cycle_found2 == 1) {
+			remove_temp_depend_for_sp(p_lash, src, dest, min_filled_lane);
+			remove_temp_depend_for_sp(p_lash, dest, src, min_filled_lane);
+
+			virtual_location[src][dest][max_filled_lane] = 2;
+			virtual_location[dest][src][max_filled_lane] = 2;
+			trials--;
+			trials--;
+		} else {
+			set_temp_depend_to_permanent_for_sp(p_lash, src, dest, min_filled_lane);
+			set_temp_depend_to_permanent_for_sp(p_lash, dest, src, min_filled_lane);
+
+			num_mst_in_lane[max_filled_lane]--;
+			num_mst_in_lane[max_filled_lane]--;
+			num_mst_in_lane[min_filled_lane]++;
+			num_mst_in_lane[min_filled_lane]++;
+
+			remove_semipermanent_depend_for_sp(p_lash, src, dest, max_filled_lane);
+			remove_semipermanent_depend_for_sp(p_lash, dest, src, max_filled_lane);
+			virtual_location[src][dest][max_filled_lane] = 0;
+			virtual_location[dest][src][max_filled_lane] = 0;
+			virtual_location[src][dest][min_filled_lane] = 1;
+			virtual_location[dest][src][min_filled_lane] = 1;
+			p_lash->switches[src]->routing_table[dest].lane = min_filled_lane;
+			p_lash->switches[dest]->routing_table[src].lane = min_filled_lane;
+		}
+
+		if (trials == 0)
+			stop = 1;
+		else {
+			if (num_mst_in_lane[max_filled_lane] - num_mst_in_lane[min_filled_lane] <
+			    p_lash->balance_limit)
+				stop = 1;
+		}
+
+		old_min_filled_lane = min_filled_lane;
+		old_max_filled_lane = max_filled_lane;
+
+		new_num_min_lane = MAX_INT;
+		new_num_max_lane = 0;
+
+		for (i = 0; i < lanes_needed; i++) {
+
+			if (num_mst_in_lane[i] < new_num_min_lane) {
+				new_num_min_lane = num_mst_in_lane[i];
+				min_filled_lane = i;
+			}
+
+			if (num_mst_in_lane[i] > new_num_max_lane) {
+				new_num_max_lane = num_mst_in_lane[i];
+				max_filled_lane = i;
+			}
+		}
+
+		if (old_min_filled_lane != min_filled_lane) {
+			trials = num_mst_in_lane[max_filled_lane];
+			for (i = 0; i < num_switches; i++)
+				for (j = 0; j < num_switches; j++)
+					if (virtual_location[i][j][max_filled_lane] == 2)
+						virtual_location[i][j][max_filled_lane] = 1;
+		}
+
+		if (old_max_filled_lane != max_filled_lane) {
+			trials = num_mst_in_lane[max_filled_lane];
+			for (i = 0; i < num_switches; i++)
+				for (j = 0; j < num_switches; j++)
+					if (virtual_location[i][j][old_max_filled_lane] == 2)
+						virtual_location[i][j][old_max_filled_lane] = 1;
+		}
+	}
+}
+
+static switch_t *switch_create(lash_t * p_lash, unsigned id, osm_switch_t * p_sw)
+{
+	unsigned num_switches = p_lash->num_switches;
+	unsigned num_ports = p_sw->num_ports;
+	switch_t *sw;
+	unsigned int i;
+
+	sw = malloc(sizeof(*sw));
+	if (!sw)
+		return NULL;
+
+	memset(sw, 0, sizeof(*sw));
+
+	sw->id = id;
+	sw->dij_channels = malloc(num_ports * sizeof(int));
+	if (!sw->dij_channels) {
+		free(sw);
+		return NULL;
+	}
+
+	sw->virtual_physical_port_table = malloc(num_ports * sizeof(int));
+	if (!sw->virtual_physical_port_table) {
+		free(sw->dij_channels);
+		free(sw);
+		return NULL;
+	}
+
+	sw->phys_connections = malloc(num_ports * sizeof(int));
+	if (!sw->phys_connections) {
+		free(sw->virtual_physical_port_table);
+		free(sw->dij_channels);
+		free(sw);
+		return NULL;
+	}
+
+	sw->routing_table = malloc(num_switches * sizeof(sw->routing_table[0]));
+	if (!sw->routing_table) {
+		free(sw->phys_connections);
+		free(sw->virtual_physical_port_table);
+		free(sw->dij_channels);
+		free(sw);
+		return NULL;
+	}
+
+	for (i = 0; i < num_switches; i++) {
+		sw->routing_table[i].out_link = NONE;
+		sw->routing_table[i].lane = NONE;
+	}
+
+	for (i = 0; i < num_ports; i++) {
+		sw->virtual_physical_port_table[i] = -1;
+		sw->phys_connections[i] = NONE;
+	}
+
+	sw->p_sw = p_sw;
+	if (p_sw)
+		p_sw->priv = sw;
+
+	return sw;
+}
+
+static void switch_delete(switch_t * sw)
+{
+	if (sw->dij_channels)
+		free(sw->dij_channels);
+	if (sw->virtual_physical_port_table)
+		free(sw->virtual_physical_port_table);
+	if (sw->phys_connections)
+		free(sw->phys_connections);
+	if (sw->routing_table)
+		free(sw->routing_table);
+	free(sw);
+}
+
+static void free_lash_structures(lash_t * p_lash)
+{
+	unsigned int i, j, k;
+	unsigned num_switches = p_lash->num_switches;
+	osm_log_t *p_log = &p_lash->p_osm->log;
+
+	OSM_LOG_ENTER(p_log);
+
+	// free cdg_vertex_matrix
+	for (i = 0; i < p_lash->vl_min; i++) {
+		for (j = 0; j < num_switches; j++) {
+			for (k = 0; k < num_switches; k++) {
+				if (p_lash->cdg_vertex_matrix[i][j][k]) {
+
+					if (p_lash->cdg_vertex_matrix[i][j][k]->dependency)
+						free(p_lash->cdg_vertex_matrix[i][j][k]->
+						     dependency);
+
+					if (p_lash->cdg_vertex_matrix[i][j][k]->
+					    num_using_this_depend)
+						free(p_lash->cdg_vertex_matrix[i][j][k]->
+						     num_using_this_depend);
+
+					free(p_lash->cdg_vertex_matrix[i][j][k]);
+				}
+			}
+			if (p_lash->cdg_vertex_matrix[i][j])
+				free(p_lash->cdg_vertex_matrix[i][j]);
+		}
+		if (p_lash->cdg_vertex_matrix[i])
+			free(p_lash->cdg_vertex_matrix[i]);
+	}
+
+	if (p_lash->cdg_vertex_matrix)
+		free(p_lash->cdg_vertex_matrix);
+
+	// free virtual_location
+	for (i = 0; i < num_switches; i++) {
+		for (j = 0; j < num_switches; j++) {
+			if (p_lash->virtual_location[i][j])
+				free(p_lash->virtual_location[i][j]);
+		}
+		if (p_lash->virtual_location[i])
+			free(p_lash->virtual_location[i]);
+	}
+	if (p_lash->virtual_location)
+		free(p_lash->virtual_location);
+
+	if (p_lash->num_mst_in_lane)
+		free(p_lash->num_mst_in_lane);
+
+	OSM_LOG_EXIT(p_log);
+}
+
+static int init_lash_structures(lash_t * p_lash)
+{
+	unsigned vl_min = p_lash->vl_min;
+	unsigned num_switches = p_lash->num_switches;
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	int status = 0;
+	unsigned int i, j, k;
+
+	OSM_LOG_ENTER(p_log);
+
+	// initialise cdg_vertex_matrix[num_switches][num_switches][num_switches]
+	p_lash->cdg_vertex_matrix =
+	    (cdg_vertex_t ****) malloc(vl_min * sizeof(cdg_vertex_t ****));
+	for (i = 0; i < vl_min; i++) {
+		p_lash->cdg_vertex_matrix[i] =
+		    (cdg_vertex_t ***) malloc(num_switches *
+					      sizeof(cdg_vertex_t ***));
+
+		if (p_lash->cdg_vertex_matrix[i] == NULL)
+			goto Exit_Mem_Error;
+	}
+
+	for (i = 0; i < vl_min; i++) {
+		for (j = 0; j < num_switches; j++) {
+			p_lash->cdg_vertex_matrix[i][j] =
+			    (cdg_vertex_t **) malloc(num_switches *
+						     sizeof(cdg_vertex_t **));
+			if (p_lash->cdg_vertex_matrix[i][j] == NULL)
+				goto Exit_Mem_Error;
+
+			for (k = 0; k < num_switches; k++) {
+				p_lash->cdg_vertex_matrix[i][j][k] = NULL;
+			}
+		}
+	}
+
+	// initialise virtual_location[num_switches][num_switches][num_layers],
+	// default value = 0
+	p_lash->virtual_location =
+	    (int ***)malloc(num_switches * sizeof(int ***));
+	if (p_lash->virtual_location == NULL)
+		goto Exit_Mem_Error;
+
+	for (i = 0; i < num_switches; i++) {
+		p_lash->virtual_location[i] =
+		    (int **)malloc(num_switches * sizeof(int **));
+		if (p_lash->virtual_location[i] == NULL)
+			goto Exit_Mem_Error;
+	}
+
+	for (i = 0; i < num_switches; i++) {
+		for (j = 0; j < num_switches; j++) {
+			p_lash->virtual_location[i][j] =
+			    (int *)malloc(vl_min * sizeof(int *));
+			if (p_lash->virtual_location[i][j] == NULL)
+				goto Exit_Mem_Error;
+			for (k = 0; k < vl_min; k++) {
+				p_lash->virtual_location[i][j][k] = 0;
+			}
+		}
+	}
+
+	// initialise num_mst_in_lane[num_switches], default 0
+	p_lash->num_mst_in_lane = (int *)malloc(num_switches * sizeof(int));
+	if (p_lash->num_mst_in_lane == NULL)
+		goto Exit_Mem_Error;
+	memset(p_lash->num_mst_in_lane, 0,
+	       num_switches * sizeof(p_lash->num_mst_in_lane[0]));
+
+	goto Exit;
+
+Exit_Mem_Error:
+	status = -1;
+	OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D01: "
+		"Could not allocate required memory for LASH errno %d, errno %d for lack of memory\n",
+		errno, ENOMEM);
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+static int lash_core(lash_t * p_lash)
+{
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	unsigned num_switches = p_lash->num_switches;
+	switch_t **switches = p_lash->switches;
+	unsigned lanes_needed = 1;
+	unsigned int i, j, k, dest_switch = 0;
+	reachable_dest_t *dests, *idest;
+	int cycle_found = 0;
+	unsigned v_lane;
+	int stop = 0, output_link, i_next_switch;
+	int output_link2, i_next_switch2;
+	int cycle_found2 = 0;
+	int status = 0;
+	int *switch_bitmap;	/* Bitmap to check if we have processed this pair */
+
+	OSM_LOG_ENTER(p_log);
+
+	for (i = 0; i < num_switches; i++) {
+
+		shortest_path(p_lash, i);
+		generate_routing_func_for_mst(p_lash, i, &dests);
+
+		idest = dests;
+		while (idest != NULL) {
+			dests = dests->next;
+			free(idest);
+			idest = dests;
+		}
+
+		for (j = 0; j < num_switches; j++) {
+			switches[j]->used_channels = 0;
+			switches[j]->q_state = UNQUEUED;
+		}
+	}
+
+	switch_bitmap = malloc(num_switches * num_switches * sizeof(int));
+	if (!switch_bitmap) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D04: "
+			"Failed allocating switch_bitmap - out of memory\n");
+		goto Exit;
+	}
+	memset(switch_bitmap, 0, num_switches * num_switches * sizeof(int));
+
+	for (i = 0; i < num_switches; i++) {
+		for (dest_switch = 0; dest_switch < num_switches; dest_switch++)
+			if (dest_switch != i && switch_bitmap[i * num_switches + dest_switch] == 0) {
+				v_lane = 0;
+				stop = 0;
+				while (v_lane < lanes_needed && stop == 0) {
+					generate_cdg_for_sp(p_lash, i, dest_switch, v_lane);
+					generate_cdg_for_sp(p_lash, dest_switch, i, v_lane);
+
+					output_link =
+					    switches[i]->routing_table[dest_switch].out_link;
+					output_link2 =
+					    switches[dest_switch]->routing_table[i].out_link;
+
+					i_next_switch = switches[i]->phys_connections[output_link];
+					i_next_switch2 =
+					    switches[dest_switch]->phys_connections[output_link2];
+
+					CL_ASSERT(p_lash->
+						  cdg_vertex_matrix[v_lane][i][i_next_switch] !=
+						  NULL);
+					CL_ASSERT(p_lash->
+						  cdg_vertex_matrix[v_lane][dest_switch]
+						  [i_next_switch2] != NULL);
+
+					cycle_found =
+					    cycle_exists(p_lash->
+							 cdg_vertex_matrix[v_lane][i]
+							 [i_next_switch], NULL, NULL, 1);
+					cycle_found2 =
+					    cycle_exists(p_lash->
+							 cdg_vertex_matrix[v_lane][dest_switch]
+							 [i_next_switch2], NULL, NULL, 1);
+
+					for (j = 0; j < num_switches; j++)
+						for (k = 0; k < num_switches; k++)
+							if (p_lash->
+							    cdg_vertex_matrix[v_lane][j][k] !=
+							    NULL) {
+								p_lash->
+								    cdg_vertex_matrix[v_lane][j]
+								    [k]->visiting_number = 0;
+								p_lash->
+								    cdg_vertex_matrix[v_lane][j]
+								    [k]->seen = 0;
+							}
+
+					if (cycle_found == 1 || cycle_found2 == 1) {
+						remove_temp_depend_for_sp(p_lash, i, dest_switch,
+									  v_lane);
+						remove_temp_depend_for_sp(p_lash, dest_switch, i,
+									  v_lane);
+						v_lane++;
+					} else {
+						set_temp_depend_to_permanent_for_sp(p_lash, i,
+										    dest_switch,
+										    v_lane);
+						set_temp_depend_to_permanent_for_sp(p_lash,
+										    dest_switch, i,
+										    v_lane);
+						stop = 1;
+						p_lash->num_mst_in_lane[v_lane]++;
+						p_lash->num_mst_in_lane[v_lane]++;
+					}
+				}
+
+				switches[i]->routing_table[dest_switch].lane = v_lane;
+				switches[dest_switch]->routing_table[i].lane = v_lane;
+
+				if (cycle_found == 1 || cycle_found2 == 1) {
+					if (++lanes_needed > p_lash->vl_min)
+						goto Error_Not_Enough_Lanes;
+
+					generate_cdg_for_sp(p_lash, i, dest_switch, v_lane);
+					generate_cdg_for_sp(p_lash, dest_switch, i, v_lane);
+
+					set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch,
+									    v_lane);
+					set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i,
+									    v_lane);
+
+					p_lash->num_mst_in_lane[v_lane]++;
+					p_lash->num_mst_in_lane[v_lane]++;
+				}
+				p_lash->virtual_location[i][dest_switch][v_lane] = 1;
+				p_lash->virtual_location[dest_switch][i][v_lane] = 1;
+
+				switch_bitmap[i * num_switches + dest_switch] = 1;
+				switch_bitmap[dest_switch * num_switches + i] = 1;
+			}
+	}
+
+	OSM_LOG(p_log, OSM_LOG_INFO,
+		"Lanes needed: %d, Balancing\n", lanes_needed);
+
+	for (i = 0; i < lanes_needed; i++) {
+		OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n",
+			i, p_lash->num_mst_in_lane[i]);
+	}
+
+	balance_virtual_lanes(p_lash, lanes_needed);
+
+	for (i = 0; i < lanes_needed; i++) {
+		OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n",
+			i, p_lash->num_mst_in_lane[i]);
+	}
+
+	goto Exit;
+
+Error_Not_Enough_Lanes:
+	status = -1;
+	OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D02: "
+		"Lane requirements (%d) exceed available lanes (%d)\n",
+		p_lash->vl_min, lanes_needed);
+Exit:
+	if (switch_bitmap)
+		free(switch_bitmap);
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+static unsigned get_lash_id(osm_switch_t * p_sw)
+{
+	return ((switch_t *) p_sw->priv)->id;
+}
+
+static void populate_fwd_tbls(lash_t * p_lash)
+{
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	osm_subn_t *p_subn = &p_lash->p_osm->subn;
+	osm_opensm_t *p_osm = p_lash->p_osm;
+	osm_switch_t *p_sw, *p_next_sw, *p_dst_sw;
+	osm_port_t *port;
+	uint16_t max_lid_ho, lid;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
+
+	// Go through each swtich individually
+	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
+		uint64_t current_guid;
+		switch_t *sw;
+		p_sw = p_next_sw;
+		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+
+		max_lid_ho = p_sw->max_lid_ho;
+		current_guid = p_sw->p_node->node_info.port_guid;
+		sw = p_sw->priv;
+
+		memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+		for (lid = 1; lid <= max_lid_ho; lid++) {
+			port = cl_ptr_vector_get(&p_subn->port_lid_tbl, lid);
+			if (!port)
+				continue;
+
+			p_dst_sw = get_osm_switch_from_port(port);
+			if (p_dst_sw == p_sw) {
+				uint8_t egress_port = port->p_node->sw ? 0 :
+					port->p_physp->p_remote_physp->port_num;
+				p_sw->new_lft[lid] = egress_port;
+				OSM_LOG(p_log, OSM_LOG_VERBOSE,
+					"LASH fwd MY SRC SRC GUID 0x%016" PRIx64
+					" src lash id (%d), src lid no (%u) src lash port (%d) "
+					"DST GUID 0x%016" PRIx64
+					" src lash id (%d), src lash port (%d)\n",
+					cl_ntoh64(current_guid), -1, lid,
+					egress_port, cl_ntoh64(current_guid),
+					-1, egress_port);
+			} else if (p_dst_sw) {
+				unsigned dst_lash_switch_id =
+				    get_lash_id(p_dst_sw);
+				uint8_t lash_egress_port =
+				    (uint8_t) sw->
+				    routing_table[dst_lash_switch_id].out_link;
+				uint8_t physical_egress_port =
+				    (uint8_t) sw->
+				    virtual_physical_port_table
+				    [lash_egress_port];
+
+				p_sw->new_lft[lid] = physical_egress_port;
+				OSM_LOG(p_log, OSM_LOG_VERBOSE,
+					"LASH fwd SRC GUID 0x%016" PRIx64
+					" src lash id (%d), "
+					"src lid no (%u) src lash port (%d) "
+					"DST GUID 0x%016" PRIx64
+					" src lash id (%d), src lash port (%d)\n",
+					cl_ntoh64(current_guid), sw->id, lid,
+					lash_egress_port,
+					cl_ntoh64(p_dst_sw->p_node->node_info.
+						  port_guid),
+					dst_lash_switch_id,
+					physical_egress_port);
+			}
+		}		// for
+		osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
+	}
+	OSM_LOG_EXIT(p_log);
+}
+
+static void osm_lash_process_switch(lash_t * p_lash, osm_switch_t * p_sw)
+{
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	int i, port_count;
+	osm_physp_t *p_current_physp, *p_remote_physp;
+	unsigned switch_a_lash_id, switch_b_lash_id;
+
+	OSM_LOG_ENTER(p_log);
+
+	switch_a_lash_id = get_lash_id(p_sw);
+	port_count = osm_node_get_num_physp(p_sw->p_node);
+
+	// starting at port 1, ignoring management port on switch
+	for (i = 1; i < port_count; i++) {
+
+		p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i);
+		if (p_current_physp) {
+			p_remote_physp = p_current_physp->p_remote_physp;
+			if (p_remote_physp && p_remote_physp->p_node->sw) {
+				int physical_port_a_num =
+				    osm_physp_get_port_num(p_current_physp);
+				int physical_port_b_num =
+				    osm_physp_get_port_num(p_remote_physp);
+				switch_b_lash_id =
+				    get_lash_id(p_remote_physp->p_node->sw);
+
+				connect_switches(p_lash, switch_a_lash_id,
+						 switch_b_lash_id,
+						 physical_port_a_num);
+				OSM_LOG(p_log, OSM_LOG_VERBOSE,
+					"LASH SUCCESS connected G 0x%016" PRIx64
+					" , lash_id(%u), P(%u) " " to G 0x%016"
+					PRIx64 " , lash_id(%u) , P(%u)\n",
+					cl_ntoh64(osm_physp_get_port_guid
+						  (p_current_physp)),
+					switch_a_lash_id, physical_port_a_num,
+					cl_ntoh64(osm_physp_get_port_guid
+						  (p_remote_physp)),
+					switch_b_lash_id, physical_port_b_num);
+			}
+		}
+	}
+
+	OSM_LOG_EXIT(p_log);
+}
+
+static void lash_cleanup(lash_t * p_lash)
+{
+	osm_subn_t *p_subn = &p_lash->p_osm->subn;
+	osm_switch_t *p_next_sw, *p_sw;
+
+	/* drop any existing references to old lash switches */
+	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
+	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+		p_sw->priv = NULL;
+	}
+
+	if (p_lash->switches) {
+		unsigned id;
+		for (id = 0; ((int)id) < p_lash->num_switches; id++)
+			if (p_lash->switches[id])
+				switch_delete(p_lash->switches[id]);
+		free(p_lash->switches);
+	}
+	p_lash->switches = NULL;
+}
+
+/*
+  static int  discover_network_properties()
+  Traverse the topology of the network in order to determine
+   - the maximum number of switches,
+   - the minimum number of virtual layers
+*/
+
+static int discover_network_properties(lash_t * p_lash)
+{
+	int i = 0, id = 0;
+	uint8_t vl_min;
+	osm_subn_t *p_subn = &p_lash->p_osm->subn;
+	osm_switch_t *p_next_sw, *p_sw;
+	osm_log_t *p_log = &p_lash->p_osm->log;
+
+	p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl);
+
+	p_lash->switches = malloc(p_lash->num_switches * sizeof(switch_t *));
+	if (!p_lash->switches)
+		return -1;
+	memset(p_lash->switches, 0, p_lash->num_switches * sizeof(switch_t *));
+
+	vl_min = 5;		// set to a high value
+
+	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
+	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
+		uint16_t port_count;
+		p_sw = p_next_sw;
+		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+
+		p_lash->switches[id] = switch_create(p_lash, id, p_sw);
+		if (!p_lash->switches[id])
+			return -1;
+		id++;
+
+		port_count = osm_node_get_num_physp(p_sw->p_node);
+
+		// Note, ignoring port 0. management port
+		for (i = 1; i < port_count; i++) {
+			osm_physp_t *p_current_physp =
+			    osm_node_get_physp_ptr(p_sw->p_node, i);
+
+			if (p_current_physp
+			    && p_current_physp->p_remote_physp) {
+
+				ib_port_info_t *p_port_info =
+				    &p_current_physp->port_info;
+				uint8_t port_vl_min =
+				    ib_port_info_get_op_vls(p_port_info);
+				if (port_vl_min && port_vl_min < vl_min)
+					vl_min = port_vl_min;
+			}
+		}		// for
+	}			// while
+
+	vl_min = 1 << (vl_min - 1);
+	if (vl_min > 15)
+		vl_min = 15;
+
+	p_lash->vl_min = vl_min;
+
+	OSM_LOG(p_log, OSM_LOG_INFO,
+		"min operational vl(%d) max_switches(%d)\n", p_lash->vl_min,
+		p_lash->num_switches);
+	return 0;
+}
+
+static void process_switches(lash_t * p_lash)
+{
+	osm_switch_t *p_sw, *p_next_sw;
+	osm_subn_t *p_subn = &p_lash->p_osm->subn;
+
+	/* Go through each swithc and process it. i.e build the connection
+	   structure required by LASH */
+	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
+	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+
+		osm_lash_process_switch(p_lash, p_sw);
+	}
+}
+
+static int lash_process(void *context)
+{
+	lash_t *p_lash = context;
+	osm_log_t *p_log = &p_lash->p_osm->log;
+	int return_status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_lash->balance_limit = 6;
+
+	// everything starts here
+	lash_cleanup(p_lash);
+
+	discover_network_properties(p_lash);
+
+	return_status = init_lash_structures(p_lash);
+	if (return_status != IB_SUCCESS)
+		goto Exit;
+
+	process_switches(p_lash);
+
+	return_status = lash_core(p_lash);
+	if (return_status != IB_SUCCESS)
+		goto Exit;
+
+	populate_fwd_tbls(p_lash);
+
+Exit:
+	free_lash_structures(p_lash);
+	OSM_LOG_EXIT(p_log);
+
+	return return_status;
+}
+
+static lash_t *lash_create(osm_opensm_t * p_osm)
+{
+	lash_t *p_lash;
+
+	p_lash = malloc(sizeof(lash_t));
+	if (!p_lash)
+		return NULL;
+
+	memset(p_lash, 0, sizeof(lash_t));
+	p_lash->p_osm = p_osm;
+
+	return (p_lash);
+}
+
+static void lash_delete(void *context)
+{
+	lash_t *p_lash = context;
+	if (p_lash->switches) {
+		unsigned id;
+		for (id = 0; ((int)id) < p_lash->num_switches; id++)
+			if (p_lash->switches[id])
+				switch_delete(p_lash->switches[id]);
+		free(p_lash->switches);
+	}
+	free(p_lash);
+}
+
+uint8_t osm_get_lash_sl(osm_opensm_t * p_osm, osm_port_t * p_src_port,
+			osm_port_t * p_dst_port)
+{
+	unsigned dst_id;
+	unsigned src_id;
+	osm_switch_t *p_sw;
+
+	if (p_osm->routing_engine_used != OSM_ROUTING_ENGINE_TYPE_LASH)
+		return OSM_DEFAULT_SL;
+
+	p_sw = get_osm_switch_from_port(p_dst_port);
+	if (!p_sw || !p_sw->priv)
+		return OSM_DEFAULT_SL;
+	dst_id = get_lash_id(p_sw);
+
+	p_sw = get_osm_switch_from_port(p_src_port);
+	if (!p_sw || !p_sw->priv)
+		return OSM_DEFAULT_SL;
+
+	src_id = get_lash_id(p_sw);
+	if (src_id == dst_id)
+		return OSM_DEFAULT_SL;
+
+	return (uint8_t) ((switch_t *) p_sw->priv)->routing_table[dst_id].lane;
+}
+
+int osm_ucast_lash_setup(struct osm_routing_engine *r, osm_opensm_t *p_osm)
+{
+	lash_t *p_lash = lash_create(p_osm);
+	if (!p_lash)
+		return -1;
+
+	r->context = p_lash;
+	r->ucast_build_fwd_tables = lash_process;
+	r->delete = lash_delete;
+
+	return 0;
+}
diff --git a/opensm/osm_ucast_mgr.c b/opensm/osm_ucast_mgr.c
new file mode 100644
index 0000000..371c99a
--- /dev/null
+++ b/opensm/osm_ucast_mgr.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_ucast_mgr_t.
+ * This file implements the Unicast Manager object.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_sm.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>
+
+/**********************************************************************
+ **********************************************************************/
+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);
+
+	if (p_mgr->cache_valid)
+		osm_ucast_cache_invalidate(p_mgr);
+
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ucast_mgr_init(IN osm_ucast_mgr_t * const p_mgr, IN osm_sm_t * sm)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	osm_ucast_mgr_construct(p_mgr);
+
+	p_mgr->sm = sm;
+	p_mgr->p_log = sm->p_log;
+	p_mgr->p_subn = sm->p_subn;
+	p_mgr->p_lock = sm->p_lock;
+
+	if (sm->p_subn->opt.use_ucast_cache)
+		cl_qmap_init(&p_mgr->cache_sw_tbl);
+
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return (status);
+}
+
+/**********************************************************************
+ Add each switch's own and neighbor LIDs to its LID matrix
+**********************************************************************/
+static void
+__osm_ucast_mgr_process_hop_0_1(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_node_t *p_remote_node;
+	uint16_t lid, remote_lid;
+	uint8_t i, remote_port;
+
+	lid = osm_node_get_base_lid(p_sw->p_node, 0);
+	lid = cl_ntoh16(lid);
+	osm_switch_set_hops(p_sw, lid, 0, 0);
+
+	for (i = 1; i < p_sw->num_ports; i++) {
+		p_remote_node =
+		    osm_node_get_remote_node(p_sw->p_node, i, &remote_port);
+
+		if (p_remote_node && p_remote_node->sw &&
+		    (p_remote_node != p_sw->p_node)) {
+			remote_lid = osm_node_get_base_lid(p_remote_node, 0);
+			remote_lid = cl_ntoh16(remote_lid);
+			osm_switch_set_hops(p_sw, remote_lid, i, 1);
+			osm_switch_set_hops(p_remote_node->sw, lid, remote_port,
+					    1);
+		}
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * const p_mgr,
+				 IN osm_switch_t * const p_this_sw,
+				 IN osm_switch_t * const p_remote_sw,
+				 IN const uint8_t port_num,
+				 IN const uint8_t remote_port_num)
+{
+	osm_switch_t *p_sw, *p_next_sw;
+	uint16_t lid_ho;
+	uint8_t hops;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Node 0x%" PRIx64 ", remote node 0x%" PRIx64
+		", port %u, remote port %u\n",
+		cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
+		cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
+		port_num, remote_port_num);
+
+	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
+	while (p_next_sw !=
+	       (osm_switch_t *) cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl)) {
+		p_sw = p_next_sw;
+		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
+		lid_ho = osm_node_get_base_lid(p_sw->p_node, 0);
+		lid_ho = cl_ntoh16(lid_ho);
+		hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
+		if (hops == OSM_NO_PATH)
+			continue;
+		hops++;
+		if (hops <
+		    osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
+			if (osm_switch_set_hops
+			    (p_this_sw, lid_ho, port_num, hops) != 0)
+				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
+					"cannot set hops for lid %u at switch 0x%"
+					PRIx64 "\n", lid_ho,
+					cl_ntoh64(osm_node_get_node_guid
+						  (p_this_sw->p_node)));
+			p_mgr->some_hop_count_set = TRUE;
+		}
+	}
+
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static struct osm_remote_node *
+find_and_add_remote_sys(osm_switch_t *sw, uint8_t port,
+			struct osm_remote_guids_count *r)
+{
+	unsigned i;
+	osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
+	osm_node_t *node = p->p_remote_physp->p_node;
+
+	for (i = 0; i < r->count; i++)
+		if (r->guids[i].node == node)
+			return &r->guids[i];
+
+	r->guids[i].node = node;
+	r->guids[i].forwarded_to = 0;
+	r->count++;
+	return &r->guids[i];
+}
+
+static void
+__osm_ucast_mgr_process_port(IN osm_ucast_mgr_t * const p_mgr,
+			     IN osm_switch_t * const p_sw,
+			     IN osm_port_t * const p_port,
+			     IN unsigned lid_offset)
+{
+	uint16_t min_lid_ho;
+	uint16_t max_lid_ho;
+	uint16_t lid_ho;
+	uint8_t port;
+	boolean_t is_ignored_by_port_prof;
+	ib_net64_t node_guid;
+	unsigned start_from = 1;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
+
+	/* If the lids are zero - then there was some problem with
+	 * the initialization. Don't handle this port. */
+	if (min_lid_ho == 0 || max_lid_ho == 0) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
+			"Port 0x%" PRIx64 " has LID 0. An initialization "
+			"error occurred. Ignoring port\n",
+			cl_ntoh64(osm_port_get_guid(p_port)));
+		goto Exit;
+	}
+
+	lid_ho = min_lid_ho + lid_offset;
+
+	if (lid_ho > max_lid_ho)
+		goto Exit;
+
+	if (lid_offset)
+		/* ignore potential overflow - it is handled in osm_switch.c */
+		start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1) + 1;
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Processing port 0x%" PRIx64 " (\'%s\' port %u), LID %u [%u,%u]\n",
+		cl_ntoh64(osm_port_get_guid(p_port)),
+		p_port->p_node->print_desc, p_port->p_physp->port_num,
+		lid_ho, min_lid_ho, max_lid_ho);
+
+	/* TODO - This should be runtime error, not a CL_ASSERT() */
+	CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO);
+
+	node_guid = osm_node_get_node_guid(p_sw->p_node);
+
+	/*
+	   The lid matrix contains the number of hops to each
+	   lid from each port.  From this information we determine
+	   how best to distribute the LID range across the ports
+	   that can reach those LIDs.
+	 */
+	port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
+					 p_mgr->p_subn->ignore_existing_lfts,
+					 p_mgr->is_dor);
+
+	if (port == OSM_NO_PATH) {
+		/* do not try to overwrite the ppro of non existing port ... */
+		is_ignored_by_port_prof = TRUE;
+
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"No path to get to LID %u from switch 0x%" PRIx64 "\n",
+			lid_ho, cl_ntoh64(node_guid));
+	} else {
+		osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
+
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Routing LID %u to port %u"
+			" for switch 0x%" PRIx64 "\n",
+			lid_ho, port, cl_ntoh64(node_guid));
+
+		/*
+		   we would like to optionally ignore this port in equalization
+		   as in the case of the Mellanox Anafa Internal PCI TCA port
+		 */
+		is_ignored_by_port_prof = p->is_prof_ignored;
+
+		/*
+		   We also would ignore this route if the target lid is of
+		   a switch and the port_profile_switch_node is not TRUE
+		 */
+		if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
+			is_ignored_by_port_prof |=
+			    (osm_node_get_type(p_port->p_node) ==
+			     IB_NODE_TYPE_SWITCH);
+	}
+
+	/*
+	   We have selected the port for this LID.
+	   Write it to the forwarding tables.
+	 */
+	p_sw->new_lft[lid_ho] = port;
+	if (!is_ignored_by_port_prof) {
+		struct osm_remote_node *rem_node_used;
+		osm_switch_count_path(p_sw, port);
+		if (port > 0 && p_port->priv &&
+		    (rem_node_used = find_and_add_remote_sys(p_sw, port,
+							     p_port->priv)))
+			rem_node_used->forwarded_to++;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int 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;
+	uint16_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);
+
+	CL_ASSERT(p_sw);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(p_node);
+
+	p_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));
+
+	/*
+	   Set the top of the unicast forwarding table.
+	 */
+	si = p_sw->switch_info;
+	lin_top = cl_hton16(p_sw->max_lid_ho);
+	if (lin_top != si.lin_top) {
+		set_swinfo_require = TRUE;
+		si.lin_top = lin_top;
+	}
+
+	/* 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) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Setting switch FT top to LID %u\n", p_sw->max_lid_ho);
+
+		context.si_context.light_sweep = FALSE;
+		context.si_context.node_guid = osm_node_get_node_guid(p_node);
+		context.si_context.set_method = TRUE;
+
+		status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
+				     sizeof(si),
+				     IB_MAD_ATTR_SWITCH_INFO,
+				     0, CL_DISP_MSGID_NONE, &context);
+
+		if (status != IB_SUCCESS)
+			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
+				"Sending SwitchInfo attribute failed (%s)\n",
+				ib_get_err_str(status));
+	}
+
+	/*
+	   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;
+
+	if (!p_sw->new_lft) {
+		/* any routing should provide the new_lft */
+		CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
+			  p_mgr->cache_valid && !p_sw->need_update);
+		goto Exit;
+	}
+
+	for (block_id_ho = 0;
+	     osm_switch_get_lft_block(p_sw, block_id_ho, block);
+	     block_id_ho++) {
+		if (!p_sw->need_update && !p_mgr->p_subn->need_update &&
+		    !memcmp(block,
+			    p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
+			    IB_SMP_DATA_SIZE))
+			continue;
+
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Writing FT block %u\n", block_id_ho);
+
+		status = osm_req_set(p_mgr->sm, p_path,
+				     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
+				     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, "ERR 3A05: "
+				"Sending linear fwd. tbl. block failed (%s)\n",
+				ib_get_err_str(status));
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void alloc_ports_priv(osm_ucast_mgr_t *mgr)
+{
+	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
+	struct osm_remote_guids_count *r;
+	osm_port_t *port;
+	cl_map_item_t *item;
+	unsigned lmc;
+
+	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
+	     item = cl_qmap_next(item)) {
+		port = (osm_port_t *)item;
+		lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
+		if (!lmc)
+			continue;
+		r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
+		if (!r) {
+			OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
+				"cannot allocate memory to track remote"
+				" systems for lmc > 0\n");
+			port->priv = NULL;
+			continue;
+		}
+		memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
+		port->priv = r;
+	}
+}
+
+static void free_ports_priv(osm_ucast_mgr_t *mgr)
+{
+	cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
+	osm_port_t *port;
+	cl_map_item_t *item;
+	for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
+	     item = cl_qmap_next(item)) {
+		port = (osm_port_t *)item;
+		if (port->priv) {
+			free(port->priv);
+			port->priv = NULL;
+		}
+	}
+}
+
+static void
+__osm_ucast_mgr_process_tbl(IN cl_map_item_t * const p_map_item,
+			    IN void *context)
+{
+	osm_ucast_mgr_t *p_mgr = context;
+	osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
+	unsigned i, lids_per_port;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	CL_ASSERT(p_sw && p_sw->p_node);
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Processing switch 0x%" PRIx64 "\n",
+		cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
+
+	/* Initialize LIDs in buffer to invalid port number. */
+	memset(p_sw->new_lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);
+
+	if (p_mgr->p_subn->opt.lmc)
+		alloc_ports_priv(p_mgr);
+
+	/*
+	   Iterate through every port setting LID routes for each
+	   port based on base LID and LMC value.
+	 */
+	lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
+	for (i = 0; i < lids_per_port; i++) {
+		cl_qlist_t *list = &p_mgr->port_order_list;
+		cl_list_item_t *item;
+		for (item = cl_qlist_head(list); item != cl_qlist_end(list);
+		     item = cl_qlist_next(item)) {
+			osm_port_t *port = cl_item_obj(item, port, list_item);
+			__osm_ucast_mgr_process_port(p_mgr, p_sw, port, i);
+		}
+	}
+
+	osm_ucast_mgr_set_fwd_table(p_mgr, p_sw);
+
+	if (p_mgr->p_subn->opt.lmc)
+		free_ports_priv(p_mgr);
+
+	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);
+
+	p_node = p_sw->p_node;
+
+	CL_ASSERT(p_node);
+	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+		"Processing switch with GUID 0x%" PRIx64 "\n",
+		cl_ntoh64(osm_node_get_node_guid(p_node)));
+
+	num_ports = osm_node_get_num_physp(p_node);
+
+	/*
+	   Start with port 1 to skip the switch's management port.
+	 */
+	for (port_num = 1; port_num < num_ports; port_num++) {
+		p_remote_node = osm_node_get_remote_node(p_node,
+							 (uint8_t) port_num,
+							 &remote_port_num);
+
+		if (p_remote_node && p_remote_node->sw
+		    && (p_remote_node != p_node)) {
+			/* make sure the link is healthy. If it is not - don't
+			   propagate through it. */
+			p_physp = osm_node_get_physp_ptr(p_node, port_num);
+			if (!p_physp || !osm_link_is_healthy(p_physp))
+				continue;
+
+			__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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int 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,
+		"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_1, p_mgr);
+
+	/*
+	   Get the switch matrices for each switch's neighbors.
+	   This process requires a number of iterations equal to
+	   the number of switches in the subnet minus 1.
+
+	   In each iteration, a switch learns the lid/port/hop
+	   information (as contained by a switch's lid matrix) from
+	   its immediate neighbors.  After each iteration, a switch
+	   (and it's neighbors) know more routing information than
+	   it did on the previous iteration.
+	   Thus, by repeatedly absorbing the routing information of
+	   neighbor switches, every switch eventually learns how to
+	   route all LIDs on the subnet.
+
+	   Note that there may not be any switches in the subnet if
+	   we are in simple p2p configuration.
+	 */
+	iteration_max = cl_qmap_count(p_sw_guid_tbl);
+
+	/*
+	   If there are switches in the subnet, iterate until the lid
+	   matrix has been constructed.  Otherwise, just immediately
+	   indicate we're done if no switches exist.
+	 */
+	if (iteration_max) {
+		iteration_max--;
+
+		/*
+		   we need to find out when the propagation of
+		   hop counts has relaxed. So this global variable
+		   is preset to 0 on each iteration and if
+		   if non of the switches was set will exit the
+		   while loop
+		 */
+		p_mgr->some_hop_count_set = TRUE;
+		for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
+		     i++) {
+			p_mgr->some_hop_count_set = FALSE;
+			cl_qmap_apply_func(p_sw_guid_tbl,
+					   __osm_ucast_mgr_process_neighbors,
+					   p_mgr);
+		}
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Min-hop propagated in %d steps\n", i);
+	}
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
+{
+	osm_switch_t *p_sw;
+	uint16_t lids;
+
+	lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);
+	lids = lids ? lids - 1 : 0;
+
+	for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
+	     p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl);
+	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
+		if (osm_switch_prepare_path_rebuild(p_sw, lids)) {
+			OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: "
+				"cannot setup switch 0x%016" PRIx64 "\n",
+				cl_ntoh64(osm_node_get_node_guid
+					  (p_sw->p_node)));
+			return -1;
+		}
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
+{
+	osm_ucast_mgr_t *m = ctx;
+	osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
+
+	if (!port) {
+		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+			"port guid not found: 0x%016" PRIx64 "\n", guid);
+		return 0;
+	}
+
+	if (port->flag) {
+		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+			"port guid specified multiple times 0x%016" PRIx64 "\n",
+			guid);
+		return 0;
+	}
+
+	cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
+	port->flag = 1;
+
+	return 0;
+}
+
+static void add_port_to_order_list(cl_map_item_t * const p_map_item, void *ctx)
+{
+	osm_port_t *port = (osm_port_t *)p_map_item;
+	osm_ucast_mgr_t *m = ctx;
+
+	if (!port->flag)
+		cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
+	else
+		port->flag = 0;
+}
+
+static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
+{
+	osm_ucast_mgr_t *m = ctx;
+	osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
+	osm_physp_t *physp;
+	unsigned port;
+
+	if (!node || !node->sw) {
+		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+			"switch with guid 0x%016" PRIx64 " is not found\n",
+			guid);
+		return 0;
+	}
+
+	if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
+	    port >= node->sw->num_ports) {
+		OSM_LOG(m->p_log, OSM_LOG_DEBUG,
+			"bad port specified for guid 0x%016" PRIx64 "\n", guid);
+		return 0;
+	}
+
+	physp = osm_node_get_physp_ptr(node, port);
+	if (!physp)
+		return 0;
+
+	physp->is_prof_ignored = 1;
+
+	return 0;
+}
+
+static void clear_prof_ignore_flag(cl_map_item_t * const p_map_item, void *ctx)
+{
+	osm_switch_t *sw = (osm_switch_t *)p_map_item;
+	int i;
+
+	for (i = 1; i < sw->num_ports; i++) {
+		osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
+		if (p)
+			p->is_prof_ignored = 0;
+	}
+}
+
+static int ucast_mgr_build_lfts(osm_ucast_mgr_t *p_mgr)
+{
+	cl_qlist_init(&p_mgr->port_order_list);
+
+	if (p_mgr->p_subn->opt.guid_routing_order_file) {
+		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
+			"Fetching guid routing order file \'%s\'\n",
+			p_mgr->p_subn->opt.guid_routing_order_file);
+
+		if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
+				   add_guid_to_order_list, p_mgr))
+			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
+				"cannot parse guid routing order file \'%s\'\n",
+				p_mgr->p_subn->opt.guid_routing_order_file);
+	}
+
+	if (p_mgr->p_subn->opt.port_prof_ignore_file) {
+		cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+				   clear_prof_ignore_flag, NULL);
+		if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
+				   mark_ignored_port, p_mgr)) {
+			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR : "
+				"cannot parse port prof ignore file \'%s\'\n",
+				p_mgr->p_subn->opt.port_prof_ignore_file);
+		}
+	}
+
+	cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
+			   add_port_to_order_list, p_mgr);
+
+	cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+			   __osm_ucast_mgr_process_tbl, p_mgr);
+
+	cl_qlist_remove_all(&p_mgr->port_order_list);
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t *osm)
+{
+	int ret;
+
+	OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
+		"building routing with \'%s\' routing algorithm...\n", r->name);
+
+	if (!r->build_lid_matrices ||
+	    (ret = r->build_lid_matrices(r->context)) > 0)
+		ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr);
+
+	if (ret < 0) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"%s: cannot build lid matrices.\n", r->name);
+		return ret;
+	}
+
+	if (!r->ucast_build_fwd_tables ||
+	    (ret = r->ucast_build_fwd_tables(r->context)) > 0)
+		ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr);
+
+	if (ret < 0) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"%s: cannot build fwd tables.\n", r->name);
+		return ret;
+	}
+
+	osm->routing_engine_used = osm_routing_engine_type(r->name);
+
+	return 0;
+}
+
+int osm_ucast_mgr_process(IN osm_ucast_mgr_t * const p_mgr)
+{
+	osm_opensm_t *p_osm;
+	struct osm_routing_engine *p_routing_eng;
+	cl_qmap_t *p_sw_guid_tbl;
+
+	OSM_LOG_ENTER(p_mgr->p_log);
+
+	p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+	p_osm = p_mgr->p_subn->p_osm;
+	p_routing_eng = p_osm->routing_engine_list;
+
+	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
+
+	/*
+	   If there are no switches in the subnet, we are done.
+	 */
+	if (cl_qmap_count(p_sw_guid_tbl) == 0 ||
+	    ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0)
+		goto Exit;
+
+	p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_NONE;
+	while (p_routing_eng) {
+		if (!ucast_mgr_route(p_routing_eng, p_osm))
+			break;
+		p_routing_eng = p_routing_eng->next;
+	}
+
+	if (p_osm->routing_engine_used == OSM_ROUTING_ENGINE_TYPE_NONE) {
+		/* If configured routing algorithm failed, use default MinHop */
+		osm_ucast_mgr_build_lid_matrices(p_mgr);
+		ucast_mgr_build_lfts(p_mgr);
+		p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_MINHOP;
+	}
+
+	OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
+		"%s tables configured on all switches\n",
+		osm_routing_engine_type_str(p_osm->routing_engine_used));
+
+        if (p_mgr->p_subn->opt.use_ucast_cache)
+		p_mgr->cache_valid = TRUE;
+
+Exit:
+	CL_PLOCK_RELEASE(p_mgr->p_lock);
+	OSM_LOG_EXIT(p_mgr->p_log);
+	return 0;
+}
+
+static int ucast_build_lid_matrices(void *context)
+{
+	return osm_ucast_mgr_build_lid_matrices(context);
+}
+
+static int ucast_build_lfts(void *context)
+{
+	return ucast_mgr_build_lfts(context);
+}
+
+int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
+{
+	r->context = &osm->sm.ucast_mgr;
+	r->build_lid_matrices = ucast_build_lid_matrices;
+	r->ucast_build_fwd_tables = ucast_build_lfts;
+	return 0;
+}
+
+static int ucast_dor_build_lfts(void *context)
+{
+	osm_ucast_mgr_t *mgr = context;
+	int ret;
+
+	mgr->is_dor = 1;
+	ret = ucast_mgr_build_lfts(mgr);
+	mgr->is_dor = 0;
+
+	return ret;
+}
+
+int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
+{
+	r->context = &osm->sm.ucast_mgr;
+	r->build_lid_matrices = ucast_build_lid_matrices;
+	r->ucast_build_fwd_tables = ucast_dor_build_lfts;
+	return 0;
+}
diff --git a/opensm/osm_ucast_updn.c b/opensm/osm_ucast_updn.c
new file mode 100644
index 0000000..bb9ccda
--- /dev/null
+++ b/opensm/osm_ucast_updn.c
@@ -0,0 +1,686 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *      Implementation of Up Down Algorithm using ranking & Min Hop
+ *      Calculation functions
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_ucast_mgr.h>
+
+/* //////////////////////////// */
+/*  Local types                 */
+/* //////////////////////////// */
+
+/* direction */
+typedef enum updn_switch_dir {
+	UP = 0,
+	DOWN
+} updn_switch_dir_t;
+
+/* updn structure */
+typedef struct updn {
+	unsigned num_roots;
+	osm_opensm_t *p_osm;
+} updn_t;
+
+struct updn_node {
+	cl_list_item_t list;
+	osm_switch_t *sw;
+	uint64_t id;
+	updn_switch_dir_t dir;
+	unsigned rank;
+	unsigned visited;
+};
+
+/**********************************************************************
+ **********************************************************************/
+/* This function returns direction based on rank and guid info of current &
+   remote ports */
+static updn_switch_dir_t updn_get_dir(unsigned cur_rank, unsigned rem_rank,
+				      uint64_t cur_id, uint64_t rem_id)
+{
+	/* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect
+	   directly, but in case they are we assign to root node an UP direction to allow UPDN to discover
+	   the subnet correctly (and not from the point of view of the last root node).
+	 */
+	if (!cur_rank && !rem_rank)
+		return UP;
+
+	if (cur_rank < rem_rank)
+		return DOWN;
+	else if (cur_rank > rem_rank)
+		return UP;
+	else {
+		/* Equal rank, decide by id number, bigger == UP direction */
+		if (cur_id > rem_id)
+			return UP;
+		else
+			return DOWN;
+	}
+}
+
+/**********************************************************************
+ * This function does the bfs of min hop table calculation by guid index
+ * as a starting point.
+ **********************************************************************/
+static int updn_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn,
+			    IN osm_switch_t * p_sw)
+{
+	uint8_t pn, pn_rem;
+	cl_qlist_t list;
+	uint16_t lid;
+	struct updn_node *u;
+	updn_switch_dir_t next_dir, current_dir;
+
+	OSM_LOG_ENTER(p_log);
+
+	lid = osm_node_get_base_lid(p_sw->p_node, 0);
+	lid = cl_ntoh16(lid);
+	osm_switch_set_hops(p_sw, lid, 0, 0);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Starting from switch - port GUID 0x%" PRIx64 " lid %u\n",
+		cl_ntoh64(p_sw->p_node->node_info.port_guid), lid);
+
+	u = p_sw->priv;
+	u->dir = UP;
+
+	/* Update list with the new element */
+	cl_qlist_init(&list);
+	cl_qlist_insert_tail(&list, &u->list);
+
+	/* BFS the list till no next element */
+	while (!cl_is_qlist_empty(&list)) {
+		u = (struct updn_node *)cl_qlist_remove_head(&list);
+		u->visited = 0;	/* cleanup */
+		current_dir = u->dir;
+		/* Go over all ports of the switch and find unvisited remote nodes */
+		for (pn = 1; pn < u->sw->num_ports; pn++) {
+			osm_node_t *p_remote_node;
+			struct updn_node *rem_u;
+			uint8_t current_min_hop, remote_min_hop,
+			    set_hop_return_value;
+			osm_switch_t *p_remote_sw;
+
+			p_remote_node =
+			    osm_node_get_remote_node(u->sw->p_node, pn,
+						     &pn_rem);
+			/* If no remote node OR remote node is not a SWITCH
+			   continue to next pn */
+			if (!p_remote_node || !p_remote_node->sw)
+				continue;
+			/* Fetch remote guid only after validation of remote node */
+			p_remote_sw = p_remote_node->sw;
+			rem_u = p_remote_sw->priv;
+			/* Decide which direction to mark it (UP/DOWN) */
+			next_dir = updn_get_dir(u->rank, rem_u->rank,
+						u->id, rem_u->id);
+
+			/* Check if this is a legal step : the only illegal step is going
+			   from DOWN to UP */
+			if ((current_dir == DOWN) && (next_dir == UP)) {
+				OSM_LOG(p_log, OSM_LOG_DEBUG,
+					"Avoiding move from 0x%016" PRIx64
+					" to 0x%016" PRIx64 "\n",
+					cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)),
+					cl_ntoh64(osm_node_get_node_guid(p_remote_node)));
+				/* Illegal step */
+				continue;
+			}
+			/* Set MinHop value for the current lid */
+			current_min_hop = osm_switch_get_least_hops(u->sw, lid);
+			/* Check hop count if better insert into list && update
+			   the remote node Min Hop Table */
+			remote_min_hop =
+			    osm_switch_get_hop_count(p_remote_sw, lid, pn_rem);
+			if (current_min_hop + 1 < remote_min_hop) {
+				set_hop_return_value =
+				    osm_switch_set_hops(p_remote_sw, lid,
+							pn_rem,
+							current_min_hop + 1);
+				if (set_hop_return_value) {
+					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AA01: "
+						"Invalid value returned from set min hop is: %d\n",
+						set_hop_return_value);
+				}
+				/* Check if remote port has already been visited */
+				if (!rem_u->visited) {
+					/* Insert updn_switch item into the list */
+					rem_u->dir = next_dir;
+					rem_u->visited = 1;
+					cl_qlist_insert_tail(&list,
+							     &rem_u->list);
+				}
+			}
+		}
+	}
+
+	OSM_LOG_EXIT(p_log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* NOTE : PLS check if we need to decide that the first */
+/*        rank is a SWITCH for BFS purpose */
+static int updn_subn_rank(IN updn_t * p_updn)
+{
+	osm_switch_t *p_sw;
+	osm_physp_t *p_physp, *p_remote_physp;
+	cl_qlist_t list;
+	cl_map_item_t *item;
+	struct updn_node *u, *remote_u;
+	uint8_t num_ports, port_num;
+	osm_log_t *p_log = &p_updn->p_osm->log;
+	unsigned max_rank = 0;
+
+	OSM_LOG_ENTER(p_log);
+	cl_qlist_init(&list);
+
+	/* add all roots to the list */
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *)item;
+		u = p_sw->priv;
+		if (!u->rank)
+			cl_qlist_insert_tail(&list, &u->list);
+	}
+
+	/* BFS the list till it's empty */
+	while (!cl_is_qlist_empty(&list)) {
+		u = (struct updn_node *)cl_qlist_remove_head(&list);
+		/* Go over all remote nodes and rank them (if not already visited) */
+		p_sw = u->sw;
+		num_ports = p_sw->num_ports;
+		OSM_LOG(p_log, OSM_LOG_DEBUG,
+			"Handling switch GUID 0x%" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
+		for (port_num = 1; port_num < num_ports; port_num++) {
+			ib_net64_t port_guid;
+
+			/* Current port fetched in order to get remote side */
+			p_physp =
+			    osm_node_get_physp_ptr(p_sw->p_node, port_num);
+
+			if (!p_physp)
+				continue;
+
+			p_remote_physp = p_physp->p_remote_physp;
+
+			/*
+			   make sure that all the following occur on p_remote_physp:
+			   1. The port isn't NULL
+			   2. It is a switch
+			 */
+			if (p_remote_physp && p_remote_physp->p_node->sw) {
+				remote_u = p_remote_physp->p_node->sw->priv;
+				port_guid = p_remote_physp->port_guid;
+
+				if (remote_u->rank > u->rank + 1) {
+					remote_u->rank = u->rank + 1;
+					max_rank = remote_u->rank;
+					cl_qlist_insert_tail(&list,
+							     &remote_u->list);
+					OSM_LOG(p_log, OSM_LOG_DEBUG,
+						"Rank of port GUID 0x%" PRIx64
+						" = %u\n", cl_ntoh64(port_guid),
+						remote_u->rank);
+				}
+			}
+		}
+	}
+
+	/* Print Summary of ranking */
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"Subnet ranking completed. Max Node Rank = %d\n", max_rank);
+	OSM_LOG_EXIT(p_log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* hack: preserve min hops entries to any other root switches */
+static void updn_clear_root_hops(updn_t * p_updn, osm_switch_t * p_sw)
+{
+	osm_port_t *p_port;
+	unsigned i;
+
+	for (i = 0; i < p_sw->num_hops; i++)
+		if (p_sw->hops[i]) {
+			p_port =
+			    cl_ptr_vector_get(&p_updn->p_osm->subn.port_lid_tbl,
+					      i);
+			if (!p_port || !p_port->p_node->sw
+			    || ((struct updn_node *)p_port->p_node->sw->priv)->
+			    rank != 0)
+				memset(p_sw->hops[i], 0xff, p_sw->num_ports);
+		}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int updn_set_min_hop_table(IN updn_t * p_updn)
+{
+	osm_subn_t *p_subn = &p_updn->p_osm->subn;
+	osm_log_t *p_log = &p_updn->p_osm->log;
+	osm_switch_t *p_sw;
+	cl_map_item_t *item;
+
+	OSM_LOG_ENTER(p_log);
+
+	/* Go over all the switches in the subnet - for each init their Min Hop
+	   Table */
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"Init Min Hop Table of all switches [\n");
+
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *)item;
+		/* Clear Min Hop Table */
+		if (p_subn->opt.connect_roots)
+			updn_clear_root_hops(p_updn, p_sw);
+		else
+			osm_switch_clear_hops(p_sw);
+	}
+
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"Init Min Hop Table of all switches ]\n");
+
+	/* Now do the BFS for each port  in the subnet */
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"BFS through all port guids in the subnet [\n");
+
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *)item;
+		updn_bfs_by_node(p_log, p_subn, p_sw);
+	}
+
+	OSM_LOG(p_log, OSM_LOG_VERBOSE,
+		"BFS through all port guids in the subnet ]\n");
+	/* Cleanup */
+	OSM_LOG_EXIT(p_log);
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int updn_build_lid_matrices(IN updn_t * p_updn)
+{
+	int status;
+
+	OSM_LOG_ENTER(&p_updn->p_osm->log);
+
+	OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE,
+		"Ranking all port guids in the list\n");
+	if (!p_updn->num_roots) {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0A: "
+			"No guids were provided or number of guids is 0\n");
+		status = -1;
+		goto _exit;
+	}
+
+	/* Check if it's not a switched subnet */
+	if (cl_is_qmap_empty(&p_updn->p_osm->subn.sw_guid_tbl)) {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AAOB: "
+			"This is not a switched subnet, cannot perform UPDN algorithm\n");
+		status = -1;
+		goto _exit;
+	}
+
+	/* Rank the subnet switches */
+	updn_subn_rank(p_updn);
+
+	/* After multiple ranking need to set Min Hop Table by UpDn algorithm  */
+	OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE,
+		"Setting all switches' Min Hop Table\n");
+	status = updn_set_min_hop_table(p_updn);
+
+_exit:
+	OSM_LOG_EXIT(&p_updn->p_osm->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static struct updn_node *create_updn_node(osm_switch_t * sw)
+{
+	struct updn_node *u;
+
+	u = malloc(sizeof(*u));
+	if (!u)
+		return NULL;
+	memset(u, 0, sizeof(*u));
+	u->sw = sw;
+	u->id = cl_ntoh64(osm_node_get_node_guid(sw->p_node));
+	u->rank = 0xffffffff;
+	return u;
+}
+
+static void delete_updn_node(struct updn_node *u)
+{
+	u->sw->priv = NULL;
+	free(u);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Find Root nodes automatically by Min Hop Table info */
+static void updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn)
+{
+	osm_opensm_t *p_osm = p_updn->p_osm;
+	osm_switch_t *p_sw;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	cl_map_item_t *item;
+	double thd1, thd2;
+	unsigned i, cas_num = 0;
+	unsigned *cas_per_sw;
+	uint16_t lid_ho;
+
+	OSM_LOG_ENTER(&p_osm->log);
+
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+		"Current number of ports in the subnet is %d\n",
+		cl_qmap_count(&p_osm->subn.port_guid_tbl));
+
+	cas_per_sw = malloc((IB_LID_UCAST_END_HO + 1) * sizeof(*cas_per_sw));
+	if (!cas_per_sw) {
+		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR AA14: "
+			"cannot alloc mem for CAs per switch counter array\n");
+		goto _exit;
+	}
+	memset(cas_per_sw, 0, (IB_LID_UCAST_END_HO + 1) * sizeof(*cas_per_sw));
+
+	/* Find the Maximum number of CAs (and routers) for histogram normalization */
+	OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+		"Finding the number of CAs and storing them in cl_map\n");
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.port_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.port_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_port = (osm_port_t *)item;
+		if (!p_port->p_node->sw) {
+			p_physp = p_port->p_physp->p_remote_physp;
+			if (!p_physp || !p_physp->p_node->sw)
+				continue;
+			lid_ho = osm_node_get_base_lid(p_physp->p_node, 0);
+			lid_ho = cl_ntoh16(lid_ho);
+			cas_per_sw[lid_ho]++;
+			cas_num++;
+		}
+	}
+
+	thd1 = cas_num * 0.9;
+	thd2 = cas_num * 0.05;
+	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+		"Found %u CAs and RTRs, %u SWs in the subnet. "
+		"Thresholds are thd1 = %f && thd2 = %f\n",
+		cas_num, cl_qmap_count(&p_osm->subn.sw_guid_tbl), thd1, thd2);
+
+	OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
+		"Passing through all switches to collect Min Hop info\n");
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		unsigned hop_hist[IB_SUBNET_PATH_HOPS_MAX];
+		uint16_t max_lid_ho;
+		uint8_t hop_val;
+		uint16_t numHopBarsOverThd1 = 0;
+		uint16_t numHopBarsOverThd2 = 0;
+
+		p_sw = (osm_switch_t *) item;
+
+		memset(hop_hist, 0, sizeof(hop_hist));
+
+		max_lid_ho = p_sw->max_lid_ho;
+		for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++)
+			if (cas_per_sw[lid_ho]) {
+				hop_val =
+				    osm_switch_get_least_hops(p_sw, lid_ho);
+				if (hop_val >= IB_SUBNET_PATH_HOPS_MAX)
+					continue;
+
+				hop_hist[hop_val] += cas_per_sw[lid_ho];
+			}
+
+		/* Now recognize the spines by requiring one bar to be
+		   above 90% of the number of CAs and RTRs */
+		for (i = 0; i < IB_SUBNET_PATH_HOPS_MAX; i++) {
+			if (hop_hist[i] > thd1)
+				numHopBarsOverThd1++;
+			if (hop_hist[i] > thd2)
+				numHopBarsOverThd2++;
+		}
+
+		/* If thd conditions are valid - rank the root node */
+		if (numHopBarsOverThd1 == 1 && numHopBarsOverThd2 == 1) {
+			OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
+				"Ranking GUID 0x%" PRIx64 " as root node\n",
+				cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
+			((struct updn_node *)p_sw->priv)->rank = 0;
+			p_updn->num_roots++;
+		}
+	}
+
+	free(cas_per_sw);
+_exit:
+	OSM_LOG_EXIT(&p_osm->log);
+	return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void dump_roots(cl_map_item_t *item, FILE *file, void *cxt)
+{
+	osm_switch_t *sw = (osm_switch_t *)item;
+	if (!((struct updn_node *)sw->priv)->rank)
+		fprintf(file, "0x%" PRIx64 "\n",
+			cl_ntoh64(osm_node_get_node_guid(sw->p_node)));
+}
+
+static int update_id(void *cxt, uint64_t guid, char *p)
+{
+	osm_opensm_t *osm = cxt;
+	osm_switch_t *sw;
+	uint64_t id;
+	char *e;
+
+	sw = osm_get_switch_by_guid(&osm->subn, cl_hton64(guid));
+	if (!sw) {
+		OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
+			"switch with guid 0x%" PRIx64 " is not found\n", guid);
+		return 0;
+	}
+
+	id = strtoull(p, &e, 0);
+	if (*e && !isspace(*e)) {
+		OSM_LOG(&osm->log, OSM_LOG_ERROR,
+			"ERR: cannot parse node id \'%s\'", p);
+		return -1;
+	}
+
+	OSM_LOG(&osm->log, OSM_LOG_DEBUG,
+		"update node 0x%" PRIx64 " id to 0x%" PRIx64 "\n", guid, id);
+
+	((struct updn_node *)sw->priv)->id = id;
+
+	return 0;
+}
+
+static int rank_root_node(void *cxt, uint64_t guid, char *p)
+{
+	updn_t *updn = cxt;
+	osm_switch_t *sw;
+
+	sw = osm_get_switch_by_guid(&updn->p_osm->subn, cl_hton64(guid));
+	if (!sw) {
+		OSM_LOG(&updn->p_osm->log, OSM_LOG_VERBOSE,
+			"switch with guid 0x%" PRIx64 " is not found\n", guid);
+		return 0;
+	}
+
+	OSM_LOG(&updn->p_osm->log, OSM_LOG_DEBUG,
+		"Ranking root port GUID 0x%" PRIx64 "\n", guid);
+
+	((struct updn_node *)sw->priv)->rank = 0;
+	updn->num_roots++;
+
+	return 0;
+}
+
+/* UPDN callback function */
+static int updn_lid_matrices(void *ctx)
+{
+	updn_t *p_updn = ctx;
+	cl_map_item_t *item;
+	osm_switch_t *p_sw;
+	int ret = 0;
+
+	OSM_LOG_ENTER(&p_updn->p_osm->log);
+
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *)item;
+		p_sw->priv = create_updn_node(p_sw);
+		if (!p_sw->priv) {
+			OSM_LOG(&(p_updn->p_osm->log), OSM_LOG_ERROR, "ERR AA0C: "
+				"cannot create updn node\n");
+			OSM_LOG_EXIT(&p_updn->p_osm->log);
+			return -1;
+		}
+	}
+
+	/* First setup root nodes */
+	p_updn->num_roots = 0;
+
+	if (p_updn->p_osm->subn.opt.root_guid_file) {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
+			"UPDN - Fetching root nodes from file \'%s\'\n",
+			p_updn->p_osm->subn.opt.root_guid_file);
+
+		ret = parse_node_map(p_updn->p_osm->subn.opt.root_guid_file,
+				     rank_root_node, p_updn);
+		if (ret)
+			OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR : "
+				"cannot parse root guids file \'%s\'\n",
+				p_updn->p_osm->subn.opt.root_guid_file);
+		if (p_updn->p_osm->subn.opt.connect_roots &&
+		    p_updn->num_roots > 1)
+			osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
+	} else {
+		osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
+		updn_find_root_nodes_by_min_hop(p_updn);
+	}
+
+	if (p_updn->p_osm->subn.opt.ids_guid_file) {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
+			"UPDN - update node ids from file \'%s\'\n",
+			p_updn->p_osm->subn.opt.ids_guid_file);
+
+		ret = parse_node_map(p_updn->p_osm->subn.opt.ids_guid_file,
+				     update_id, p_updn->p_osm);
+		if (ret)
+			OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR : "
+				"cannot parse node ids file \'%s\'\n",
+				p_updn->p_osm->subn.opt.ids_guid_file);
+	}
+
+	/* Only if there are assigned root nodes do the algorithm, otherwise perform do nothing */
+	if (p_updn->num_roots) {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
+			"activating UPDN algorithm\n");
+		ret = updn_build_lid_matrices(p_updn);
+	} else {
+		OSM_LOG(&p_updn->p_osm->log, OSM_LOG_INFO,
+			"disabling UPDN algorithm, no root nodes were found\n");
+		ret = -1;
+	}
+
+	if (osm_log_is_active(&p_updn->p_osm->log, OSM_LOG_ROUTING))
+		osm_dump_qmap_to_file(p_updn->p_osm, "opensm-updn-roots.dump",
+				      &p_updn->p_osm->subn.sw_guid_tbl,
+				      dump_roots, NULL);
+
+	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
+	     item = cl_qmap_next(item)) {
+		p_sw = (osm_switch_t *) item;
+		delete_updn_node(p_sw->priv);
+	}
+
+	OSM_LOG_EXIT(&p_updn->p_osm->log);
+	return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void updn_delete(void *context)
+{
+	free(context);
+}
+
+int osm_ucast_updn_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
+{
+	updn_t *updn;
+
+	updn = malloc(sizeof(updn_t));
+	if (!updn)
+		return -1;
+	memset(updn, 0, sizeof(updn_t));
+
+	updn->p_osm = osm;
+
+	r->context = updn;
+	r->delete = updn_delete;
+	r->build_lid_matrices = updn_lid_matrices;
+
+	return 0;
+}
diff --git a/opensm/osm_vl15intf.c b/opensm/osm_vl15intf.c
new file mode 100644
index 0000000..0703a4f
--- /dev/null
+++ b/opensm/osm_vl15intf.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_vl15_t.
+ * This object represents the VL15 Interface object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_thread.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+
+static void vl15_send_mad(osm_vl15_t * p_vl, osm_madw_t * p_madw)
+{
+	ib_api_status_t status;
+
+	/*
+	   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.
+		 */
+		cl_atomic_inc(&p_vl->p_stats->qp0_mads_outstanding_on_wire);
+	else
+		cl_atomic_inc(&p_vl->p_stats->qp0_unicasts_sent);
+
+	cl_atomic_inc(&p_vl->p_stats->qp0_mads_sent);
+
+	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
+				 p_madw, p_madw->resp_expected);
+
+	if (status == IB_SUCCESS) {
+		OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+			"%u QP0 MADs on wire, %u outstanding, "
+			"%u unicasts sent, %u total sent\n",
+			p_vl->p_stats->qp0_mads_outstanding_on_wire,
+			p_vl->p_stats->qp0_mads_outstanding,
+			p_vl->p_stats->qp0_unicasts_sent,
+			p_vl->p_stats->qp0_mads_sent);
+		return;
+	}
+
+	OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E03: "
+		"MAD send failed (%s)\n", ib_get_err_str(status));
+
+	/*
+	   The MAD was never successfully sent, so
+	   fix up the pre-incremented count values.
+	 */
+
+	/* Decrement qp0_mads_sent that were incremented in the code above.
+	   qp0_mads_outstanding will be decremented by send error callback
+	   (called by osm_vendor_send() */
+	cl_atomic_dec(&p_vl->p_stats->qp0_mads_sent);
+	if (!p_madw->resp_expected)
+		cl_atomic_dec(&p_vl->p_stats->qp0_unicasts_sent);
+}
+
+static void __osm_vl15_poller(IN void *p_ptr)
+{
+	ib_api_status_t status;
+	osm_madw_t *p_madw;
+	osm_vl15_t *const p_vl = (osm_vl15_t *) p_ptr;
+	cl_qlist_t *p_fifo;
+
+	OSM_LOG_ENTER(p_vl->p_log);
+
+	if (p_vl->thread_state == OSM_THREAD_STATE_NONE)
+		p_vl->thread_state = OSM_THREAD_STATE_RUN;
+
+	while (p_vl->thread_state == OSM_THREAD_STATE_RUN) {
+		/*
+		   Start servicing the FIFOs by pulling off MAD wrappers
+		   and passing them to the transport interface.
+		   There are lots of corner cases here so tread carefully.
+
+		   The unicast FIFO has priority, since somebody is waiting
+		   for a timely response.
+		 */
+		cl_spinlock_acquire(&p_vl->lock);
+
+		if (cl_qlist_count(&p_vl->ufifo) != 0)
+			p_fifo = &p_vl->ufifo;
+		else
+			p_fifo = &p_vl->rfifo;
+
+		p_madw = (osm_madw_t *) cl_qlist_remove_head(p_fifo);
+
+		cl_spinlock_release(&p_vl->lock);
+
+		if (p_madw != (osm_madw_t *) cl_qlist_end(p_fifo)) {
+			OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+				"Servicing p_madw = %p\n", p_madw);
+			if (osm_log_is_active(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);
+
+			vl15_send_mad(p_vl, p_madw);
+		} else
+			/*
+			   The VL15 FIFO is empty, so we have nothing left to do.
+			 */
+			status = cl_event_wait_on(&p_vl->signal,
+						  EVENT_NO_TIMEOUT, TRUE);
+
+		while ((p_vl->p_stats->qp0_mads_outstanding_on_wire >=
+			(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, "ERR 3E02: "
+					"Event wait failed (%s)\n",
+					CL_STATUS_MSG(status));
+				break;
+			}
+		}
+	}
+
+	/*
+	   since we abort immediately when the state != OSM_THREAD_STATE_RUN
+	   we might have some mads on the queues. After the thread exits
+	   the vl15 destroy routine should put these mads back...
+	 */
+
+	OSM_LOG_EXIT(p_vl->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vl15_construct(IN osm_vl15_t * 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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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);
+
+	/*
+	   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)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	p_vl->p_vend = p_vend;
+	p_vl->p_log = p_log;
+	p_vl->p_stats = p_stats;
+	p_vl->max_wire_smps = max_wire_smps;
+
+	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;
+
+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);
+
+	CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
+
+	/*
+	   If we have room for more VL15 MADs on the wire,
+	   then signal the poller thread.
+
+	   This is not an airtight check, since the poller thread
+	   could be just about to send another MAD as we signal
+	   the event here.  To cover this rare case, the poller
+	   thread checks for a spurious wake-up.
+	 */
+	if (p_vl->p_stats->qp0_mads_outstanding_on_wire <
+	    (int32_t) p_vl->max_wire_smps) {
+		OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+			"Signalling poller thread\n");
+		cl_event_signal(&p_vl->signal);
+	}
+
+	OSM_LOG_EXIT(p_vl->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_vl15_post(IN osm_vl15_t * const p_vl, IN osm_madw_t * const p_madw)
+{
+	OSM_LOG_ENTER(p_vl->p_log);
+
+	CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
+
+	OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Posting p_madw = 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, &p_madw->list_item);
+		osm_stats_inc_qp0_outstanding(p_vl->p_stats);
+	} else
+		cl_qlist_insert_tail(&p_vl->ufifo, &p_madw->list_item);
+	cl_spinlock_release(&p_vl->lock);
+
+	OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+		"%u QP0 MADs on wire, %u QP0 MADs outstanding\n",
+		p_vl->p_stats->qp0_mads_outstanding_on_wire,
+		p_vl->p_stats->qp0_mads_outstanding);
+
+	osm_vl15_poll(p_vl);
+
+	OSM_LOG_EXIT(p_vl->p_log);
+}
+
+void
+osm_vl15_shutdown(IN osm_vl15_t * const p_vl,
+		  IN osm_mad_pool_t * const p_mad_pool)
+{
+	osm_madw_t *p_madw;
+
+	OSM_LOG_ENTER(p_vl->p_log);
+
+	/* we only should get here after the VL15 interface was initialized */
+	CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
+
+	/* grap a lock on the object */
+	cl_spinlock_acquire(&p_vl->lock);
+
+	/* go over all outstanding MADs and retire their transactions */
+
+	/* first we handle the list of response MADs */
+	p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
+	while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->ufifo)) {
+		OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+			"Releasing Response p_madw = %p\n", p_madw);
+
+		osm_mad_pool_put(p_mad_pool, p_madw);
+
+		p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
+	}
+
+	/* Request MADs we send out */
+	p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
+	while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->rfifo)) {
+		OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
+			"Releasing Request p_madw = %p\n", p_madw);
+
+		osm_mad_pool_put(p_mad_pool, p_madw);
+		osm_stats_dec_qp0_outstanding(p_vl->p_stats);
+
+		p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
+	}
+
+	/* free the lock */
+	cl_spinlock_release(&p_vl->lock);
+
+	OSM_LOG_EXIT(p_vl->p_log);
+}
diff --git a/opensm/osm_vl_arb_rcv.c b/opensm/osm_vl_arb_rcv.c
new file mode 100644
index 0000000..ec04d67
--- /dev/null
+++ b/opensm/osm_vl_arb_rcv.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of osm_vla_rcv_t.
+ * This object represents the Vl Arbitration Receiver object.
+ * This object is part of the opensm family of objects.
+ */
+
+#if HAVE_CONFIG_H
+#  include <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 <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void osm_vla_rcv_process(IN void *context, IN void *data)
+{
+	osm_sm_t *sm = context;
+	osm_madw_t *p_madw = data;
+	ib_vl_arb_table_t *p_vla_tbl;
+	ib_smp_t *p_smp;
+	osm_port_t *p_port;
+	osm_physp_t *p_physp;
+	osm_node_t *p_node;
+	osm_vla_context_t *p_context;
+	ib_net64_t port_guid;
+	ib_net64_t node_guid;
+	uint8_t port_num, block_num;
+
+	CL_ASSERT(sm);
+
+	OSM_LOG_ENTER(sm->p_log);
+
+	CL_ASSERT(p_madw);
+
+	p_smp = osm_madw_get_smp_ptr(p_madw);
+
+	p_context = osm_madw_get_vla_context_ptr(p_madw);
+	p_vla_tbl = (ib_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);
+
+	cl_plock_excl_acquire(sm->p_lock);
+	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
+	if (!p_port) {
+		cl_plock_release(sm->p_lock);
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3F06: "
+			"No port object for port with GUID 0x%" PRIx64
+			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+			", TID 0x%" PRIx64 "\n",
+			cl_ntoh64(port_guid),
+			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+		goto Exit;
+	}
+
+	p_node = p_port->p_node;
+	CL_ASSERT(p_node);
+
+	block_num = (uint8_t) (cl_ntoh32(p_smp->attr_mod) >> 16);
+	/* in case of a non switch node the attr modifier should be ignored */
+	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {
+		port_num = (uint8_t) (cl_ntoh32(p_smp->attr_mod) & 0x000000FF);
+		p_physp = osm_node_get_physp_ptr(p_node, port_num);
+	} else {
+		p_physp = p_port->p_physp;
+		port_num = p_physp->port_num;
+	}
+
+	/*
+	   We do not mind if this is a result of a set or get - all we want is to update
+	   the subnet.
+	 */
+	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
+		"Got GetResp(VLArb) block:%u port_num %u with GUID 0x%"
+		PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%"
+		PRIx64 "\n", block_num, port_num, cl_ntoh64(port_guid),
+		cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
+
+	/*
+	   Determine if we encountered a new Physical Port.
+	   If so, Ignore it.
+	 */
+	if (!p_physp) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"Got invalid port number %u\n", port_num);
+		goto Exit;
+	}
+
+	osm_dump_vl_arb_table(sm->p_log,
+			      port_guid, block_num,
+			      port_num, p_vla_tbl, OSM_LOG_DEBUG);
+
+	if ((block_num < 1) || (block_num > 4)) {
+		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
+			"Got invalid block number 0x%X\n", block_num);
+		goto Exit;
+	}
+	osm_physp_set_vla_tbl(p_physp, p_vla_tbl, block_num);
+
+Exit:
+	cl_plock_release(sm->p_lock);
+
+	OSM_LOG_EXIT(sm->p_log);
+}
diff --git a/opensm/st.c b/opensm/st.c
new file mode 100644
index 0000000..c5a2f53
--- /dev/null
+++ b/opensm/st.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/* static   char  sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
+
+#if HAVE_CONFIG_H
+#  include <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;
+}
diff --git a/osmeventplugin/Makefile.am b/osmeventplugin/Makefile.am
new file mode 100644
index 0000000..79e3d55
--- /dev/null
+++ b/osmeventplugin/Makefile.am
@@ -0,0 +1,34 @@
+
+INCLUDES = -I$(srcdir)/../include \
+	   -I$(includedir)/infiniband
+
+lib_LTLIBRARIES = libosmeventplugin.la
+
+if DEBUG
+DBGFLAGS = -ggdb -D_DEBUG_
+else
+DBGFLAGS = -g
+endif
+
+libosmeventplugin_la_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+
+if HAVE_LD_VERSION_SCRIPT
+    libosmeventplugin_version_script = -Wl,--version-script=$(srcdir)/libosmeventplugin.map
+else
+    libosmeventplugin_version_script =
+endif
+
+osmeventplugin_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmeventplugin.ver | sed 's/LIBVERSION=//')
+
+libosmeventplugin_la_SOURCES = src/osmeventplugin.c
+libosmeventplugin_la_LDFLAGS = -version-info $(osmeventplugin_api_version) \
+	 -export-dynamic $(libosmeventplugin_version_script)
+libosmeventplugin_la_LIBADD = -L../complib $(OSMV_LDADD) -losmcomp
+libosmeventplugin_la_DEPENDENCIES = $(srcdir)/libosmeventplugin.map
+
+libosmeventpluginincludedir = $(includedir)/infiniband/complib
+
+libosmeventplugininclude_HEADERS =
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmeventplugin.map $(srcdir)/libosmeventplugin.ver
diff --git a/osmeventplugin/Makefile.in b/osmeventplugin/Makefile.in
new file mode 100644
index 0000000..4c2dd80
--- /dev/null
+++ b/osmeventplugin/Makefile.in
@@ -0,0 +1,545 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = osmeventplugin
+DIST_COMMON = $(libosmeventplugininclude_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+	"$(DESTDIR)$(libosmeventpluginincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_libosmeventplugin_la_OBJECTS =  \
+	libosmeventplugin_la-osmeventplugin.lo
+libosmeventplugin_la_OBJECTS = $(am_libosmeventplugin_la_OBJECTS)
+libosmeventplugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(libosmeventplugin_la_CFLAGS) $(CFLAGS) \
+	$(libosmeventplugin_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libosmeventplugin_la_SOURCES)
+DIST_SOURCES = $(libosmeventplugin_la_SOURCES)
+libosmeventpluginincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libosmeventplugininclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I$(srcdir)/../include \
+	   -I$(includedir)/infiniband
+
+lib_LTLIBRARIES = libosmeventplugin.la
+ at DEBUG_FALSE@DBGFLAGS = -g
+ at DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_
+libosmeventplugin_la_CFLAGS = -Wall $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+ at HAVE_LD_VERSION_SCRIPT_FALSE@libosmeventplugin_version_script = 
+ at HAVE_LD_VERSION_SCRIPT_TRUE@libosmeventplugin_version_script = -Wl,--version-script=$(srcdir)/libosmeventplugin.map
+osmeventplugin_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmeventplugin.ver | sed 's/LIBVERSION=//')
+libosmeventplugin_la_SOURCES = src/osmeventplugin.c
+libosmeventplugin_la_LDFLAGS = -version-info $(osmeventplugin_api_version) \
+	 -export-dynamic $(libosmeventplugin_version_script)
+
+libosmeventplugin_la_LIBADD = -L../complib $(OSMV_LDADD) -losmcomp
+libosmeventplugin_la_DEPENDENCIES = $(srcdir)/libosmeventplugin.map
+libosmeventpluginincludedir = $(includedir)/infiniband/complib
+libosmeventplugininclude_HEADERS = 
+
+# headers are distributed as part of the include dir
+EXTRA_DIST = $(srcdir)/libosmeventplugin.map $(srcdir)/libosmeventplugin.ver
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  osmeventplugin/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  osmeventplugin/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libosmeventplugin.la: $(libosmeventplugin_la_OBJECTS) $(libosmeventplugin_la_DEPENDENCIES) 
+	$(libosmeventplugin_la_LINK) -rpath $(libdir) $(libosmeventplugin_la_OBJECTS) $(libosmeventplugin_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libosmeventplugin_la-osmeventplugin.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libosmeventplugin_la-osmeventplugin.lo: src/osmeventplugin.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmeventplugin_la_CFLAGS) $(CFLAGS) -MT libosmeventplugin_la-osmeventplugin.lo -MD -MP -MF $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Tpo -c -o libosmeventplugin_la-osmeventplugin.lo `test -f 'src/osmeventplugin.c' || echo '$(srcdir)/'`src/osmeventplugin.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Tpo $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='src/osmeventplugin.c' object='libosmeventplugin_la-osmeventplugin.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmeventplugin_la_CFLAGS) $(CFLAGS) -c -o libosmeventplugin_la-osmeventplugin.lo `test -f 'src/osmeventplugin.c' || echo '$(srcdir)/'`src/osmeventplugin.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-libosmeventpluginincludeHEADERS: $(libosmeventplugininclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libosmeventpluginincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmeventpluginincludedir)"
+	@list='$(libosmeventplugininclude_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libosmeventpluginincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libosmeventpluginincludedir)/$$f'"; \
+	  $(libosmeventpluginincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libosmeventpluginincludedir)/$$f"; \
+	done
+
+uninstall-libosmeventpluginincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libosmeventplugininclude_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libosmeventpluginincludedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libosmeventpluginincludedir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmeventpluginincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libosmeventpluginincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES \
+	uninstall-libosmeventpluginincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-libosmeventpluginincludeHEADERS \
+	install-man install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-libLTLIBRARIES \
+	uninstall-libosmeventpluginincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/osmeventplugin/libosmeventplugin.map b/osmeventplugin/libosmeventplugin.map
new file mode 100644
index 0000000..346d1f3
--- /dev/null
+++ b/osmeventplugin/libosmeventplugin.map
@@ -0,0 +1,5 @@
+OSMPMDB_1.0 {
+	global:
+	osm_event_plugin;
+	local: *;
+};
diff --git a/osmeventplugin/libosmeventplugin.ver b/osmeventplugin/libosmeventplugin.ver
new file mode 100644
index 0000000..f755ff6
--- /dev/null
+++ b/osmeventplugin/libosmeventplugin.ver
@@ -0,0 +1,9 @@
+# In this file we track the current API version
+# of the vendor interface (and libraries)
+# The version is built of the following
+# tree numbers:
+# API_REV:RUNNING_REV:AGE
+# API_REV - advance on any added API
+# RUNNING_REV - advance any change to the vendor files
+# AGE - number of backward versions the API still supports
+LIBVERSION=1:0:0
diff --git a/osmeventplugin/src/osmeventplugin.c b/osmeventplugin/src/osmeventplugin.c
new file mode 100644
index 0000000..f0781eb
--- /dev/null
+++ b/osmeventplugin/src/osmeventplugin.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2007 The Regents of the University of California.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif				/* HAVE_CONFIG_H */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <dlfcn.h>
+#include <stdint.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+
+/** =========================================================================
+ * This is a simple example plugin which logs some of the events the OSM
+ * generates to this interface.
+ */
+#define SAMPLE_PLUGIN_OUTPUT_FILE "/tmp/osm_sample_event_plugin_output"
+typedef struct _log_events {
+	FILE *log_file;
+	osm_log_t *osmlog;
+} _log_events_t;
+
+/** =========================================================================
+ */
+static void *construct(osm_opensm_t *osm)
+{
+	_log_events_t *log = malloc(sizeof(*log));
+	if (!log)
+		return (NULL);
+
+	log->log_file = fopen(SAMPLE_PLUGIN_OUTPUT_FILE, "a+");
+
+	if (!(log->log_file)) {
+		osm_log(&osm->log, OSM_LOG_ERROR,
+			"Sample Event Plugin: Failed to open output file \"%s\"\n",
+			SAMPLE_PLUGIN_OUTPUT_FILE);
+		free(log);
+		return (NULL);
+	}
+
+	log->osmlog = &osm->log;
+	return ((void *)log);
+}
+
+/** =========================================================================
+ */
+static void destroy(void *_log)
+{
+	_log_events_t *log = (_log_events_t *) _log;
+	fclose(log->log_file);
+	free(log);
+}
+
+/** =========================================================================
+ */
+static void handle_port_counter(_log_events_t * log, osm_epi_pe_event_t * pc)
+{
+	if (pc->symbol_err_cnt > 0
+	    || pc->link_err_recover > 0
+	    || pc->link_downed > 0
+	    || pc->rcv_err > 0
+	    || pc->rcv_rem_phys_err > 0
+	    || pc->rcv_switch_relay_err > 0
+	    || pc->xmit_discards > 0
+	    || pc->xmit_constraint_err > 0
+	    || pc->rcv_constraint_err > 0
+	    || pc->link_integrity > 0
+	    || pc->buffer_overrun > 0 || pc->vl15_dropped > 0) {
+		fprintf(log->log_file,
+			"Port counter errors for node 0x%" PRIx64
+			" (%s) port %d\n", pc->port_id.node_guid,
+			pc->port_id.node_name, pc->port_id.port_num);
+	}
+}
+
+/** =========================================================================
+ */
+static void
+handle_port_counter_ext(_log_events_t * log, osm_epi_dc_event_t * epc)
+{
+	fprintf(log->log_file,
+		"Recieved Data counters for node 0x%" PRIx64 " (%s) port %d\n",
+		epc->port_id.node_guid,
+		epc->port_id.node_name, epc->port_id.port_num);
+}
+
+/** =========================================================================
+ */
+static void handle_port_select(_log_events_t * log, osm_epi_ps_event_t * ps)
+{
+	if (ps->xmit_wait > 0) {
+		fprintf(log->log_file,
+			"Port select Xmit Wait counts for node 0x%" PRIx64
+			" (%s) port %d\n", ps->port_id.node_guid,
+			ps->port_id.node_name, ps->port_id.port_num);
+	}
+}
+
+/** =========================================================================
+ */
+static void handle_trap_event(_log_events_t * log, osm_epi_trap_event_t * trap)
+{
+	fprintf(log->log_file,
+		"Trap event %d from 0x%" PRIx64 " (%s) port %d\n",
+		trap->trap_num,
+		trap->port_id.node_guid,
+		trap->port_id.node_name, trap->port_id.port_num);
+}
+
+/** =========================================================================
+ */
+static void report(void *_log, osm_epi_event_id_t event_id, void *event_data)
+{
+	_log_events_t *log = (_log_events_t *) _log;
+
+	switch (event_id) {
+	case OSM_EVENT_ID_PORT_ERRORS:
+		handle_port_counter(log, (osm_epi_pe_event_t *) event_data);
+		break;
+	case OSM_EVENT_ID_PORT_DATA_COUNTERS:
+		handle_port_counter_ext(log, (osm_epi_dc_event_t *) event_data);
+		break;
+	case OSM_EVENT_ID_PORT_SELECT:
+		handle_port_select(log, (osm_epi_ps_event_t *) event_data);
+		break;
+	case OSM_EVENT_ID_TRAP:
+		handle_trap_event(log, (osm_epi_trap_event_t *) event_data);
+		break;
+	case OSM_EVENT_ID_MAX:
+	default:
+		osm_log(log->osmlog, OSM_LOG_ERROR,
+			"Unknown event reported to plugin\n");
+	}
+}
+
+/** =========================================================================
+ * Define the object symbol for loading
+ */
+
+#if OSM_EVENT_PLUGIN_INTERFACE_VER != 2
+#error OpenSM plugin interface version missmatch
+#endif
+
+osm_event_plugin_t osm_event_plugin = {
+      osm_version:OSM_VERSION,
+      create:construct,
+      delete:destroy,
+      report:report
+};
diff --git a/osmtest/Makefile.am b/osmtest/Makefile.am
new file mode 100644
index 0000000..4c68852
--- /dev/null
+++ b/osmtest/Makefile.am
@@ -0,0 +1,23 @@
+
+if DEBUG
+DBGFLAGS = -ggdb -D_DEBUG_
+else
+DBGFLAGS = -g
+endif
+
+INCLUDES = -I$(srcdir)/include $(OSMV_INCLUDES)
+
+sbin_PROGRAMS = osmtest
+osmtest_SOURCES = main.c osmtest.c osmt_service.c osmt_slvl_vl_arb.c \
+		 osmt_multicast.c osmt_inform.c
+if OSMV_VAPI
+osmtest_SOURCES += osmt_mtl_regular_qp.c
+endif
+osmtest_CFLAGS = -Wall $(DBGFLAGS)
+osmtest_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L../opensm -lopensm $(OSMV_LDADD)
+
+EXTRA_DIST = $(srcdir)/include/osmt_inform.h \
+   $(srcdir)/include/osmtest_subnet.h \
+   $(srcdir)/include/osmtest.h \
+   $(srcdir)/include/osmt_mtl_regular_qp.h \
+   $(srcdir)/include/osmtest_base.h
diff --git a/osmtest/Makefile.in b/osmtest/Makefile.in
new file mode 100644
index 0000000..3644788
--- /dev/null
+++ b/osmtest/Makefile.in
@@ -0,0 +1,614 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = osmtest$(EXEEXT)
+ at OSMV_VAPI_TRUE@am__append_1 = osmt_mtl_regular_qp.c
+subdir = osmtest
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 \
+	$(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h \
+	$(top_builddir)/include/opensm/osm_config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)"
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(sbin_PROGRAMS)
+am__osmtest_SOURCES_DIST = main.c osmtest.c osmt_service.c \
+	osmt_slvl_vl_arb.c osmt_multicast.c osmt_inform.c \
+	osmt_mtl_regular_qp.c
+ at OSMV_VAPI_TRUE@am__objects_1 = osmtest-osmt_mtl_regular_qp.$(OBJEXT)
+am_osmtest_OBJECTS = osmtest-main.$(OBJEXT) osmtest-osmtest.$(OBJEXT) \
+	osmtest-osmt_service.$(OBJEXT) \
+	osmtest-osmt_slvl_vl_arb.$(OBJEXT) \
+	osmtest-osmt_multicast.$(OBJEXT) osmtest-osmt_inform.$(OBJEXT) \
+	$(am__objects_1)
+osmtest_OBJECTS = $(am_osmtest_OBJECTS)
+am__DEPENDENCIES_1 =
+osmtest_DEPENDENCIES = $(am__DEPENDENCIES_1)
+osmtest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(osmtest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(osmtest_SOURCES)
+DIST_SOURCES = $(am__osmtest_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NODENAMEMAPFILE = @NODENAMEMAPFILE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@
+OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@
+OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@
+OSMV_INCLUDES = @OSMV_INCLUDES@
+OSMV_LDADD = @OSMV_LDADD@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@
+QOS_POLICY_FILE = @QOS_POLICY_FILE@
+RANLIB = @RANLIB@
+RELEASE = @RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TARBALL = @TARBALL@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+_LEX_ = @_LEX_@
+_YACC_ = @_YACC_@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ at DEBUG_FALSE@DBGFLAGS = -g
+ at DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_
+INCLUDES = -I$(srcdir)/include $(OSMV_INCLUDES)
+osmtest_SOURCES = main.c osmtest.c osmt_service.c osmt_slvl_vl_arb.c \
+	osmt_multicast.c osmt_inform.c $(am__append_1)
+osmtest_CFLAGS = -Wall $(DBGFLAGS)
+osmtest_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L../opensm -lopensm $(OSMV_LDADD)
+EXTRA_DIST = $(srcdir)/include/osmt_inform.h \
+   $(srcdir)/include/osmtest_subnet.h \
+   $(srcdir)/include/osmtest.h \
+   $(srcdir)/include/osmt_mtl_regular_qp.h \
+   $(srcdir)/include/osmtest_base.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  osmtest/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  osmtest/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+	done
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+osmtest$(EXEEXT): $(osmtest_OBJECTS) $(osmtest_DEPENDENCIES) 
+	@rm -f osmtest$(EXEEXT)
+	$(osmtest_LINK) $(osmtest_OBJECTS) $(osmtest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmt_inform.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmt_multicast.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmt_service.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/osmtest-osmtest.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+osmtest-main.o: main.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-main.o -MD -MP -MF $(DEPDIR)/osmtest-main.Tpo -c -o osmtest-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-main.Tpo $(DEPDIR)/osmtest-main.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='main.c' object='osmtest-main.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+
+osmtest-main.obj: main.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-main.obj -MD -MP -MF $(DEPDIR)/osmtest-main.Tpo -c -o osmtest-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-main.Tpo $(DEPDIR)/osmtest-main.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='main.c' object='osmtest-main.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+
+osmtest-osmtest.o: osmtest.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmtest.o -MD -MP -MF $(DEPDIR)/osmtest-osmtest.Tpo -c -o osmtest-osmtest.o `test -f 'osmtest.c' || echo '$(srcdir)/'`osmtest.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmtest.Tpo $(DEPDIR)/osmtest-osmtest.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmtest.c' object='osmtest-osmtest.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmtest.o `test -f 'osmtest.c' || echo '$(srcdir)/'`osmtest.c
+
+osmtest-osmtest.obj: osmtest.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmtest.obj -MD -MP -MF $(DEPDIR)/osmtest-osmtest.Tpo -c -o osmtest-osmtest.obj `if test -f 'osmtest.c'; then $(CYGPATH_W) 'osmtest.c'; else $(CYGPATH_W) '$(srcdir)/osmtest.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmtest.Tpo $(DEPDIR)/osmtest-osmtest.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmtest.c' object='osmtest-osmtest.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmtest.obj `if test -f 'osmtest.c'; then $(CYGPATH_W) 'osmtest.c'; else $(CYGPATH_W) '$(srcdir)/osmtest.c'; fi`
+
+osmtest-osmt_service.o: osmt_service.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_service.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_service.Tpo -c -o osmtest-osmt_service.o `test -f 'osmt_service.c' || echo '$(srcdir)/'`osmt_service.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_service.Tpo $(DEPDIR)/osmtest-osmt_service.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_service.c' object='osmtest-osmt_service.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_service.o `test -f 'osmt_service.c' || echo '$(srcdir)/'`osmt_service.c
+
+osmtest-osmt_service.obj: osmt_service.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_service.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_service.Tpo -c -o osmtest-osmt_service.obj `if test -f 'osmt_service.c'; then $(CYGPATH_W) 'osmt_service.c'; else $(CYGPATH_W) '$(srcdir)/osmt_service.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_service.Tpo $(DEPDIR)/osmtest-osmt_service.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_service.c' object='osmtest-osmt_service.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_service.obj `if test -f 'osmt_service.c'; then $(CYGPATH_W) 'osmt_service.c'; else $(CYGPATH_W) '$(srcdir)/osmt_service.c'; fi`
+
+osmtest-osmt_slvl_vl_arb.o: osmt_slvl_vl_arb.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_slvl_vl_arb.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo -c -o osmtest-osmt_slvl_vl_arb.o `test -f 'osmt_slvl_vl_arb.c' || echo '$(srcdir)/'`osmt_slvl_vl_arb.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_slvl_vl_arb.c' object='osmtest-osmt_slvl_vl_arb.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_slvl_vl_arb.o `test -f 'osmt_slvl_vl_arb.c' || echo '$(srcdir)/'`osmt_slvl_vl_arb.c
+
+osmtest-osmt_slvl_vl_arb.obj: osmt_slvl_vl_arb.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_slvl_vl_arb.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo -c -o osmtest-osmt_slvl_vl_arb.obj `if test -f 'osmt_slvl_vl_arb.c'; then $(CYGPATH_W) 'osmt_slvl_vl_arb.c'; else $(CYGPATH_W) '$(srcdir)/osmt_slvl_vl_arb.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_slvl_vl_arb.c' object='osmtest-osmt_slvl_vl_arb.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_slvl_vl_arb.obj `if test -f 'osmt_slvl_vl_arb.c'; then $(CYGPATH_W) 'osmt_slvl_vl_arb.c'; else $(CYGPATH_W) '$(srcdir)/osmt_slvl_vl_arb.c'; fi`
+
+osmtest-osmt_multicast.o: osmt_multicast.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_multicast.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_multicast.Tpo -c -o osmtest-osmt_multicast.o `test -f 'osmt_multicast.c' || echo '$(srcdir)/'`osmt_multicast.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_multicast.Tpo $(DEPDIR)/osmtest-osmt_multicast.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_multicast.c' object='osmtest-osmt_multicast.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_multicast.o `test -f 'osmt_multicast.c' || echo '$(srcdir)/'`osmt_multicast.c
+
+osmtest-osmt_multicast.obj: osmt_multicast.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_multicast.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_multicast.Tpo -c -o osmtest-osmt_multicast.obj `if test -f 'osmt_multicast.c'; then $(CYGPATH_W) 'osmt_multicast.c'; else $(CYGPATH_W) '$(srcdir)/osmt_multicast.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_multicast.Tpo $(DEPDIR)/osmtest-osmt_multicast.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_multicast.c' object='osmtest-osmt_multicast.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_multicast.obj `if test -f 'osmt_multicast.c'; then $(CYGPATH_W) 'osmt_multicast.c'; else $(CYGPATH_W) '$(srcdir)/osmt_multicast.c'; fi`
+
+osmtest-osmt_inform.o: osmt_inform.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_inform.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_inform.Tpo -c -o osmtest-osmt_inform.o `test -f 'osmt_inform.c' || echo '$(srcdir)/'`osmt_inform.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_inform.Tpo $(DEPDIR)/osmtest-osmt_inform.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_inform.c' object='osmtest-osmt_inform.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_inform.o `test -f 'osmt_inform.c' || echo '$(srcdir)/'`osmt_inform.c
+
+osmtest-osmt_inform.obj: osmt_inform.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_inform.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_inform.Tpo -c -o osmtest-osmt_inform.obj `if test -f 'osmt_inform.c'; then $(CYGPATH_W) 'osmt_inform.c'; else $(CYGPATH_W) '$(srcdir)/osmt_inform.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_inform.Tpo $(DEPDIR)/osmtest-osmt_inform.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_inform.c' object='osmtest-osmt_inform.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_inform.obj `if test -f 'osmt_inform.c'; then $(CYGPATH_W) 'osmt_inform.c'; else $(CYGPATH_W) '$(srcdir)/osmt_inform.c'; fi`
+
+osmtest-osmt_mtl_regular_qp.o: osmt_mtl_regular_qp.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_mtl_regular_qp.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo -c -o osmtest-osmt_mtl_regular_qp.o `test -f 'osmt_mtl_regular_qp.c' || echo '$(srcdir)/'`osmt_mtl_regular_qp.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_mtl_regular_qp.c' object='osmtest-osmt_mtl_regular_qp.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_mtl_regular_qp.o `test -f 'osmt_mtl_regular_qp.c' || echo '$(srcdir)/'`osmt_mtl_regular_qp.c
+
+osmtest-osmt_mtl_regular_qp.obj: osmt_mtl_regular_qp.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_mtl_regular_qp.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo -c -o osmtest-osmt_mtl_regular_qp.obj `if test -f 'osmt_mtl_regular_qp.c'; then $(CYGPATH_W) 'osmt_mtl_regular_qp.c'; else $(CYGPATH_W) '$(srcdir)/osmt_mtl_regular_qp.c'; fi`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='osmt_mtl_regular_qp.c' object='osmtest-osmt_mtl_regular_qp.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_mtl_regular_qp.obj `if test -f 'osmt_mtl_regular_qp.c'; then $(CYGPATH_W) 'osmt_mtl_regular_qp.c'; else $(CYGPATH_W) '$(srcdir)/osmt_mtl_regular_qp.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+	for dir in "$(DESTDIR)$(sbindir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-sbinPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-sbinPROGRAMS install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-sbinPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/osmtest/include/osmt_inform.h b/osmtest/include/osmt_inform.h
new file mode 100644
index 0000000..bc796cc
--- /dev/null
+++ b/osmtest/include/osmt_inform.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __OSMT_INFORM__
+#define __OSMT_INFORM__
+
+#ifdef OSM_VENDOR_INTF_MTL
+#include <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__ */
diff --git a/osmtest/include/osmt_mtl_regular_qp.h b/osmtest/include/osmt_mtl_regular_qp.h
new file mode 100644
index 0000000..3fd6e9d
--- /dev/null
+++ b/osmtest/include/osmt_mtl_regular_qp.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2001-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ *    mad.h -
+ *      Header file for common special QP resources creation code.
+ *
+ *  Creation date:
+ *
+ *  Version: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan
+ *
+ *  Authors:
+ *    Elazar Raab
+ *
+ *  Changes:
+ */
+
+#ifndef H_MAD_H
+#define H_MAD_H
+
+#include <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
diff --git a/osmtest/include/osmtest.h b/osmtest/include/osmtest.h
new file mode 100644
index 0000000..c3134ef
--- /dev/null
+++ b/osmtest/include/osmtest.h
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ */
+
+#ifndef _OSMTEST_H_
+#define _OSMTEST_H_
+
+#include <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"
+
+enum OSMT_FLOWS {
+	OSMT_FLOW_ALL = 0,
+	OSMT_FLOW_CREATE_INVENTORY,
+	OSMT_FLOW_VALIDATE_INVENTORY,
+	OSMT_FLOW_SERVICE_REGISTRATION,
+	OSMT_FLOW_EVENT_FORWARDING,
+	OSMT_FLOW_STRESS_SA,
+	OSMT_FLOW_MULTICAST,
+	OSMT_FLOW_QOS,
+	OSMT_FLOW_TRAP,
+};
+
+/****s* OpenSM: Subnet/osmtest_opt_t
+ * NAME
+ * osmtest_opt_t
+ *
+ * DESCRIPTION
+ * Subnet options structure.  This structure contains the various
+ * site specific configuration parameters for osmtest.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest_opt {
+	uint32_t transaction_timeout;
+	boolean_t force_log_flush;
+	boolean_t create;
+	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_ */
diff --git a/osmtest/include/osmtest_base.h b/osmtest/include/osmtest_base.h
new file mode 100644
index 0000000..7c33da3
--- /dev/null
+++ b/osmtest/include/osmtest_base.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osmtest_t.
+ *	This object represents the OSMTest Test object.
+ *
+ */
+#ifndef _OSMTEST_BASE_H_
+#define _OSMTEST_BASE_H_
+
+#ifndef __WIN__
+#include <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_ */
diff --git a/osmtest/include/osmtest_subnet.h b/osmtest/include/osmtest_subnet.h
new file mode 100644
index 0000000..09063dd
--- /dev/null
+++ b/osmtest/include/osmtest_subnet.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Declaration of osmtest_t.
+ *	This object represents the OSMTest Test object.
+ *
+ */
+
+#ifndef _OSMTEST_SUBNET_H_
+#define _OSMTEST_SUBNET_H_
+
+#include <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
diff --git a/osmtest/main.c b/osmtest/main.c
new file mode 100644
index 0000000..f87e33b
--- /dev/null
+++ b/osmtest/main.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Command line interface for osmtest.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.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
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t osmt_is_debug(void)
+{
+#if defined( _DEBUG_ )
+	return TRUE;
+#else
+	return FALSE;
+#endif				/* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+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, deregistration, and lease test\n"
+	       "          e = run event forwarding test\n"
+	       "          f = flood the SA with queries according to the stress mode\n"
+	       "          m = multicast flow\n"
+	       "          q = QoS info: dump VLArb and SLtoVL tables\n"
+	       "          t = run trap 64/65 flow (this flow requires running of external tool)\n"
+	       "          (default is all flows except QoS)\n\n");
+
+	printf("-w <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\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"
+	       "          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\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\n");
+	printf("-p \n"
+	       "--port\n"
+	       "          This option displays a menu of possible local port GUID values\n"
+	       "          with which osmtest could bind\n\n");
+	printf("-h\n"
+	       "--help\n" "          Display this usage info then exit\n\n");
+	printf("-i <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 -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 with OpenSM MC\n"
+	       " Multiple mode - Could be run with other apps using MC with\n"
+	       "   OpenSM."
+	       " Without -M, default flow testing is performed\n\n");
+
+	printf("-t <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");
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void print_all_guids(IN osmtest_t * p_osmt);
+static void print_all_guids(IN osmtest_t * p_osmt)
+{
+	ib_api_status_t status;
+	uint32_t num_ports = GUID_ARRAY_SIZE;
+	ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+	int i;
+
+	/*
+	   Call the transport layer for a list of local port
+	   GUID values.
+	 */
+	status =
+	    osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array,
+					 &num_ports);
+	if (status != IB_SUCCESS) {
+		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
+		       status);
+		return;
+	}
+
+	printf("\nListing GUIDs:\n");
+	for (i = 0; i < num_ports; i++)
+		printf("Port %i: 0x%" PRIx64 "\n", i,
+		       cl_hton64(attr_array[i].port_guid));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t get_port_guid(IN osmtest_t * p_osmt, uint64_t port_guid)
+{
+	ib_api_status_t status;
+	uint32_t num_ports = GUID_ARRAY_SIZE;
+	ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+	int i;
+
+	/*
+	   Call the transport layer for a list of local port
+	   GUID values.
+	 */
+/* "local ports" is(?) phys, shouldn't this exclude port 0 then ? */
+	status =
+	    osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array,
+					 &num_ports);
+	if (status != IB_SUCCESS) {
+		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
+		       status);
+		return (0);
+	}
+
+	if (num_ports == 1) {
+		printf("using default guid 0x%" PRIx64 "\n",
+		       cl_hton64(attr_array[0].port_guid));
+		return (attr_array[0].port_guid);
+	}
+
+	for (i = 0; i < num_ports; i++) {
+		if (attr_array[i].port_guid == port_guid ||
+		    (!port_guid && attr_array[i].link_state > IB_LINK_DOWN))
+			return attr_array[i].port_guid;
+	}
+
+	return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+int main(int argc, char *argv[])
+{
+	static osmtest_t osm_test;
+	osmtest_opt_t opt = { 0 };
+	ib_net64_t guid = 0;
+	uint16_t max_lid = 100;
+	ib_api_status_t status;
+	uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+	int32_t vendor_debug = 0;
+	char flow_name[64];
+	uint32_t next_option;
+	const char *const short_option = "f:l:m:M:d:g:s:t:i:pcvVh";
+
+	/*
+	 * 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", 2, NULL, 'g'},
+		{"port", 0, NULL, 'p'},
+		{"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 */
+	};
+
+	/* Make sure that the opensm, complib and osmtest were compiled using
+	   same modes (debug/free) */
+	if (osm_is_debug() != cl_is_debug() || osm_is_debug() != osmt_is_debug()
+	    || osmt_is_debug() != cl_is_debug()) {
+		fprintf(stderr,
+			"-E- OpenSM, Complib and OsmTest were compiled using different modes\n");
+		fprintf(stderr,
+			"-E- OpenSM debug:%d Complib debug:%d OsmTest debug:%d \n",
+			osm_is_debug(), cl_is_debug(), osmt_is_debug());
+		exit(1);
+	}
+
+	opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+	opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC;
+	opt.retry_count = OSMT_DEFAULT_RETRY_COUNT;
+	opt.force_log_flush = FALSE;
+	opt.stress = 0;
+	opt.log_file = NULL;
+	opt.create = FALSE;
+	opt.mmode = 1;
+	opt.ignore_path_records = FALSE;	/*  Do path Records too */
+	opt.flow = OSMT_FLOW_ALL;	/*  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 = OSMT_FLOW_CREATE_INVENTORY;
+			} else if (!strcmp("v", optarg)) {
+				strcpy(flow_name, "Validate Inventory");
+				opt.flow = OSMT_FLOW_VALIDATE_INVENTORY;
+			} else if (!strcmp("s", optarg)) {
+				strcpy(flow_name, "Services Registration");
+				opt.flow = OSMT_FLOW_SERVICE_REGISTRATION;
+			} else if (!strcmp("e", optarg)) {
+				strcpy(flow_name, "Event Forwarding");
+				opt.flow = OSMT_FLOW_EVENT_FORWARDING;
+			} else if (!strcmp("f", optarg)) {
+				strcpy(flow_name, "Stress SA");
+				opt.flow = OSMT_FLOW_STRESS_SA;
+			} else if (!strcmp("m", optarg)) {
+				strcpy(flow_name, "Multicast");
+				opt.flow = OSMT_FLOW_MULTICAST;
+			} else if (!strcmp("q", optarg)) {
+				strcpy(flow_name, "QoS: VLArb and SLtoVL");
+				opt.flow = OSMT_FLOW_QOS;
+			} else if (!strcmp("t", optarg)) {
+				strcpy(flow_name, "Trap 64/65");
+				opt.flow = OSMT_FLOW_TRAP;
+			} else if (!strcmp("a", optarg)) {
+				strcpy(flow_name, "All Validations");
+				opt.flow = OSMT_FLOW_ALL;
+			} else {
+				printf("\nError: unknown flow %s\n", flow_name);
+				exit(2);
+			}
+			break;
+
+		case 'w':
+			/*
+			 * Specifies trap 64/65 wait time
+			 */
+			CL_ASSERT(strtol(optarg, NULL, 0) < 0x100);
+			opt.wait_time = (uint8_t) strtol(optarg, NULL, 0);
+			printf("\tTrap 64/65 wait time = %d\n", opt.wait_time);
+			break;
+
+		case 'm':
+			/*
+			 * Specifies the max LID to search for during exploration.
+			 */
+			max_lid = atoi(optarg);
+			printf("\tMAX-LID %u\n", max_lid);
+			break;
+
+		case 'g':
+			/*
+			 * Specifies port guid with which to bind.
+			 */
+			guid = cl_hton64(strtoull(optarg, NULL, 16));
+			printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(guid));
+			break;
+
+		case 'p':
+			/*
+			 * Display current port guids
+			 */
+			guid = INVALID_GUID;
+			break;
+
+		case 't':
+			/*
+			 * Specifies transaction timeout.
+			 */
+			opt.transaction_timeout = strtol(optarg, NULL, 0);
+			printf("\tTransaction timeout = %d\n",
+			       opt.transaction_timeout);
+			break;
+
+		case 'l':
+			opt.log_file = optarg;
+			printf("\tLog File:%s\n", opt.log_file);
+			break;
+
+		case 'v':
+			/*
+			 * Increases log verbosity.
+			 */
+			log_flags = (log_flags << 1) | 1;
+			printf("\tVerbose option -v (log flags = 0x%X)\n",
+			       log_flags);
+			break;
+
+		case 'V':
+			/*
+			 * Specifies maximum log verbosity.
+			 */
+			log_flags = 0xFFFFFFFF;
+			opt.force_log_flush = TRUE;
+			printf("\tEnabling maximum log verbosity\n");
+			break;
+
+		case 's':
+			/*
+			 * Perform stress test.
+			 */
+			opt.stress = strtol(optarg, NULL, 0);
+			printf("\tStress test enabled: ");
+			switch (opt.stress) {
+			case 1:
+				printf("Small SA queries\n");
+				break;
+			case 2:
+				printf("Large SA queries\n");
+				break;
+			case 3:
+				printf("Large Path Record SA queries\n");
+				break;
+			default:
+				printf("Unknown value %u (ignored)\n",
+				       opt.stress);
+				opt.stress = 0;
+				break;
+			}
+			break;
+
+		case 'M':
+			/*
+			 * Perform multicast test.
+			 */
+			opt.mmode = strtol(optarg, NULL, 0);
+			printf("\tMulticast test enabled: ");
+			switch (opt.mmode) {
+			case 1:
+				printf
+				    ("Short MC Flow - single mode (default)\n");
+				break;
+			case 2:
+				printf("Short MC Flow - multiple mode\n");
+				break;
+			case 3:
+				printf("Long MC Flow - single mode\n");
+				break;
+			case 4:
+				printf("Long MC Flow - multiple mode\n");
+				break;
+			default:
+				printf("Unknown value %u (ignored)\n",
+				       opt.stress);
+				opt.mmode = 0;
+				break;
+			}
+			break;
+
+		case 'd':
+			/*
+			 * Debug Options
+			 */
+			printf("\tDebug Option: ");
+			switch (strtol(optarg, NULL, 0)) {
+			case 1:
+				printf("Ignore Path Records\n");
+				opt.ignore_path_records = TRUE;
+				break;
+			case 2:
+				printf("Force Log Flush\n");
+				opt.force_log_flush = TRUE;
+				break;
+			case 3:
+				/* Used to be memory tracking */
+			default:
+				printf("Unknown value %ld (ignored)\n",
+				       strtol(optarg, NULL, 0));
+				break;
+			}
+			break;
+
+		case 'h':
+			show_usage();
+			return 0;
+
+		case 'x':
+			log_flags = strtol(optarg, NULL, 0);
+			printf
+			    ("\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 (vendor_debug)
+		osm_vendor_set_debug(osm_test.p_vendor, vendor_debug);
+
+	complib_init();
+
+	status = osmtest_init(&osm_test, &opt, (osm_log_level_t) log_flags);
+	if (status != IB_SUCCESS) {
+		printf("\nError from osmtest_init: %s\n",
+		       ib_get_err_str(status));
+		goto Exit;
+	}
+	if (cl_hton64(guid) == cl_hton64(INVALID_GUID)) {
+		print_all_guids(&osm_test);
+		complib_exit();
+		return (status);
+	}
+
+	/*
+	   If the user didn't specify a GUID on the command line,
+	   then get a port GUID value with which to bind.
+	 */
+	if (guid == 0 && !(guid = get_port_guid(&osm_test, guid))) {
+		printf("\nError: port guid 0x%" PRIx64 " not found\n", guid);
+		goto Exit;
+	}
+
+	/*
+	 * Guid may be zero going into this function if the user
+	 * hasn't specified a binding port on the command line.
+	 */
+	status = osmtest_bind(&osm_test, max_lid, guid);
+	if (status != IB_SUCCESS)
+		exit(status);
+
+	status = osmtest_run(&osm_test);
+	if (status != IB_SUCCESS) {
+		printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name);
+	} else {
+		printf("OSMTEST: TEST \"%s\" PASS\n", flow_name);
+	}
+	osmtest_destroy(&osm_test);
+
+	complib_exit();
+
+Exit:
+	return (status);
+}
diff --git a/osmtest/osmt_inform.c b/osmtest/osmt_inform.c
new file mode 100644
index 0000000..c252a4c
--- /dev/null
+++ b/osmtest/osmt_inform.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef OSM_VENDOR_INTF_MTL
+/*
+ * Abstract:
+ *    Implementation of InformInfo testing flow..
+ *    Top level is osmt_run_inform_info_flow:
+ *     osmt_bind_inform_qp
+ *     osmt_reg_unreg_inform_info
+ *     osmt_send_trap_wait_for_forward
+ *
+ */
+
+#include <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);
+
+	port_guid = p_osmt->local_port.port_guid;
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n",
+		cl_ntoh64(port_guid));
+
+	/* obtain the hca name and port num from the guid */
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"Finding CA and Port that owns port guid 0x%" PRIx64 "\n",
+		port_guid);
+
+	mgt_ret =
+	    osm_vendor_get_guid_ca_and_port(p_osmt->p_vendor,
+					    port_guid,
+					    &hca_hndl,
+					    &hca_id[0], &hca_index, &port_num);
+	if (mgt_ret != IB_MGT_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0109: "
+			"Unable to obtain CA and port (%d).\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000
+
+	strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id));
+	p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl;
+	p_qp_ctx->qp_bind_hndl.port_num = port_num;
+	p_qp_ctx->qp_bind_hndl.max_outs_sq = 10;
+	p_qp_ctx->qp_bind_hndl.max_outs_rq = 10;
+	p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY;
+
+	vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl);
+	if (vapi_ret != VAPI_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0114: "
+			"Error initializing QP.\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* we use the pre-allocated buffers for send and receive :
+	   send from buf[0]
+	   receive from buf[2]
+	 */
+	p_qp_ctx->p_send_buf =
+	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN;
+	p_qp_ctx->p_recv_buf =
+	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN +
+							      MAD_BLOCK_SIZE);
+
+	/* Need to clear assigned memory of p_send_buf - before using it to send any data */
+	memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE);
+
+	status = IB_SUCCESS;
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Initialized QP:0x%X in VAPI Mode\n",
+		p_qp_ctx->qp_bind_hndl.qp_id);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to IB_MGT SMI\n");
+
+	/* we also need a QP0 handle for sending packets */
+	mgt_ret = IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI,
+				    &(p_qp_ctx->ib_mgt_qp0_handle));
+	if (IB_MGT_OK != mgt_ret) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0115: "
+			"Error obtaining IB_MGT handle to SMI\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+/*
+ * Close the QP
+ */
+void
+osmt_unbind_inform_qp(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
+{
+	osm_log_t *p_log = &p_osmt->log;
+
+	OSM_LOG_ENTER(p_log);
+
+	osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl);
+
+	IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle);
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Unbind QP handles\n");
+	OSM_LOG_EXIT(&p_osmt->log);
+}
+
+/*
+ * Register/Unregister to receive the given InformInfo
+ *
+ * Uses the qp context to send the inform info mad.
+ * Wait for GetResp(InformInfoResp)
+ *
+ */
+ib_api_status_t
+osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
+			   IN osmt_qp_ctx_t * p_qp_ctx,
+			   IN ib_inform_info_t * p_inform_info,
+			   IN uint8_t reg_flag)
+{
+	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
+	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
+	VAPI_ret_t vapi_ret;
+	VAPI_wc_desc_t wc_desc;
+	VAPI_ud_av_hndl_t avh;
+	static VAPI_wr_id_t wrid = 16198;
+	osm_log_t *p_log = &p_osmt->log;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/* init the MAD */
+	ib_mad_init_new((ib_mad_t *) p_sa_mad,
+			IB_MCLASS_SUBN_ADM,
+			(uint8_t) 2,
+			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
+	wrid++;
+	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;
+
+	/* copy the reference inform info */
+	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));
+
+	if (reg_flag) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
+			p_ii->lid_range_begin, p_ii->lid_range_end,
+			p_ii->g_or_v.generic.trap_num);
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
+			p_ii->lid_range_begin, p_ii->lid_range_end);
+	}
+
+	/* set the subscribe bit */
+	if (reg_flag) {
+		p_ii->subscribe = 1;
+	} else {
+		p_ii->subscribe = 0;
+		/*
+		 * we need to set the QPN on the mad if we unsubscribe:
+		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
+		 */
+		ib_inform_info_set_qpn(p_ii,
+				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
+						 qp_num));
+	}
+
+	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);
+
+	/* --------------------- PREP ------------------------- */
+	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  but we need only one mad at a time */
+					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
+			"Error posting recv bufs\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
+
+	vapi_ret =
+	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
+			       p_osmt->local_port.sm_lid, &avh);
+	if (vapi_ret != VAPI_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
+			"Error Preparing AVH (%s)\n",
+			VAPI_strerror_sym(vapi_ret));
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
+
+	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
+		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
+				OSM_LOG_DEBUG);
+#if 0
+		for (i = 56; i < 253; i++) {
+			if (i % 8 == 0) {
+				printf("\n %d : ", i);
+			}
+			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
+		}
+#endif
+		printf("\n");
+	}
+
+	/* --------------------- SEND ------------------------- */
+	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
+				     0,	/*  SL is 0 */
+				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
+				     avh);
+	if (vapi_ret != VAPI_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
+			"Error sending mad (%s)\n",
+			VAPI_strerror_sym(vapi_ret));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
+					 &wc_desc, 20, 10000, NULL);
+	if (vapi_ret != VAPI_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
+			"Error getting send completion (%s)\n",
+			VAPI_strerror_sym(vapi_ret));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if (wc_desc.status != VAPI_SUCCESS) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
+			"Error on send completion (%s) (%d)\n",
+			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");
+
+	/* --------------------- RECV ------------------------- */
+	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+					 &wc_desc, 20, 10000, &avh);
+	if (vapi_ret != VAPI_SUCCESS) {
+		if (vapi_ret == VAPI_CQ_EMPTY) {
+			status = IB_TIMEOUT;
+		} else {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
+				"Error receiving mad (%s)\n",
+				VAPI_strerror_sym(vapi_ret));
+			status = IB_ERROR;
+		}
+		goto Exit;
+	}
+
+	/* check to see if successful - by examination of the subscribe bit */
+	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
+
+	if (p_sa_mad->status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
+			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
+			p_sa_mad->method);
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
+			cl_ntoh16(p_sa_mad->attr_id));
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
+	if (!p_ii->subscribe) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
+			"Subscribe/Unsubscribe Failed\n");
+		status = IB_REMOTE_ERROR;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/*
+ * Send a trap (Subn LID Route) Trap(Notice) through the regular
+ * connection QP connection (targeted at QP0)
+ *
+ * Wait for the trap repress
+ */
+ib_api_status_t
+osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,
+				IN osmt_qp_ctx_t * p_qp_ctx)
+{
+	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
+	ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
+	ib_sa_mad_t *p_sa_mad;
+	IB_MGT_ret_t mgt_res;
+	VAPI_ret_t vapi_ret;
+	VAPI_wc_desc_t wc_desc;
+	VAPI_ud_av_hndl_t avh;
+	IB_ud_av_t av;
+	static VAPI_wr_id_t wrid = 2222;
+	osm_log_t *p_log = &p_osmt->log;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_INFO,
+		"Sending Traps to QP0 of SA LID:0x%X\n",
+		p_osmt->local_port.sm_lid);
+
+	/* init the MAD */
+	memset(p_smp, 0, sizeof(ib_smp_t));
+	ib_mad_init_new((ib_mad_t *) p_smp,
+			IB_MCLASS_SUBN_LID,
+			(uint8_t) 2,
+			IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0);
+
+	wrid++;
+	p_smp->attr_id = IB_MAD_ATTR_NOTICE;
+
+	/* prepare the notice */
+	p_ntc->generic_type = 0x82;	/*  generic, type = 2 */
+	ib_notice_set_prod_type_ho(p_ntc, 1);
+	p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
+	p_ntc->issuer_lid = cl_hton16(2);
+
+	/* --------------------- PREP ------------------------- */
+	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  we need to receive both trap repress and report */
+					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: "
+			"Error posting recv bufs\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
+
+	av.dlid = p_osmt->local_port.sm_lid;
+	av.grh_flag = FALSE;
+
+	/*  EZ: returned in HACK: use constants */
+	av.static_rate = 0;	/*  p_mad_addr->static_rate; */
+	av.src_path_bits = 1;	/*  p_mad_addr->path_bits; */
+	av.sl = 0;		/*  p_mad_addr->addr_type.gsi.service_level; */
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG,
+		"av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n",
+		cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits);
+
+	/* send it */
+	mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp,	/*  actual payload */
+				  &av,	/*  address vector */
+				  wrid,	/*  casting the mad wrapper pointer for err cb */
+				  p_osmt->opt.transaction_timeout);
+	if (mgt_res != IB_MGT_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: "
+			"Error sending mad (%d)\n", mgt_res);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	vapi_ret =
+	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
+			       p_osmt->local_port.sm_lid, &avh);
+	if (vapi_ret != VAPI_OK) {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: "
+			"Error Preparing AVH (%s)\n",
+			VAPI_strerror_sym(vapi_ret));
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
+
+	OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n");
+
+	/* --------------------- RECV ------------------------- */
+	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+					 &wc_desc, 200, 10000, &avh);
+	if (vapi_ret != VAPI_SUCCESS) {
+		if (vapi_ret == VAPI_CQ_EMPTY) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
+				"Timeout receiving mad (%s)\n",
+				VAPI_strerror_sym(vapi_ret));
+			status = IB_TIMEOUT;
+		} else {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
+				"Error receiving mad (%s)\n",
+				VAPI_strerror_sym(vapi_ret));
+			status = IB_ERROR;
+		}
+		goto Exit;
+	}
+
+	/* check to see if successful - by examination of the subscribe bit */
+	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
+
+	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
+		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
+			OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
+				"Did not receive a Report(Notice) but attr:%d\n",
+				cl_ntoh16(p_sa_mad->attr_id));
+			status = IB_ERROR;
+		}
+	} else {
+		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
+			"Received an Unexpected Method:%d\n", p_smp->method);
+		status = IB_ERROR;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+/*
+ * Wait for a trap on QPn
+ *
+ */
+ib_api_status_t
+osmt_trap_wait(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
+{
+	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
+	ib_sa_mad_t *p_sa_mad;
+	VAPI_ret_t vapi_ret;
+	VAPI_wc_desc_t wc_desc;
+	osm_log_t *p_log = &p_osmt->log;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(p_log, OSM_LOG_INFO,
+		"Waiting for Traps under QP:0x%X of SA LID:0x%X\n",
+		cl_ntoh16(p_osmt->local_port.sm_lid));
+
+	/* --------------------- RECV ------------------------- */
+	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+					 &wc_desc,
+					 // 200,
+					 p_osmt->opt.wait_time * 100,
+					 10000, NULL);
+	if (vapi_ret != VAPI_SUCCESS) {
+		if (vapi_ret == VAPI_CQ_EMPTY) {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
+				"Timeout receiving mad (%s)\n",
+				VAPI_strerror_sym(vapi_ret));
+			status = IB_TIMEOUT;
+		} else {
+			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
+				"Error receiving mad (%s)\n",
+				VAPI_strerror_sym(vapi_ret));
+			status = IB_ERROR;
+		}
+		goto Exit;
+	}
+
+	/* check to see if successful - by examination of the subscribe bit */
+	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
+
+	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
+		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Received the Report!\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
+				"Did not receive a Report(Notice) but attr:%d\n",
+				cl_ntoh16(p_sa_mad->attr_id));
+			status = IB_ERROR;
+		}
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
+			"Received an Unexpected Method:%d\n", p_smp->method);
+		status = IB_ERROR;
+	}
+
+Exit:
+	OSM_LOG_EXIT(p_log);
+	return status;
+}
+
+/*
+ * Initialize an inform info attribute:
+ * Catch all traps in the lid range of the p_osmt
+ *
+ */
+ib_api_status_t
+osmt_init_inform_info(IN osmtest_t * const p_osmt, OUT ib_inform_info_t * p_ii)
+{
+
+	memset(p_ii, 0, sizeof(ib_inform_info_t));
+	/*  p_ii->lid_range_begin = cl_hton16(1); */
+	p_ii->lid_range_begin = 0xFFFF;
+	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+	p_ii->is_generic = 1;	/*  have to choose */
+	p_ii->trap_type = 0xFFFF;	/*  ALL */
+	p_ii->g_or_v.generic.trap_num = 0xFFFF;	/*  ALL */
+	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
+	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
+	return IB_SUCCESS;
+}
+
+ib_api_status_t
+osmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt,
+			      IN ib_net16_t trap_num,
+			      OUT ib_inform_info_t * p_ii)
+{
+
+	memset(p_ii, 0, sizeof(ib_inform_info_t));
+	/*  p_ii->lid_range_begin = cl_hton16(1); */
+	p_ii->lid_range_begin = 0xFFFF;
+	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+	p_ii->is_generic = 1;	/*  have to choose */
+	p_ii->trap_type = 0xFFFF;	/*  ALL */
+	p_ii->g_or_v.generic.trap_num = trap_num;	/*  ALL */
+	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
+	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
+	return IB_SUCCESS;
+}
+
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that 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);
+
+	/* bind the QP */
+	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/* init the inform info */
+	osmt_init_inform_info(p_osmt, &inform_info);
+
+	/* first try to unsubscribe */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
+	/* WAS IB_REMOTE_ERROR */
+	if (status != IB_REMOTE_ERROR) {
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Error during UnSubscribe: (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Expected Failure to UnSubscribe non existing InformInfo\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+	}
+
+	/* send the inform info registration */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/* send a trap through QP0 and wait on QPN */
+	status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Error during Send Trap and Wait For Report: (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/* try to unsubscribe for cleanup */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Error during UnSubscribe: (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	} else {
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Remote Error during UnSubscribe\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+	}
+
+Exit:
+	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that match the sent one
+ *
+ */
+ib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt)
+{
+	ib_inform_info_t inform_info;
+	ib_api_status_t status;
+	osmt_qp_ctx_t qp_ctx;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/* bind the QP */
+	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/* init the inform info */
+	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(64), &inform_info);
+
+	/* send the inform info registration */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+  /*--------------------- PREP -------------------------*/
+	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to receive the report */
+					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
+			"Error posting recv bufs for trap 64\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 64\n");
+
+	/* init the inform info */
+	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(65), &inform_info);
+
+	/* send the inform info registration */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+  /*--------------------- PREP -------------------------*/
+	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to reveive the report */
+					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
+			"Error posting recv bufs for trap 65\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 65\n");
+
+	/* Sleep for x seconds in order to allow external script trap generation */
+#if 0
+	sleep(p_osmt->opt.wait_time);
+#endif
+
+	/* wait for a trap on QPN */
+	status = osmt_trap_wait(p_osmt, &qp_ctx);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Error during Send Trap and Wait For Report: (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/* try to unsubscribe for cleanup */
+	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Error during UnSubscribe: (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+#endif				/*  OSM_VENDOR_INTF_MTL */
diff --git a/osmtest/osmt_mtl_regular_qp.c b/osmtest/osmt_mtl_regular_qp.c
new file mode 100644
index 0000000..6374dc2
--- /dev/null
+++ b/osmtest/osmt_mtl_regular_qp.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/*                  - Mellanox Confidential and Proprietary -
+ *
+ *  Copyright (C) Jul. 2001, Mellanox Technologies Ltd.  ALL RIGHTS RESERVED.
+ *
+ *  Except as specifically permitted herein, no portion of the information,
+ *  including but not limited to object code and source code, may be reproduced,
+ *  modified, distributed, republished or otherwise exploited in any form or by
+ *  any means for any purpose without the prior written permission of Mellanox
+ *  Technologies Ltd. Use of software subject to the terms and conditions
+ *  detailed in the file "LICENSE.txt".
+ *
+ *  End of legal section ......................................................
+ *
+ *  osmt_mtl_regular_qp.c -
+ *    Provide Simple Interface for Sending and Receiving MADS through a regular QP
+ *
+ *  Creation date:
+ *
+ *  Version: $Id$
+ *
+ *  Authors:
+ *    Eitan Zahavi
+ *
+ *  Changes:
+ */
+
+#include <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 */
diff --git a/osmtest/osmt_multicast.c b/osmtest/osmt_multicast.c
new file mode 100644
index 0000000..165457c
--- /dev/null
+++ b/osmtest/osmt_multicast.c
@@ -0,0 +1,2707 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ * 	Implementation of Multicast Member testing flow..
+ *
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_map.h>
+#include <complib/cl_list.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, "ERR 02B5: "
+			"Failed getting the multicast groups records - %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_err_str(context.result.status));
+		return;
+	}
+
+	osm_log(&p_osmt->log, OSM_LOG_INFO,
+		"\n                    |------------------------------------------|"
+		"\n                    |        Remaining Multicast Groups        |"
+		"\n                    |------------------------------------------|\n");
+
+	for (i = 0; i < context.result.result_cnt; i++) {
+		mcast_record =
+		    osmv_get_query_mc_rec(context.result.p_result_madw, i);
+		osm_dump_mc_record(&p_osmt->log, mcast_record, OSM_LOG_INFO);
+	}
+
+	/* Trusted - now get the multicast group members */
+	req.sm_key = OSM_DEFAULT_SM_KEY;
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+
+	if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B6: "
+			"Failed getting the multicast group members records - %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_err_str(context.result.status));
+		return;
+	}
+
+	osm_log(&p_osmt->log, OSM_LOG_INFO,
+		"\n                    |--------------------------------------------------|"
+		"\n                    |        Remaining Multicast Group Members        |"
+		"\n                    |--------------------------------------------------|\n");
+
+	for (i = 0; i < context.result.result_cnt; i++) {
+		mcast_record =
+		    osmv_get_query_mc_rec(context.result.p_result_madw, i);
+		osm_dump_mc_record(&p_osmt->log, mcast_record, OSM_LOG_INFO);
+	}
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static cl_status_t
+__match_mgids(IN const void *const p_object, IN void *context)
+{
+	ib_gid_t *p_mgid_context = (ib_gid_t *) context;
+	ib_gid_t *p_mgid_list_item = (ib_gid_t *) p_object;
+	int32_t count;
+
+	count = memcmp(p_mgid_context, p_mgid_list_item, sizeof(ib_gid_t));
+	if (count == 0)
+		return CL_SUCCESS;
+	else
+		return CL_NOT_FOUND;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t osmt_query_mcast(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	osmtest_req_context_t context;
+	ib_member_rec_t *p_rec;
+	uint32_t i, num_recs = 0;
+	cl_list_t mgids_list;
+	cl_list_t *p_mgids_list;
+	cl_list_iterator_t p_mgids_res;
+	cl_status_t cl_status;
+	cl_map_item_t *p_item, *p_next_item;
+	osmtest_mgrp_t *p_mgrp;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Do a blocking query for all Multicast Records in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+
+	context.p_osmt = p_osmt;
+	user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+	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, "ERR 0203: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0264: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s.\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/* ok we have got something */
+	/* First Delete the old MGID Table */
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.mgrp_mlid_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.mgrp_mlid_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		cl_qmap_remove_item(&p_osmt->exp_subn.mgrp_mlid_tbl, p_item);
+		free(p_item);
+
+	}
+
+	cl_list_construct(&mgids_list);
+	cl_list_init(&mgids_list, num_recs);
+	p_mgids_list = &mgids_list;
+	num_recs = context.result.result_cnt;
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n",
+		num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec = osmv_get_query_result(context.result.p_result_madw, i);
+		p_mgids_res =
+		    cl_list_find_from_head(p_mgids_list, __match_mgids,
+					   &(p_rec->mgid));
+		/* If returns iterator other than end of list, same mgid exists already */
+		if (p_mgids_res != cl_list_end(p_mgids_list)) {
+			char gid_str[INET6_ADDRSTRLEN];
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0265: "
+				"MCG MGIDs are the same - invalid MGID : %s\n",
+				inet_ntop(AF_INET6, p_rec->mgid.raw, gid_str,
+					  sizeof gid_str));
+			status = IB_ERROR;
+			goto Exit;
+
+		}
+		osm_dump_mc_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE);
+		cl_status = cl_list_insert_head(p_mgids_list, &(p_rec->mgid));
+		if (cl_status) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0205: "
+				"Could not add MGID to cl_list\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+		p_mgrp = (osmtest_mgrp_t *) malloc(sizeof(*p_mgrp));
+		if (!p_mgrp) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0204: "
+				"Could not allocate new MCG\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+		memcpy(&p_mgrp->mcmember_rec, p_rec,
+		       sizeof(p_mgrp->mcmember_rec));
+		cl_qmap_insert(&p_osmt->exp_subn.mgrp_mlid_tbl,
+			       cl_ntoh16(p_rec->mlid), &p_mgrp->map_item);
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+/* given a multicast request send and wait for response. */
+ib_api_status_t
+osmt_send_mcast_request(IN osmtest_t * const p_osmt,
+			IN uint8_t is_set,
+			IN ib_member_rec_t * p_mc_req,
+			IN uint64_t comp_mask, OUT ib_sa_mad_t * p_res)
+{
+	osmtest_req_context_t context;
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&context, 0, sizeof(context));
+	memset(p_res, 0, sizeof(ib_sa_mad_t));
+
+	context.p_osmt = p_osmt;
+
+	user.p_attr = p_mc_req;
+	user.comp_mask = comp_mask;
+
+	if (is_set == 1) {
+		req.query_type = OSMV_QUERY_UD_MULTICAST_SET;
+	} else if (is_set == 0) {
+		req.query_type = OSMV_QUERY_UD_MULTICAST_DELETE;
+	} else if (is_set == 0xee) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Set USER DEFINED QUERY\n");
+		req.query_type = OSMV_QUERY_USER_DEFINED;
+		user.method = IB_MAD_METHOD_GET;
+		user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+		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,
+			"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, "ERR 0206: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/* ok it worked */
+	memcpy(p_res,
+	       osm_madw_get_mad_ptr(context.result.p_result_madw),
+	       sizeof(ib_sa_mad_t));
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0224: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osmt_init_mc_query_rec(IN osmtest_t * const p_osmt,
+		       IN OUT ib_member_rec_t * p_mc_req)
+{
+	/* use default values so we can change only what we want later */
+	memset(p_mc_req, 0, sizeof(ib_member_rec_t));
+
+	/* we leave the MGID to the user */
+	memcpy(&p_mc_req->port_gid.unicast.interface_id,
+	       &p_osmt->local_port.port_guid,
+	       sizeof(p_osmt->local_port.port_guid)
+	    );
+
+	/*  use our own subnet prefix: */
+	p_mc_req->port_gid.unicast.prefix = CL_HTON64(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)
+{
+	char gid_str[INET6_ADDRSTRLEN];
+	char gid_str2[INET6_ADDRSTRLEN];
+	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);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "GetTable of all current MCGs...\n");
+	status = osmt_query_mcast(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 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, "(start): "
+			"Number of MC Records found in SA DB is %d\n",
+			start_cnt);
+	}
+
+	/* This flow is being added due to bug discovered using SilverStorm stack -
+	   The bug was initializing MCast with MTU & RATE min values that do
+	   not match the subnet capability, even though that OpenSM
+	   reponds with the correct value it does not store it in the MCG.
+	   We want the check a join request to already existing group (ipoib)
+	   without using MTU or RATE then getting response from OpenSM with
+	   the correct values then join again with them and get IB_SUCCESS
+	   all the way
+	 */
+
+	/* First validate IPoIB exist in the SA DB */
+	p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl);
+	/* scan all available multicast groups in the DB and fill in the table */
+	while (p_mgrp != (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) {
+		/* search for ipoib mgid */
+		if (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) {
+			start_ipoib_cnt++;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Non-IPoIB MC Groups exist: mgid=%s\n",
+				inet_ntop(AF_INET6,
+					  p_mgrp->mcmember_rec.mgid.raw,
+					  gid_str, sizeof gid_str));
+			mcg_outside_test_cnt++;
+		}
+
+		p_mgrp = (osmtest_mgrp_t *) cl_qmap_next(&p_mgrp->map_item);
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Found %d non-IPoIB MC Groups\n", mcg_outside_test_cnt);
+
+	if (start_ipoib_cnt) {
+		/* o15-0.2.4 - Check a join request to already created MCG */
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Found IPoIB MC Group, so we run SilverStorm Bug Flow...\n");
+		/* Try to join first like IPoIB of SilverStorm */
+		memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid,
+		       sizeof(ib_gid_t));
+		/* Request Join */
+		ib_member_set_join_state(&mc_req_rec,
+					 IB_MC_REC_STATE_FULL_MEMBER);
+		comp_mask =
+		    IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID |
+		    IB_MCR_COMPMASK_JOIN_STATE;
+
+		status = osmt_send_mcast_request(p_osmt, 0xff,	/* User Defined query Set */
+						 &mc_req_rec,
+						 comp_mask, &res_sa_mad);
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Joining an existing IPoIB multicast group\n");
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Sent Join request with :\n\t\tport_gid=%s, mgid=%s\n"
+			"\t\tjoin state= 0x%x, response is : %s\n",
+			inet_ntop(AF_INET6, mc_req_rec.port_gid.raw,
+				  gid_str, sizeof gid_str),
+			inet_ntop(AF_INET6, mc_req_rec.mgid.raw,
+				  gid_str2, sizeof gid_str2),
+			(mc_req_rec.scope_state & 0x0F),
+			ib_get_err_str(status));
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B3: "
+				"Failed joining existing IPoIB MCGroup - got %s\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		/* Check MTU & Rate Value and resend with SA suggested values */
+		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,
+			"Received attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n",
+			p_mc_res->mtu, p_mc_res->rate);
+
+		mc_req_rec.mtu = p_mc_res->mtu;
+		mc_req_rec.rate = p_mc_res->rate;
+		/* Set feasible mtu & rate that will allow check the
+		   exact statement of OpenSM */
+		mtu_phys = p_mc_res->mtu;
+		rate_phys = p_mc_res->rate;
+
+		memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid,
+		       sizeof(ib_gid_t));
+		/* Request Join */
+		ib_member_set_join_state(&mc_req_rec,
+					 IB_MC_REC_STATE_FULL_MEMBER);
+		comp_mask =
+		    IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID |
+		    IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_MTU_SEL |
+		    IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE_SEL |
+		    IB_MCR_COMPMASK_RATE;
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Sending attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n",
+			mc_req_rec.mtu, mc_req_rec.rate);
+		status = osmt_send_mcast_request(p_osmt, 0xff,	/* User Defined query */
+						 &mc_req_rec,
+						 comp_mask, &res_sa_mad);
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Sent Join request using response values, response is : %s\n",
+			ib_get_err_str(status));
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EF: "
+				"Query as Full Member of already existing "
+				"ipoib group gid %s has failed\n",
+				inet_ntop(AF_INET6, mc_req_rec.mgid.raw,
+					  gid_str, sizeof gid_str));
+			goto Exit;
+		}
+		/* We do not want to leave the MCG since its IPoIB */
+	}
+
+  /**************************************************************************/
+	/* Check Get with invalid mlid */
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Get with invalid mlid...\n");
+	/* Request Get */
+	ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+	mc_req_rec.mlid = invalid_mlid;
+	comp_mask = IB_MCR_COMPMASK_MLID;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 0xee,	/* User Defined query Get */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 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,
+		"Checking Get with invalid port guid (0x0) but valid interface ID : 0x%"
+		PRIx64 "...\n",
+		cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id));
+
+	/* Request Get */
+	ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+	memset(&mc_req_rec.port_gid.unicast.interface_id, 0,
+	       sizeof(ib_net64_t));
+	comp_mask = IB_MCR_COMPMASK_GID;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 0xee,	/* User Defined query Get */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"Checking Join with less than min rate 2.5GB (o15.0.1.8)...\n");
+
+	/* impossible requested rate */
+	mc_req_rec.rate =
+	    IB_PATH_RECORD_RATE_2_5_GBS | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking Join with unrealistic mtu : \n\t\tmore than 4096 -"
+		" max (o15.0.1.8)...\n");
+
+	/* impossible requested mtu */
+	mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking Join with unrealistic mtu : \n\t\tless than 256 -"
+		" min (o15.0.1.8)...\n");
+
+	/* impossible requested mtu */
+	mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking Join with unrealistic mtu (o15.0.1.8)...\n");
+
+	/* impossible requested mtu */
+	mc_req_rec.mtu = 0x6 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking Create with unrealistic packet life value less than 0 (o15.0.1.8)...\n");
+
+	/* impossible requested packet life */
+	mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_LIFE | IB_MCR_COMPMASK_LIFE_SEL;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"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, 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, 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, "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, "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, "(post false create): "
+			"Number of MC Records found in SA DB is %d\n",
+			middle_cnt);
+		if (middle_cnt != start_cnt) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Got different number of records stored in SA DB (before any creation)\n"
+				"Instead of %d got %d\n", start_cnt,
+				middle_cnt);
+		}
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n");
+
+	osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+	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, 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, 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, "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,
+		"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, 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, 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, "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,
+		"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, "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, "created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Validating resulting MGID (o15.0.1.5)...\n");
+	/* prefix 0xFF1 Scope 0xA01B */
+	/* Since we did not directly specified SCOPE in comp mask
+	   we should get the comp mask that is link-local scope */
+	if ((p_mc_res->mgid.multicast.header[0] != 0xFF) ||
+	    (p_mc_res->mgid.multicast.header[1] != 0x12) ||
+	    (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+	    (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1B)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0209: "
+			"Validating MGID failed. MGID:%s\n",
+			inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str,
+				  sizeof gid_str));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+	/* Using feasible GREATER_THAN 0 packet lifitime */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Create given MGID=0 (o15.0.1.4)...\n");
+
+	status = osmt_query_mcast(p_osmt);
+
+	osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+	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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Checking Create given valid MGID=%s (o15.0.1.6)...\n",
+		inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str,
+			  sizeof gid_str));
+
+	/* Before creation, need to check that this group doesn't exist */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Verifying that MCGroup with this MGID doesn't exist by trying to Join it (o15.0.1.13)...\n");
+
+	ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,	/* join */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Now creating group with given valid MGID=%s (o15.0.1.6)...\n",
+		inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str,
+			  sizeof gid_str));
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0211: "
+			"Failed to create MCG for MGID=%s (o15.0.1.6) - got %s/%s\n",
+			inet_ntop(AF_INET6, good_mgid.raw, gid_str,
+				  sizeof gid_str), ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Validating resulting MGID (o15.0.1.6)...\n");
+	/* prefix 0xFF1 Scope 0xA01B */
+	if ((p_mc_res->mgid.multicast.header[0] != 0xFF) || (p_mc_res->mgid.multicast.header[1] != 0x12) ||	/* HACK hardcoded scope = 0x02 */
+	    (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+	    (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1C)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0212: "
+			"Validating MGID failed. MGID:%s\n",
+			inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str,
+				  sizeof gid_str));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking BAD MGID=0xFA..... (o15.0.1.6)...\n");
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid.raw[0] = 0xFA;
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking BAD MGID=0xFF12A01B..... with link-local scope (o15.0.1.6)...\n");
+
+	mc_req_rec.mgid.raw[0] = 0xFF;
+	mc_req_rec.mgid.raw[3] = 0x1B;
+	comp_mask = comp_mask | IB_MCR_COMPMASK_SCOPE;
+	mc_req_rec.scope_state = mc_req_rec.scope_state & 0x2F;	/* local scope */
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking BAD MGID PREFIX=0xEF... (o15.0.1.6)...\n");
+
+	mc_req_rec.mgid = good_mgid;
+
+	mc_req_rec.mgid.raw[0] = 0xEF;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking local scope with full member \n\t\tand valid mgid %s"
+		"  ... (o15.0.1.6)...\n",
+		inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str,
+			  sizeof gid_str));
+
+	mc_req_rec.mgid = good_mgid;
+
+	mc_req_rec.mgid.raw[1] = 0x1F;
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0216: "
+			"Failed to create MCG for MGID=%s - got %s/%s\n",
+			inet_ntop(AF_INET6, good_mgid.raw, gid_str,
+				  sizeof gid_str), ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Checking invalid flags=0xFF 22  ... (o15.0.1.6)...\n");
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = good_mgid;
+
+	mc_req_rec.mgid.raw[1] = 0x22;
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Checking new MGID with invalid join state (o15.0.1.9)...\n");
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = good_mgid;
+	mc_req_rec.mgid.raw[12] = 0xFF;
+	mc_req_rec.scope_state = 0x22;	/* link-local scope, non-member state */
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"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, "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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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,
+		"Checking new MGID with invalid join state (o15.0.1.9)...\n");
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	/* We have created a new MCG so now we need different mgid when 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, 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, "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,
+		"Checking new MGID creation with valid join state (o15.0.2.3)...\n");
+
+	mc_req_rec.mgid = good_mgid;
+	mc_req_rec.mgid.raw[12] = 0xFB;
+	memcpy(&special_mgid, &mc_req_rec.mgid, sizeof(ib_gid_t));
+	mc_req_rec.scope_state = 0x2F;	/* link-local scope, Full member with all other bits turned on */
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0222: "
+			"Failed to create MCG with valid join state 0xF - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&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, "Created MGID:%s MLID:0x%04X\n",
+		inet_ntop(AF_INET6, p_recvd_rec->mgid.raw, gid_str,
+			  sizeof gid_str), 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, "Check o15-0.2.4 statement...\n");
+	/* Try to join */
+	memcpy(&mc_req_rec.mgid, &p_mc_res->mgid, sizeof(ib_gid_t));
+	/* Request Join */
+	ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER);
+	comp_mask =
+	    IB_MCR_COMPMASK_MGID |
+	    IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE;
+
+	status = osmt_send_mcast_request(p_osmt, 0x1,	/* SubnAdmSet */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CC: "
+			"Failed to join MCG with valid req, returned status = %s\n",
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+	if ((p_mc_res->scope_state & 0x7) != 0x7) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D0: "
+			"Validating JoinState update failed. "
+			"Expected 0x27 got 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* o15.0.1.11: */
+	/* - Try to join into a MGID that exists with JoinState=SendOnlyMember -  */
+	/*   see that it updates JoinState. What is the routing change? */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n");
+
+	mc_req_rec.mgid = good_mgid;
+
+	/* first, make sure  that the group exists */
+	mc_req_rec.scope_state = 0x21;
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CD: "
+			"Failed to create/join as full member - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	mc_req_rec.scope_state = 0x22;	/* link-local scope, non-member */
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D1: "
+			"Failed to update existing MGID - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Validating Join State update with NonMember (o15.0.1.11)...\n");
+
+	if (p_mc_res->scope_state != 0x23) {	/* scope is LSB */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CE: "
+			"Validating JoinState update failed. Expected 0x23 got: 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Try delete current join state then update it with another value  */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking JoinState update request should return 0x22 (o15.0.1.11)...\n");
+
+	mc_req_rec.rate =
+	    IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	mc_req_rec.mgid = good_mgid;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Partially delete JoinState (o15.0.1.14)...\n");
+
+	/* link-local scope, both non-member bits,
+	   so we should not be able to delete) */
+	mc_req_rec.scope_state = 0x26;
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 0,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status != IB_REMOTE_ERROR) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CF: "
+			"Expected to fail partially update JoinState, "
+			"but got %s\n",
+			ib_get_err_str(status));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* link-local scope, NonMember bit, the FullMember bit should stay */
+	mc_req_rec.scope_state = 0x22;
+	status = osmt_send_mcast_request(p_osmt, 0,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D3: "
+			"Failed to partially update JoinState : %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+	if (p_mc_res->scope_state != 0x21) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D4: "
+			"Failed to partially update JoinState : "
+			"JoinState = 0x%02X, expected 0x%02X\n",
+			p_mc_res->scope_state, 0x21);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* So far successfully delete state - Now change it */
+	mc_req_rec.mgid = good_mgid;
+	mc_req_rec.scope_state = 0x24;	/* link-local scope, send only  member */
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C0: "
+			"Failed to update existing MCG - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Validating Join State update with Send Only Member (o15.0.1.11)...\n");
+
+	if (p_mc_res->scope_state != 0x25) {	/* scope is MSB */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C1: "
+			"Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+	/* Now try to update value of join state */
+	mc_req_rec.scope_state = 0x21;	/* link-local scope, full member */
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C2: "
+			"Failed to update existing MGID - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Validating Join State update with Full Member\n\t\t"
+		"to an existing 0x5 state MCG (o15.0.1.11)...\n");
+
+	if (p_mc_res->scope_state != 0x25) {	/* scope is LSB */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C3: "
+			"Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Now try to update value of join state */
+	mc_req_rec.scope_state = 0x22;	/* link-local scope,non member */
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C4: "
+			"Failed to update existing MGID - got %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Validating Join State update with Non Member\n\t\t"
+		"to an existing 0x5 state MCG (o15.0.1.11)...\n");
+
+	if (p_mc_res->scope_state != 0x27) {	/* scope is LSB */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C5: "
+			"Validating JoinState update failed. Expected 0x27 got: 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"DEBUG - Current scope_state value : 0x%02X...\n",
+		p_mc_res->scope_state);
+
+	/* - We can not check simple join since we have only one tester (for now) */
+
+	/* o15.0.1.12: Not Supported */
+	/* - The SendOnlyNonMem join should have a special treatment in the
+	   SA but what is it ? */
+
+	/* o15.0.1.13: */
+	/* - Try joining with rate that does not exist in any MCG -
+	   ERR_REQ_INVALID */
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n");
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = good_mgid;
+	mc_req_rec.rate =
+	    IB_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, 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, "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,
+		"Checking BAD MTU (higher them max) when connecting to "
+		"existing MGID (o15.0.1.13)...\n");
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = osm_ipoib_mgid;
+	mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking BAD MTU (less than min) when connecting "
+		"to existing MGID (o15.0.1.13)...\n");
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = osm_ipoib_mgid;
+	mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6;
+	comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS |	/* all above are required */
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"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 NonMember 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, "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,
+		"Validating Join State removal of Non Member bit (o15.0.1.14)...\n");
+	if (p_mc_res->scope_state != 0x25) {	/* scope is MSB - now only the full member & send only member have left */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CA: "
+			"Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+			p_mc_res->scope_state);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Now use the same scope_state and delete all JoinState - leave multicast group since state is 0x0 */
+
+	mc_req_rec.scope_state = 0x25;
+	status = osmt_send_mcast_request(p_osmt, 0,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CB: "
+			"Failed to update JoinState during delete: %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Validating Join State update remove (o15.0.1.14)...\n");
+
+	if (p_mc_res->scope_state != 0x25) {	/* scope is MSB - now only 0x0 so port is removed from MCG */
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BF: "
+			"Validating JoinState update failed. Expected 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,
+		"Checking Delete by trying to Join deleted group (o15.0.1.13)...\n");
+
+	mc_req_rec.scope_state = 0x22;	/* use non member - so if no group fail */
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,	/* join */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status != IB_REMOTE_ERROR) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BC: "
+			"Succeeded Joining Deleted Group: %s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&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,
+		"Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n");
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = osm_ipoib_mgid;
+	mc_req_rec.rate =
+	    IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	mc_req_rec.scope_state = 0x21;	/* delete full member */
+
+	status = osmt_send_mcast_request(p_osmt, 0,	/* delete flag */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"Checking Create given MGID=%s\n\t\t(o15.0.1.4)...\n",
+		inet_ntop(AF_INET6, osm_ipoib_mgid.raw, gid_str,
+			  sizeof gid_str));
+
+	mc_req_rec.mgid = good_mgid;
+	mc_req_rec.mgid.raw[12] = 0xAA;
+	mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	mc_req_rec.scope_state = 0x21;	/* Full 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, "ERR 02BE: "
+			"Failed to create MCG for %s - got %s/%s\n",
+			inet_ntop(AF_INET6, good_mgid.raw, gid_str,
+				  sizeof gid_str), ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&res_sa_mad)));
+		goto Exit;
+	}
+
+	/* - Try delete with valid join state */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Checking Full Delete of a group (o15.0.1.14)...\n");
+	mc_req_rec.scope_state = 0x21;	/* the FullMember is the current JoinState */
+	status = osmt_send_mcast_request(p_osmt, 0,
+					 &mc_req_rec, comp_mask, &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,
+		"Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n");
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+	mc_req_rec.mgid = osm_ipoib_mgid;
+	mc_req_rec.rate =
+	    IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	mc_req_rec.scope_state = 0x21;	/* delete full member */
+
+	status = osmt_send_mcast_request(p_osmt, 0,	/* delete flag */
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 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, "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,
+		"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, "ERR 02EB: "
+			"Failed to create new mgrp\n");
+		goto Exit;
+	}
+	memcpy(&tmp_mgid, &p_mc_res->mgid, sizeof(ib_gid_t));
+	osm_dump_mc_record(&p_osmt->log, p_mc_res, OSM_LOG_INFO);
+	/* tmp_mtu = p_mc_res->mtu & 0x3F; */
+
+	/* impossible requested mtu always greater than exist in MCG */
+	mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+	memcpy(&mc_req_rec.mgid, &tmp_mgid, sizeof(ib_gid_t));
+	ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+	comp_mask =
+	    IB_MCR_COMPMASK_GID |
+	    IB_MCR_COMPMASK_PORT_GID |
+	    IB_MCR_COMPMASK_JOIN_STATE |
+	    IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmt_send_mcast_request(p_osmt, 1,
+					 &mc_req_rec, comp_mask, &res_sa_mad);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E4: "
+			"Expected REMOTE ERROR got:%s/%s\n",
+			ib_get_err_str(status),
+			ib_get_mad_status_str((ib_mad_t *) (&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, "(Before checking Max MCG creation): "
+		"Number of MC Records found in SA DB is %d\n", cnt);
+
+  /**************************************************************************/
+	/* Checking join on behalf of remote port gid */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Proxy Join...\n");
+	osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E5: "
+			"osmtest_get_all_recs failed on getting all node records(%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Populate the database with the received records.
+	 */
+	num_recs = context.result.result_cnt;
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_node_rec(context.result.p_result_madw, i);
+		if (p_rec->node_info.port_guid != p_osmt->local_port.port_guid
+		    && p_rec->node_info.node_type == IB_NODE_TYPE_CA) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+				"remote port_guid = 0x%" PRIx64 "\n",
+				cl_ntoh64(p_rec->node_info.port_guid));
+
+			remote_port_guid = p_rec->node_info.port_guid;
+			i = num_recs;
+			break;
+		}
+	}
+
+	if (remote_port_guid != 0x0) {
+		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, "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,
+			"Trying deletion of remote port with local port guid\n");
+
+		osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+		ib_member_set_join_state(&mc_req_rec,
+					 IB_MC_REC_STATE_FULL_MEMBER);
+		comp_mask =
+		    IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID |
+		    IB_MCR_COMPMASK_JOIN_STATE;
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+
+		status = osmt_send_mcast_request(p_osmt, 0,	/* delete flag */
+						 &mc_req_rec,
+						 comp_mask, &res_sa_mad);
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+		if (status == IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A9: "
+				"Successful deletion of remote port guid with local one MGID : "
+				"%s, Got : %s/%s\n",
+				inet_ntop(AF_INET6,
+					p_mgrp->mcmember_rec.mgid.raw,
+					gid_str, sizeof gid_str),
+				ib_get_err_str(status),
+				ib_get_mad_status_str((ib_mad_t
+						       *) (&res_sa_mad)));
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Trying deletion of remote port with the right port guid\n");
+
+		osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+		ib_member_set_join_state(&mc_req_rec,
+					 IB_MC_REC_STATE_FULL_MEMBER);
+		mc_req_rec.mgid = proxy_mgid;
+		mc_req_rec.port_gid.unicast.interface_id = remote_port_guid;
+		comp_mask =
+		    IB_MCR_COMPMASK_MGID |
+		    IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE;
+		status = osmt_send_mcast_request(p_osmt, 0,	/* delete flag */
+						 &mc_req_rec,
+						 comp_mask, &res_sa_mad);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B0: "
+				"Failed to delete mgid with remote port guid MGID : "
+				"%s, Got : %s/%s\n",
+				inet_ntop(AF_INET6,
+					p_mgrp->mcmember_rec.mgid.raw,
+					gid_str, sizeof gid_str),
+				ib_get_err_str(status),
+				ib_get_mad_status_str((ib_mad_t
+						       *) (&res_sa_mad)));
+			goto Exit;
+		}
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Could not check proxy join since could not found remote port, different from local port\n");
+	}
+
+	/* prepare init for next check */
+	osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  /**************************************************************************/
+	if (p_osmt->opt.mmode > 2) {
+		/* Check invalid Join with max mlid which is more than the
+		   Mellanox switches support 0xC000+0x1000 = 0xd000 */
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+			"Checking Creation of Maximum avaliable Groups (MulticastFDBCap)...\n");
+		tmp_mlid = cl_ntoh16(max_mlid) - cnt;
+
+		while (tmp_mlid > 0 && !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,
+						"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,
+					"Created MGID:%s MLID:0x%04X\n",
+					inet_ntop(AF_INET6,
+						  p_recvd_rec->mgid.raw,
+						  gid_str, sizeof gid_str),
+					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, "ERR 02B1: "
+			"Failed to query multicast groups: %s\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "(Before Deletion of all MCG): "
+		"Number of MC Records found in SA DB is %d\n", cnt);
+
+	/* Delete all MCG that are not of IPoIB */
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Cleanup all MCG that are not IPoIB...\n");
+
+	p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+	p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl);
+	/* scan all available multicast groups in the DB and fill in the table */
+	while (p_mgrp != (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) {
+		/* Only if different from IPoIB Mgid try to delete */
+		if (!IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) {
+			osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+			mc_req_rec.mgid = p_mgrp->mcmember_rec.mgid;
+
+			/* o15-0.1.4 - need to specify the oppsite state for a valid delete */
+			if (!memcmp
+			    (&special_mgid, &p_mgrp->mcmember_rec.mgid,
+			     sizeof(special_mgid))) {
+				mc_req_rec.scope_state = 0x2F;
+			} else {
+				mc_req_rec.scope_state = 0x21;
+			}
+			comp_mask =
+			    IB_MCR_COMPMASK_MGID |
+			    IB_MCR_COMPMASK_PORT_GID |
+			    IB_MCR_COMPMASK_JOIN_STATE;
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+				"Sending request to delete MGID : %s"
+				", scope_state : 0x%02X\n",
+				inet_ntop(AF_INET6, mc_req_rec.mgid.raw,
+					  gid_str, sizeof gid_str),
+				mc_req_rec.scope_state);
+			status = osmt_send_mcast_request(p_osmt, 0,	/* delete flag */
+							 &mc_req_rec,
+							 comp_mask,
+							 &res_sa_mad);
+			if (status != IB_SUCCESS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+					"ERR 02FF: Failed to delete MGID : %s"
+					" ,\n\t\t it is not our MCG, Status : %s/%s\n",
+					inet_ntop(AF_INET6,
+						  p_mgrp->mcmember_rec.mgid.raw,
+						  gid_str, sizeof gid_str),
+					ib_get_err_str(status),
+					ib_get_mad_status_str((ib_mad_t *)
+							      (&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, "ERR 02B2 "
+			"GetTable of all records has failed - got %s\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/* If we are in single mode check flow - need to make sure all the multicast groups
+	   that are left are not ones created during the flow.
+	 */
+	if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) {
+		end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Status of MC Records in SA DB during the test flow:\n" "  Beginning of test\n" "       Unrelated to the test: %d\n" "       IPoIB MC Records     : %d\n" "       Total                : %d\n" "  End of test\n" "       Failed to delete     : %d\n" "       IPoIB MC Records     : %d\n" "       Total                : %d\n", mcg_outside_test_cnt,	/* Non-IPoIB that existed at the beginning */
+			start_ipoib_cnt,	/* IPoIB records */
+			start_cnt,	/* Total: IPoIB and MC Records unrelated to the test */
+			fail_to_delete_mcg,	/* Failed to delete at the end */
+			end_ipoib_cnt,	/* IPoIB records */
+			end_cnt);	/* Total MC Records at the end */
+
+		/* when we compare num of MCG we should consider an outside source which create other MCGs */
+		if ((end_cnt - fail_to_delete_mcg - end_ipoib_cnt) !=
+		    (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt)) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Got different number of non-IPoIB records stored in SA DB\n\t\t"
+				"at Start got %d, at End got %d (IPoIB groups only)\n",
+				(start_cnt - mcg_outside_test_cnt -
+				 start_ipoib_cnt),
+				(end_cnt - fail_to_delete_mcg - end_ipoib_cnt));
+		}
+
+		p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+		p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl);
+		while (p_mgrp !=
+		       (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) {
+			uint16_t mlid =
+			    (uint16_t) cl_qmap_key((cl_map_item_t *) p_mgrp);
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Found MLID:0x%04X\n", mlid);
+			/* Check if the mlid is in the test_created_mlids. If TRUE, then we
+			   didn't delete a MCgroup that was created in this flow. */
+			if (cl_map_get(&test_created_mlids, mlid) != NULL) {
+				/* This means that we still have an mgrp that we created!! */
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02FE: "
+					"Wasn't able to erase mgrp with MGID:%s"
+					" MLID:0x%04X\n",
+					inet_ntop(AF_INET6,
+						  p_mgrp->mcmember_rec.mgid.raw,
+						  gid_str, sizeof gid_str),
+					mlid);
+				got_error = TRUE;
+			} else {
+				OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+					"Still exists %s MGID:%s\n",
+					(IS_IPOIB_MGID
+					 (&p_mgrp->mcmember_rec.
+					  mgid)) ? "IPoIB" : "non-IPoIB",
+					inet_ntop(AF_INET6,
+						p_mgrp->mcmember_rec.mgid.raw,
+						gid_str, sizeof gid_str));
+			}
+			p_mgrp =
+			    (osmtest_mgrp_t *) cl_qmap_next(&p_mgrp->map_item);
+		}
+
+		if (got_error) {
+			__osmt_print_all_multicast_records(p_osmt);
+			status = IB_ERROR;
+		}
+	}
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
diff --git a/osmtest/osmt_service.c b/osmtest/osmt_service.c
new file mode 100644
index 0000000..97f1492
--- /dev/null
+++ b/osmtest/osmt_service.c
@@ -0,0 +1,1616 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of service records testing flow..
+ *    Top level is osmt_run_service_records_flow:
+ *     osmt_register_service
+ *     osmt_get_service_by_name
+ *     osmt_get_all_services
+ *     osmt_delete_service_by_name
+ *
+ */
+
+#ifndef __WIN__
+#include <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);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Registering service: name: %s id: 0x%" PRIx64 "\n",
+		service_name, cl_ntoh64(service_id));
+
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+	memset(&user, 0, sizeof(user));
+	memset(&svc_rec, 0, sizeof(svc_rec));
+
+	/* set the new service record fields */
+	svc_rec.service_id = service_id;
+	svc_rec.service_pkey = service_pkey;
+	svc_rec.service_gid.unicast.prefix = 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, "ERR 4A01: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A02: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_register_service_with_full_key(IN osmtest_t * const p_osmt,
+				    IN ib_net64_t service_id,
+				    IN ib_net16_t service_pkey,
+				    IN ib_net32_t service_lease,
+				    IN uint8_t * service_key,
+				    IN char *service_name)
+{
+	osmv_query_req_t req;
+	osmv_user_query_t user;
+	osmtest_req_context_t context;
+	ib_service_record_t svc_rec, *p_rec;
+	osm_log_t *p_log = &p_osmt->log;
+	ib_api_status_t status;
+	uint8_t i, skey[16];
+
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Registering service: name: %s id: 0x%" PRIx64 "\n",
+		service_name, cl_ntoh64(service_id));
+
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+	memset(&user, 0, sizeof(user));
+	memset(&svc_rec, 0, sizeof(svc_rec));
+
+	/* set the new service record fields */
+	svc_rec.service_id = service_id;
+	svc_rec.service_pkey = service_pkey;
+	svc_rec.service_gid.unicast.prefix = 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, "ERR 4A03: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A04: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/*  Check service key on context to see if match */
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Comparing service key...\n" "return key is:\n");
+	for (i = 0; i <= 15; i++) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"service_key sent[%u] = %u, service_key returned[%u] = %u\n",
+			i, service_key[i], i, p_rec->service_key[i]);
+	}
+	/*  since c15-0.1.14 not supported all key association queries should bring in return zero in service key */
+	if (memcmp(skey, p_rec->service_key, 16 * sizeof(uint8_t)) != 0) {
+		status = IB_REMOTE_ERROR;
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A33: "
+			"Data mismatch in service_key\n");
+		goto Exit;
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_register_service_with_data(IN osmtest_t * const p_osmt,
+				IN ib_net64_t service_id,
+				IN ib_net16_t service_pkey,
+				IN ib_net32_t service_lease,
+				IN uint8_t service_key_lsb,
+				IN uint8_t * service_data8,
+				IN ib_net16_t * service_data16,
+				IN ib_net32_t * service_data32,
+				IN ib_net64_t * service_data64,
+				IN char *service_name)
+{
+	osmv_query_req_t req;
+	osmv_user_query_t user;
+	osmtest_req_context_t context;
+	ib_service_record_t svc_rec, *p_rec;
+	osm_log_t *p_log = &p_osmt->log;
+	ib_api_status_t status;
+	/*   ib_service_record_t* p_rec; */
+
+	OSM_LOG_ENTER(p_log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Registering service: name: %s id: 0x%" PRIx64 "\n",
+		service_name, cl_ntoh64(service_id));
+
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+	memset(&user, 0, sizeof(user));
+	memset(&svc_rec, 0, sizeof(svc_rec));
+
+	/* set the new service record fields */
+	svc_rec.service_id = service_id;
+	svc_rec.service_pkey = service_pkey;
+	svc_rec.service_gid.unicast.prefix = 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,
+		"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, "ERR 4A05: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A06: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/*  Check data on context to see if match */
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Comparing service data...\n");
+	if (memcmp(service_data8, p_rec->service_data8, 16 * sizeof(uint8_t)) !=
+	    0
+	    || memcmp(service_data16, p_rec->service_data16,
+		      8 * sizeof(uint16_t)) != 0
+	    || memcmp(service_data32, p_rec->service_data32,
+		      4 * sizeof(uint32_t)) != 0
+	    || memcmp(service_data64, p_rec->service_data64,
+		      2 * sizeof(uint64_t)) != 0) {
+		status = IB_REMOTE_ERROR;
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Data mismatch in service_data8\n");
+		goto Exit;
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_id_and_name(IN osmtest_t * const p_osmt,
+				IN uint32_t rec_num,
+				IN ib_net64_t sid,
+				IN char *sr_name,
+				OUT ib_service_record_t * p_out_rec)
+{
+
+	ib_api_status_t status = IB_SUCCESS;
+	osmtest_req_context_t context;
+	osmv_query_req_t req;
+	ib_service_record_t svc_rec, *p_rec;
+	uint32_t num_recs = 0;
+	osmv_user_query_t user;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting service record: id: 0x%016" PRIx64
+		" and name: %s\n", cl_ntoh64(sid), sr_name);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	/* prepare the data used for this query */
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.sm_key = 0;
+
+	memset(&svc_rec, 0, sizeof(svc_rec));
+	memset(&user, 0, sizeof(user));
+	/* set the new service record fields */
+	memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+	memcpy(svc_rec.service_name, sr_name,
+	       (strlen(sr_name) + 1) * sizeof(char));
+	svc_rec.service_id = sid;
+	req.p_query_input = &user;
+
+	user.method = IB_MAD_METHOD_GET;
+	user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+	user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SNAME;
+	user.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, "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,
+				"IS EXPECTED ERROR ^^^^\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A08: "
+				"Query failed: %s (%s)\n",
+				ib_get_err_str(status), mad_stat_err);
+			goto Exit;
+		}
+	}
+
+	if (rec_num && num_recs != rec_num) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Unmatched number of records: expected: %d, received: %d\n",
+			rec_num, num_recs);
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	*p_out_rec = *p_rec;
+
+	if (num_recs) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Found service record: name: %s id: 0x%016" PRIx64 "\n",
+			p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+		osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+	}
+
+Exit:
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Expected and found %d records\n", rec_num);
+
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_id(IN osmtest_t * const p_osmt,
+		       IN uint32_t rec_num,
+		       IN ib_net64_t sid, OUT ib_service_record_t * p_out_rec)
+{
+
+	ib_api_status_t status = IB_SUCCESS;
+	osmtest_req_context_t context;
+	osmv_query_req_t req;
+	ib_service_record_t svc_rec, *p_rec;
+	uint32_t num_recs = 0;
+	osmv_user_query_t user;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting service record: id: 0x%016" PRIx64 "\n",
+		cl_ntoh64(sid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	/* prepare the data used for this query */
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.sm_key = 0;
+
+	memset(&svc_rec, 0, sizeof(svc_rec));
+	memset(&user, 0, sizeof(user));
+	/* set the new service record fields */
+	svc_rec.service_id = sid;
+	req.p_query_input = &user;
+
+	user.method = IB_MAD_METHOD_GET;
+	user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+	user.comp_mask = IB_SR_COMPMASK_SID;
+	user.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, "ERR 4A09: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+	num_recs = context.result.result_cnt;
+
+	if (status != IB_SUCCESS) {
+		char mad_stat_err[256];
+
+		/* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+		   then this is fine */
+		if (status == IB_REMOTE_ERROR)
+			strcpy(mad_stat_err,
+			       ib_get_mad_status_str(osm_madw_get_mad_ptr
+						     (context.result.
+						      p_result_madw)));
+		else
+			strcpy(mad_stat_err, ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR &&
+		    !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+		    rec_num == 0) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"IS EXPECTED ERROR ^^^^\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0A: "
+				"Query failed: %s (%s)\n",
+				ib_get_err_str(status), mad_stat_err);
+			goto Exit;
+		}
+	}
+
+	if (rec_num && num_recs != rec_num) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0B: "
+			"Unmatched number of records: expected: %d received: %d\n",
+			rec_num, num_recs);
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	*p_out_rec = *p_rec;
+
+	if (num_recs) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Found service record: name: %s id: 0x%016" PRIx64 "\n",
+			p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+		osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+	}
+
+Exit:
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Expected and found %d records\n", rec_num);
+
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_name_and_key(IN osmtest_t * const p_osmt,
+				 IN char *sr_name,
+				 IN uint32_t rec_num,
+				 IN uint8_t * skey,
+				 OUT ib_service_record_t * p_out_rec)
+{
+
+	ib_api_status_t status = IB_SUCCESS;
+	osmtest_req_context_t context;
+	osmv_query_req_t req;
+	ib_service_record_t svc_rec, *p_rec;
+	uint32_t num_recs = 0, i;
+	osmv_user_query_t user;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting service record: name: %s and key: "
+		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+		sr_name, skey[0], skey[1], skey[2], skey[3], skey[4], skey[5],
+		skey[6], skey[7], skey[8], skey[9], skey[10], skey[11],
+		skey[12], skey[13], skey[14], skey[15]);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	/* prepare the data used for this query */
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.sm_key = 0;
+
+	memset(&svc_rec, 0, sizeof(svc_rec));
+	memset(&user, 0, sizeof(user));
+	/* set the new service record fields */
+	memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+	memcpy(svc_rec.service_name, sr_name,
+	       (strlen(sr_name) + 1) * sizeof(char));
+	for (i = 0; i <= 15; i++)
+		svc_rec.service_key[i] = skey[i];
+
+	req.p_query_input = &user;
+
+	user.method = IB_MAD_METHOD_GET;
+	user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+	user.comp_mask = IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SKEY;
+	user.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, "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,
+				"IS EXPECTED ERROR ^^^^\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0D: "
+				"Query failed:%s (%s)\n",
+				ib_get_err_str(status), mad_stat_err);
+			goto Exit;
+		}
+	}
+
+	if (rec_num && num_recs != rec_num) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Unmatched number of records: expected: %d, received: %d\n",
+			rec_num, num_recs);
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	*p_out_rec = *p_rec;
+
+	if (num_recs) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Found service record: name: %s id: 0x%016" PRIx64 "\n",
+			sr_name, cl_ntoh64(p_rec->service_id));
+
+		osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+	}
+
+Exit:
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Expected and found %d records\n", rec_num);
+
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_name(IN osmtest_t * const p_osmt,
+			 IN char *sr_name,
+			 IN uint32_t rec_num,
+			 OUT ib_service_record_t * p_out_rec)
+{
+
+	ib_api_status_t status = IB_SUCCESS;
+	osmtest_req_context_t context;
+	osmv_query_req_t req;
+	ib_service_record_t *p_rec;
+	ib_svc_name_t service_name;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting service record: name: %s\n", sr_name);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	/* prepare the data used for this query */
+	req.query_type = OSMV_QUERY_SVC_REC_BY_NAME;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.sm_key = 0;
+
+	memset(service_name, 0, sizeof(service_name));
+	memcpy(service_name, sr_name, (strlen(sr_name) + 1) * sizeof(char));
+	req.p_query_input = service_name;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0E: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+	num_recs = context.result.result_cnt;
+
+	if (status != IB_SUCCESS) {
+		char mad_stat_err[256];
+
+		/*  If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+		   then this is fine */
+		if (status == IB_REMOTE_ERROR)
+			strcpy(mad_stat_err,
+			       ib_get_mad_status_str(osm_madw_get_mad_ptr
+						     (context.result.
+						      p_result_madw)));
+		else
+			strcpy(mad_stat_err, ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR &&
+		    !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+		    rec_num == 0) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"IS EXPECTED ERROR ^^^^\n");
+			status = IB_SUCCESS;
+		} else {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0F: "
+				"Query failed: %s (%s)\n",
+				ib_get_err_str(status), mad_stat_err);
+			goto Exit;
+		}
+	}
+
+	if (rec_num && num_recs != rec_num) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A10: "
+			"Unmatched number of records: expected: %d, received: %d\n",
+			rec_num, num_recs);
+		status = IB_REMOTE_ERROR;
+		goto Exit;
+	}
+
+	p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0);
+	*p_out_rec = *p_rec;
+
+	if (num_recs) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Found service record: name: %s id: 0x%016" PRIx64 "\n",
+			sr_name, cl_ntoh64(p_rec->service_id));
+
+		osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+	}
+
+Exit:
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Expected and found %d records\n", rec_num);
+
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+#ifdef VENDOR_RMPP_SUPPORT
+ib_api_status_t
+osmt_get_all_services_and_check_names(IN osmtest_t * const p_osmt,
+				      IN ib_svc_name_t *
+				      const p_valid_service_names_arr,
+				      IN uint8_t num_of_valid_names,
+				      OUT uint32_t * num_services)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmtest_req_context_t context;
+	osmv_query_req_t req;
+	ib_service_record_t *p_rec;
+	uint32_t num_recs = 0, i, j;
+	uint8_t *p_checked_names;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/* Prepare tracker for the checked names */
+	p_checked_names =
+	    (uint8_t *) malloc(sizeof(uint8_t) * num_of_valid_names);
+	for (j = 0; j < num_of_valid_names; j++) {
+		p_checked_names[j] = 0;
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting all service records\n");
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	req.query_type = OSMV_QUERY_ALL_SVC_RECS;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A12: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		if (status != IB_INVALID_PARAMETER) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A13: "
+				"ib_query failed (%s)\n", ib_get_err_str(status));
+		}
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Received %u records\n", num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, i);
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Found service record: name: %s id: 0x%016" PRIx64 "\n",
+			p_rec->service_name, cl_ntoh64(p_rec->service_id));
+		osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE);
+		for (j = 0; j < num_of_valid_names; j++) {
+			/* If the service names exist in the record, mark it as checked (1) */
+			OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+				"-I- Comparing source name : >%s<, with record name : >%s<, idx : %d\n",
+				p_valid_service_names_arr[j],
+				p_rec->service_name, p_checked_names[j]);
+			if (strcmp
+			    ((char *)p_valid_service_names_arr[j],
+			     (char *)p_rec->service_name) == 0) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+					"-I- The service %s is valid\n",
+					p_valid_service_names_arr[j]);
+				p_checked_names[j] = 1;
+				break;
+			}
+		}
+	}
+	/* Check that all service names have been identified */
+	for (j = 0; j < num_of_valid_names; j++)
+		if (p_checked_names[j] == 0) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A14: "
+				"Missing valid service: name: %s\n",
+				p_valid_service_names_arr[j]);
+			status = IB_ERROR;
+			goto Exit;
+		}
+	*num_services = num_recs;
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_delete_service_by_name(IN osmtest_t * const p_osmt,
+			    IN uint8_t IsServiceExist,
+			    IN char *sr_name, IN uint32_t rec_num)
+{
+	osmv_query_req_t req;
+	osmv_user_query_t user;
+	osmtest_req_context_t context;
+	ib_service_record_t svc_rec;
+	ib_api_status_t status;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Trying to Delete service name: %s\n", sr_name);
+
+	memset(&svc_rec, 0, sizeof(svc_rec));
+
+	status = osmt_get_service_by_name(p_osmt, sr_name, rec_num, &svc_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A15: "
+			"Failed to get service: name: %s\n", sr_name);
+		goto ExitNoDel;
+	}
+
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+	memset(&user, 0, sizeof(user));
+
+	/* set the new service record fields */
+	memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+	memcpy(svc_rec.service_name, sr_name,
+	       (strlen(sr_name) + 1) * sizeof(char));
+
+	/* prepare the data used for this query */
+	context.p_osmt = p_osmt;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.query_context = &context;
+	req.query_type = OSMV_QUERY_USER_DEFINED;	/*  basically a don't care here */
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.sm_key = 0;
+
+	user.method = IB_MAD_METHOD_DELETE;
+	user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+	user.comp_mask = IB_SR_COMPMASK_SNAME;
+	user.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, "ERR 4A16: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+	if (IsServiceExist) {
+		/* If IsServiceExist = 1 then we should succeed here */
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A17: "
+				"ib_query failed (%s)\n",
+				ib_get_err_str(status));
+
+			if (status == IB_REMOTE_ERROR) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+					"ERR 4A18: Remote error = %s\n",
+					ib_get_mad_status_str
+					(osm_madw_get_mad_ptr
+					 (context.result.p_result_madw)));
+			}
+		}
+	} else {
+		/* If IsServiceExist = 0 then we should fail here */
+		if (status == IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A19: "
+				"Succeeded to delete service: %s which "
+				"shouldn't exist", sr_name);
+			status = IB_ERROR;
+		} else {
+			/* The deletion should have failed, since the service_name
+			   shouldn't exist. */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"IS EXPECTED ERROR ^^^^\n");
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"Failed to delete service_name: %s\n", sr_name);
+			status = IB_SUCCESS;
+		}
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+ExitNoDel:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+/*
+ * Run a complete service records flow:
+ * - register a service
+ * - register a service (with a lease period)
+ * - get a service by name
+ * - get all services / must be 2
+ * - delete a service
+ * - get all services / must be 1
+ * - wait for the lease to expire
+ * - get all services / must be 0
+ * - get / set service by data
+ */
+ib_api_status_t osmt_run_service_records_flow(IN osmtest_t * const p_osmt)
+{
+	ib_service_record_t srv_rec;
+	ib_api_status_t status;
+	uint8_t instance, i;
+	uint8_t service_data8[16], service_key[16];
+	ib_net16_t service_data16[8];
+	ib_net32_t service_data32[4];
+	ib_net64_t service_data64[2];
+	uint64_t pid = getpid();
+	uint64_t id[7];
+	/* We use up to seven service names - we use the extra for bad flow */
+	ib_svc_name_t service_name[7];
+#ifdef VENDOR_RMPP_SUPPORT
+	/* This array contain only the valid names after registering vs SM */
+	ib_svc_name_t service_valid_names[3];
+	uint32_t num_recs = 0;
+#endif
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/* Init Service names */
+	for (i = 0; i < 7; i++) {
+#ifdef __WIN__
+		uint64_t rand_val = rand() - (uint64_t) i;
+#else
+		uint64_t rand_val = random() - (uint64_t) i;
+#endif
+		id[i] = abs((int)(pid - rand_val));
+		/* Just to be unique any place on any host */
+		sprintf((char *)(service_name[i]),
+			"osmt.srvc.%" PRIu64 ".%" PRIu64, rand_val, pid);
+		/*printf("-I- Service Name is : %s, ID is : 0x%" PRIx64 "\n",service_name[i],id[i]); */
+	}
+
+	status = osmt_register_service(p_osmt, cl_ntoh64(id[0]),	/*  IN ib_net64_t      service_id, */
+				       IB_DEFAULT_PKEY,	/*  IN ib_net16_t      service_pkey, */
+				       0xFFFFFFFF,	/*  IN ib_net32_t      service_lease, */
+				       11,	/*  IN uint8_t         service_key_lsb, */
+				       (char *)service_name[0]	/*  IN char            *service_name */
+	    );
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	status = osmt_register_service(p_osmt, cl_ntoh64(id[1]),	/*  IN ib_net64_t      service_id, */
+				       IB_DEFAULT_PKEY,	/*  IN ib_net16_t      service_pkey, */
+				       cl_hton32(0x00000004),	/*  IN ib_net32_t     service_lease, */
+				       11,	/*  IN uint8_t         service_key_lsb, */
+				       (char *)service_name[1]	/*  IN char            *service_name */
+	    );
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	status = osmt_register_service(p_osmt, cl_ntoh64(id[2]),	/*  IN ib_net64_t      service_id, */
+				       0,	/*  IN ib_net16_t      service_pkey, */
+				       0xFFFFFFFF,	/*  IN ib_net32_t      service_lease, */
+				       11,	/* Remove Service Record IN uint8_t service_key_lsb, */
+				       (char *)service_name[2]	/*  IN char            *service_name */
+	    );
+
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/*  Generate 2 instances of service record with consecutive data */
+	for (instance = 0; instance < 2; instance++) {
+		/*  First, clear all arrays */
+		memset(service_data8, 0, 16 * sizeof(uint8_t));
+		memset(service_data16, 0, 8 * sizeof(uint16_t));
+		memset(service_data32, 0, 4 * sizeof(uint32_t));
+		memset(service_data64, 0, 2 * sizeof(uint64_t));
+		service_data8[instance] = instance + 1;
+		service_data16[instance] = cl_hton16(instance + 2);
+		service_data32[instance] = cl_hton32(instance + 3);
+		service_data64[instance] = cl_hton64(instance + 4);
+		status = osmt_register_service_with_data(p_osmt, cl_ntoh64(id[3]),	/*  IN ib_net64_t      service_id, */
+							 IB_DEFAULT_PKEY,	/*  IN ib_net16_t      service_pkey, */
+							 cl_ntoh32(10),	/*  IN ib_net32_t      service_lease, */
+							 12,	/*  IN uint8_t         service_key_lsb, */
+							 service_data8, service_data16, service_data32, service_data64,	/* service data structures */
+							 (char *)service_name[3]	/*  IN char            *service_name */
+		    );
+
+		if (status != IB_SUCCESS) {
+			goto Exit;
+		}
+
+	}
+
+	/*  Trying to create service with zero key */
+	memset(service_key, 0, 16 * sizeof(uint8_t));
+	status = osmt_register_service_with_full_key(p_osmt, cl_ntoh64(id[5]),	/*  IN ib_net64_t      service_id, */
+						     0,	/*  IN ib_net16_t      service_pkey, */
+						     0xFFFFFFFF,	/*  IN ib_net32_t      service_lease, */
+						     service_key,	/*  full service_key, */
+						     (char *)service_name[5]	/*  IN char            *service_name */
+	    );
+
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/*  Now update it with Unique key and different service name */
+	for (i = 0; i <= 15; i++) {
+		service_key[i] = i + 1;
+	}
+	status = osmt_register_service_with_full_key(p_osmt, cl_ntoh64(id[5]),	/*  IN ib_net64_t      service_id, */
+						     0,	/*  IN ib_net16_t      service_pkey, */
+						     0xFFFFFFFF,	/*  IN ib_net32_t      service_lease, */
+						     service_key,	/* full service_key, */
+						     (char *)service_name[6]	/*  IN char            *service_name */
+	    );
+	if (status != IB_SUCCESS) {
+		goto Exit;
+	}
+
+	/* Let OpenSM handle it */
+	usleep(100);
+
+	/* Make sure service_name[0] exists */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[0], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1A: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[0]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure service_name[1] exists */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[1], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1B: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[1]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure service_name[2] exists */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[2], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1C: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[2]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure service_name[3] exists. */
+	/* After 10 seconds the service should not exist: service_lease = 10 */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[3], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1D: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[3]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	sleep(10);
+
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[3], 0, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1E: "
+			"Found service: name: %s that should have been "
+			"deleted due to service lease expiring\n",
+			(char *)service_name[3]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Check that for service: id[5] only one record exists */
+	status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]), &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1F: "
+			"Found number of records != 1 for "
+			"service: id: 0x%016" PRIx64 "\n", id[5]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Bad Flow of Get with invalid Service ID: id[6] */
+	status = osmt_get_service_by_id(p_osmt, 0, cl_ntoh64(id[6]), &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A20: "
+			"Found service: id: 0x%016" PRIx64 " "
+			"that is invalid\n", id[6]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Check by both id and service name: id[0], service_name[0] */
+	status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[0]),
+						 (char *)service_name[0],
+						 &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A21: "
+			"Fail to find service: id: 0x%016" PRIx64 " "
+			"name: %s\n", id[0], (char *)service_name[0]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Check by both id and service name: id[5], service_name[6] */
+	status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[5]),
+						 (char *)service_name[6],
+						 &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A22: "
+			"Fail to find service: id: 0x%016" PRIx64 " "
+			"name: %s\n", id[5], (char *)service_name[6]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Bad Flow of Get with invalid name(service_name[3]) and valid ID(id[0]) */
+	status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[0]),
+						 (char *)service_name[3],
+						 &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A23: "
+			"Found service: id: 0x%016" PRIx64
+			"name: %s which is an invalid service\n",
+			id[0], (char *)service_name[3]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Bad Flow of Get with unmatched name(service_name[5]) and id(id[3]) (both valid) */
+	status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[3]),
+						 (char *)service_name[5],
+						 &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A24: "
+			"Found service: id: 0x%016" PRIx64
+			"name: %s which is an invalid service\n",
+			id[3], (char *)service_name[5]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Bad Flow of Get with service name that doesn't exist (service_name[4]) */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[4], 0, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A25: "
+			"Found service: name: %s that shouldn't exist\n",
+			(char *)service_name[4]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Bad Flow : Check that getting service_name[5] brings no records since another service
+	   has been updated with the same ID (service_name[6] */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[5], 0, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A26: "
+			"Found service: name: %s which is an "
+			"invalid service\n", (char *)service_name[5]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Check that getting service_name[6] by name ONLY is valid,
+	   since we do not support key&name association, also trusted queries */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[6], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A27: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[6]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Test Service Key */
+	memset(service_key, 0, 16 * sizeof(uint8_t));
+
+	/* Check for service_name[5] with service_key=0 - the service shouldn't
+	   exist with this name. */
+	status = osmt_get_service_by_name_and_key(p_osmt,
+						  (char *)service_name[5],
+						  0, service_key, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A28: "
+			"Found service: name: %s key:0 which is an "
+			"invalid service (wrong name)\n",
+			(char *)service_name[5]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Check for service_name[6] with service_key=0 - the service should
+	   exist with different key. */
+	status = osmt_get_service_by_name_and_key(p_osmt,
+						  (char *)service_name[6],
+						  0, service_key, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A29: "
+			"Found service: name: %s key: 0 which is an "
+			"invalid service (wrong service_key)\n",
+			(char *)service_name[6]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* check for service_name[6] with the correct service_key */
+	for (i = 0; i <= 15; i++)
+		service_key[i] = i + 1;
+	status = osmt_get_service_by_name_and_key(p_osmt,
+						  (char *)service_name[6],
+						  1, service_key, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2A: "
+			"Fail to find service: name: %s with "
+			"correct service key\n", (char *)service_name[6]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+#ifdef VENDOR_RMPP_SUPPORT
+	/* These ar the only service_names which are valid */
+	memcpy(&service_valid_names[0], &service_name[0], sizeof(uint8_t) * 64);
+	memcpy(&service_valid_names[1], &service_name[2], sizeof(uint8_t) * 64);
+	memcpy(&service_valid_names[2], &service_name[6], sizeof(uint8_t) * 64);
+
+	status =
+	    osmt_get_all_services_and_check_names(p_osmt, service_valid_names,
+						  3, &num_recs);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2B: "
+			"Fail to find all services that should exist\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+#endif
+
+	/* Delete service_name[0] */
+	status = osmt_delete_service_by_name(p_osmt, 1,
+					     (char *)service_name[0], 1);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2C: "
+			"Fail to delete service: name: %s\n",
+			(char *)service_name[0]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure deletion of service_name[0] succeeded */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[0], 0, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2D: "
+			"Found service: name: %s that was deleted\n",
+			(char *)service_name[0]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure service_name[1] doesn't exist (expired service lease) */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[1], 0, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2E: "
+			"Found service: name: %s that should have expired\n",
+			(char *)service_name[1]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Make sure service_name[2] exists */
+	status = osmt_get_service_by_name(p_osmt,
+					  (char *)service_name[2], 1, &srv_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2F: "
+			"Fail to find service: name: %s\n",
+			(char *)service_name[2]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*  Bad Flow - try to delete non-existent service_name[5] */
+	status = osmt_delete_service_by_name(p_osmt, 0,
+					     (char *)service_name[5], 0);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A30: "
+			"Succeed to delete non-existent service: name: %s\n",
+			(char *)service_name[5]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Delete service_name[2] */
+	status = osmt_delete_service_by_name(p_osmt, 1,
+					     (char *)service_name[2], 1);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A31: "
+			"Fail to delete service: name: %s\n",
+			(char *)service_name[2]);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* Delete service_name[6] */
+	status = osmt_delete_service_by_name(p_osmt, 1,
+					     (char *)service_name[6], 1);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A32: "
+			"Failed to delete service name: %s\n",
+			(char *)service_name[6]);
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return status;
+}
diff --git a/osmtest/osmt_slvl_vl_arb.c b/osmtest/osmt_slvl_vl_arb.c
new file mode 100644
index 0000000..82a6f39
--- /dev/null
+++ b/osmtest/osmt_slvl_vl_arb.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * Abstract:
+ *    Implementation of SLtoVL and VL Arbitration testing flow..
+ *    Top level is osmt_run_slvl_and_vlarb_records_flow:
+ *     osmt_query_all_ports_vl_arb
+ *     osmt_query_all_ports_slvl_map
+ *
+ */
+
+#ifndef __WIN__
+#include <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);
+
+	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);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n",
+		cl_ntoh16(lid), port_num);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	record.lid = lid;
+	record.port_num = port_num;
+	record.block_num = block_num;
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0405: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0466: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/* ok it worked */
+	p_rec = osmv_get_query_result(context.result.p_result_madw, 0);
+	if (fh) {
+		osmtest_write_vl_arb_table(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+static ib_api_status_t
+osmt_query_all_ports_vl_arb(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	cl_status_t status = CL_SUCCESS;
+	cl_qmap_t *p_tbl;
+	port_t *p_src_port;
+	uint8_t block, anyErr = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Obtaining ALL Ports VL Arbitration Tables\n");
+
+	/*
+	 * Go over all ports that exist in the subnet
+	 * get the relevant VLarbs
+	 */
+
+	p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+	p_src_port = (port_t *) cl_qmap_head(p_tbl);
+
+	while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) {
+
+		/* HACK we use capability_mask to know diff a CA port from switch port */
+		if (p_src_port->rec.port_info.capability_mask) {
+			/* this is an hca port */
+			for (block = 1; block <= 4; block++) {
+				/*  NOTE to comply we must set port number to 0 and the SA should figure it out */
+				/*  since it is a CA port */
+				status =
+				    osmt_query_vl_arb(p_osmt,
+						      p_src_port->rec.lid, 0,
+						      block, fh);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0467: "
+						"Failed to get Lid:0x%X Port:0x%X (%s)\n",
+						cl_ntoh16(p_src_port->rec.lid),
+						0, ib_get_err_str(status));
+					anyErr = 1;
+				}
+			}
+		} else {
+			/* this is a switch port */
+			for (block = 1; block <= 4; block++) {
+				status =
+				    osmt_query_vl_arb(p_osmt,
+						      p_src_port->rec.lid,
+						      p_src_port->rec.port_num,
+						      block, fh);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0468: "
+						"Failed to get Lid:0x%X Port:0x%X (%s)\n",
+						cl_ntoh16(p_src_port->rec.lid),
+						p_src_port->rec.port_num,
+						ib_get_err_str(status));
+					anyErr = 1;
+				}
+			}
+		}
+
+		p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item);
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	if (anyErr) {
+		status = IB_ERROR;
+	}
+	return (status);
+}
+
+/*******************************************************************************
+ SLtoVL
+*******************************************************************************/
+static ib_api_status_t
+osmtest_write_slvl_map_table(IN osmtest_t * const p_osmt,
+			     IN FILE * fh,
+			     IN const ib_slvl_table_record_t * const p_rec)
+{
+	int result, i;
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	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);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n",
+		cl_ntoh16(lid), out_port_num, in_port_num);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	record.lid = lid;
+	record.in_port_num = in_port_num;
+	record.out_port_num = out_port_num;
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0469: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0470: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/* ok it worked */
+	p_rec = osmv_get_query_result(context.result.p_result_madw, 0);
+	if (fh) {
+		osmtest_write_slvl_map_table(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+static ib_api_status_t
+osmt_query_all_ports_slvl_map(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	cl_status_t status = CL_SUCCESS;
+	cl_qmap_t *p_tbl;
+	port_t *p_src_port;
+	uint8_t in_port, anyErr = 0, num_ports;
+	node_t *p_node;
+	const cl_qmap_t *p_node_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Go over all ports that exist in the subnet
+	 * get the relevant SLtoVLs
+	 */
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Obtaining ALL Ports (to other ports) SLtoVL Maps\n");
+
+	p_tbl = &p_osmt->exp_subn.port_key_tbl;
+	p_node_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+	p_src_port = (port_t *) cl_qmap_head(p_tbl);
+
+	while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) {
+
+		/* HACK we use capability_mask to know diff a CA port from switch port */
+		if (p_src_port->rec.port_info.capability_mask) {
+			/* this is an hca port */
+			/*  NOTE to comply we must set port number to 0 and the SA should figure it out */
+			/*  since it is a CA port */
+			status =
+			    osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0,
+						0, fh);
+			if (status != IB_SUCCESS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0471: "
+					"Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s)\n",
+					cl_ntoh16(p_src_port->rec.lid), 0, 0,
+					ib_get_err_str(status));
+				anyErr = 1;
+			}
+		} else {
+			/* this is a switch port */
+			/* get the node */
+			p_node =
+			    (node_t *) cl_qmap_get(p_node_tbl,
+						   p_src_port->rec.lid);
+			if (p_node == (node_t *) cl_qmap_end(p_node_tbl)) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0472: "
+					"Failed to get Node by Lid:0x%X\n",
+					p_src_port->rec.lid);
+				goto Exit;
+			}
+
+			num_ports = p_node->rec.node_info.num_ports;
+
+			for (in_port = 1; in_port <= num_ports; in_port++) {
+				status =
+				    osmt_query_slvl_map(p_osmt,
+							p_src_port->rec.lid,
+							p_src_port->rec.
+							port_num, in_port, fh);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0473: "
+						"Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s)\n",
+						cl_ntoh16(p_src_port->rec.lid),
+						p_src_port->rec.port_num,
+						in_port,
+						ib_get_err_str(status));
+					anyErr = 1;
+				}
+			}
+		}
+
+		p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item);
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	if (anyErr) {
+		status = IB_ERROR;
+	}
+	return (status);
+}
+
+/*
+ * Run a vl arbitration queries and sl2vl maps queries flow:
+ * Good flow:
+ * - for each physical port on the network - obtain the VL Arb
+ * - for each CA physical port obtain its SLtoVL Map
+ * - for each SW physical port (out) obtain the SLtoVL Map to each other port
+ * BAD flow:
+ * - Try get with multiple results
+ * - Try gettable
+ * - Try providing non existing port
+ */
+ib_api_status_t
+osmt_run_slvl_and_vlarb_records_flow(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status;
+	FILE *fh;
+	ib_net16_t test_lid;
+	uint8_t lmc;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	fh = fopen("qos.txt", "w");
+
+	/* 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;
+}
diff --git a/osmtest/osmtest.c b/osmtest/osmtest.c
new file mode 100644
index 0000000..243d0b2
--- /dev/null
+++ b/osmtest/osmtest.c
@@ -0,0 +1,7403 @@
+/*
+ * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */
+
+/*
+ * Abstract:
+ *    Implementation of osmtest_t.
+ *    This object represents the OSMTest Test object.
+ *
+ */
+
+#ifdef __WIN__
+#pragma warning(disable : 4996)
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __WIN__
+#include <complib/cl_timer.h>
+#else
+#include <strings.h>
+#include <sys/time.h>
+#endif
+#include <complib/cl_debug.h>
+#include "osmtest.h"
+
+#ifndef __WIN__
+#define strnicmp strncasecmp
+#endif
+
+#define POOL_MIN_ITEMS  64
+#define GUID_ARRAY_SIZE 64
+
+typedef struct _osmtest_sm_info_rec {
+	ib_net64_t sm_guid;
+	ib_net16_t lid;
+	uint8_t priority;
+	uint8_t sm_state;
+} osmtest_sm_info_rec_t;
+
+typedef struct _osmtest_inform_info {
+	boolean_t subscribe;
+	ib_net32_t qpn;
+	ib_net16_t trap;
+} osmtest_inform_info_t;
+
+typedef struct _osmtest_inform_info_rec {
+	ib_gid_t subscriber_gid;
+	ib_net16_t subscriber_enum;
+} osmtest_inform_info_rec_t;
+
+typedef enum _osmtest_token_val {
+	OSMTEST_TOKEN_COMMENT = 0,
+	OSMTEST_TOKEN_END,
+	OSMTEST_TOKEN_DEFINE_NODE,
+	OSMTEST_TOKEN_DEFINE_PORT,
+	OSMTEST_TOKEN_DEFINE_PATH,
+	OSMTEST_TOKEN_DEFINE_LINK,
+	OSMTEST_TOKEN_LID,
+	OSMTEST_TOKEN_BASE_VERSION,
+	OSMTEST_TOKEN_CLASS_VERSION,
+	OSMTEST_TOKEN_NODE_TYPE,
+	OSMTEST_TOKEN_NUM_PORTS,
+	OSMTEST_TOKEN_SYS_GUID,
+	OSMTEST_TOKEN_NODE_GUID,
+	OSMTEST_TOKEN_PORT_GUID,
+	OSMTEST_TOKEN_PARTITION_CAP,
+	OSMTEST_TOKEN_DEVICE_ID,
+	OSMTEST_TOKEN_REVISION,
+	OSMTEST_TOKEN_PORT_NUM,
+	OSMTEST_TOKEN_VENDOR_ID,
+	OSMTEST_TOKEN_DGID,
+	OSMTEST_TOKEN_SGID,
+	OSMTEST_TOKEN_DLID,
+	OSMTEST_TOKEN_SLID,
+	OSMTEST_TOKEN_HOP_FLOW_RAW,
+	OSMTEST_TOKEN_TCLASS,
+	OSMTEST_TOKEN_NUM_PATH,
+	OSMTEST_TOKEN_PKEY,
+	OSMTEST_TOKEN_SL,
+	OSMTEST_TOKEN_RATE,
+	OSMTEST_TOKEN_PKT_LIFE,
+	OSMTEST_TOKEN_PREFERENCE,
+	OSMTEST_TOKEN_MKEY,
+	OSMTEST_TOKEN_SUBN_PREF,
+	OSMTEST_TOKEN_BASE_LID,
+	OSMTEST_TOKEN_SM_BASE_LID,
+	OSMTEST_TOKEN_CAP_MASK,
+	OSMTEST_TOKEN_DIAG_CODE,
+	OSMTEST_TOKEN_MKEY_LEASE_PER,
+	OSMTEST_TOKEN_LOC_PORT_NUM,
+	OSMTEST_TOKEN_LINK_WID_EN,
+	OSMTEST_TOKEN_LINK_WID_SUP,
+	OSMTEST_TOKEN_LINK_WID_ACT,
+	OSMTEST_TOKEN_LINK_SPEED_SUP,
+	OSMTEST_TOKEN_PORT_STATE,
+	OSMTEST_TOKEN_STATE_INFO2,
+	OSMTEST_TOKEN_MKEY_PROT_BITS,
+	OSMTEST_TOKEN_LMC,
+	OSMTEST_TOKEN_LINK_SPEED,
+	OSMTEST_TOKEN_MTU_SMSL,
+	OSMTEST_TOKEN_VL_CAP,
+	OSMTEST_TOKEN_VL_HIGH_LIMIT,
+	OSMTEST_TOKEN_VL_ARB_HIGH_CAP,
+	OSMTEST_TOKEN_VL_ARB_LOW_CAP,
+	OSMTEST_TOKEN_MTU_CAP,
+	OSMTEST_TOKEN_VL_STALL_LIFE,
+	OSMTEST_TOKEN_VL_ENFORCE,
+	OSMTEST_TOKEN_MKEY_VIOL,
+	OSMTEST_TOKEN_PKEY_VIOL,
+	OSMTEST_TOKEN_QKEY_VIOL,
+	OSMTEST_TOKEN_GUID_CAP,
+	OSMTEST_TOKEN_SUBN_TIMEOUT,
+	OSMTEST_TOKEN_RESP_TIME_VAL,
+	OSMTEST_TOKEN_ERR_THRESHOLD,
+	OSMTEST_TOKEN_MTU,
+	OSMTEST_TOKEN_FROMLID,
+	OSMTEST_TOKEN_FROMPORTNUM,
+	OSMTEST_TOKEN_TOPORTNUM,
+	OSMTEST_TOKEN_TOLID,
+	OSMTEST_TOKEN_UNKNOWN
+} osmtest_token_val_t;
+
+typedef struct _osmtest_token {
+	osmtest_token_val_t val;
+	size_t str_size;
+	const char *str;
+} osmtest_token_t;
+
+const osmtest_token_t token_array[] = {
+	{OSMTEST_TOKEN_COMMENT, 1, "#"},
+	{OSMTEST_TOKEN_END, 3, "END"},
+	{OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"},
+	{OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"},
+	{OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"},
+	{OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"},
+	{OSMTEST_TOKEN_LID, 3, "LID"},
+	{OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"},
+	{OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"},
+	{OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"},
+	{OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"},
+	{OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"},
+	{OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"},
+	{OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"},
+	{OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"},
+	{OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"},
+	{OSMTEST_TOKEN_REVISION, 8, "REVISION"},
+	{OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"},
+	{OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"},
+	{OSMTEST_TOKEN_DGID, 4, "DGID"},
+	{OSMTEST_TOKEN_SGID, 4, "SGID"},
+	{OSMTEST_TOKEN_DLID, 4, "DLID"},
+	{OSMTEST_TOKEN_SLID, 4, "SLID"},
+	{OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"},
+	{OSMTEST_TOKEN_TCLASS, 6, "TCLASS"},
+	{OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"},
+	{OSMTEST_TOKEN_PKEY, 4, "PKEY"},
+	{OSMTEST_TOKEN_SL, 2, "SL"},
+	{OSMTEST_TOKEN_RATE, 4, "RATE"},
+	{OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"},
+	{OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"},
+	{OSMTEST_TOKEN_MKEY, 4, "M_KEY"},
+	{OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"},
+	{OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"},
+	{OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"},
+	{OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"},
+	{OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"},
+	{OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"},
+	{OSMTEST_TOKEN_LOC_PORT_NUM, 14, "local_port_num"},
+	{OSMTEST_TOKEN_LINK_WID_EN, 18, "link_width_enabled"},
+	{OSMTEST_TOKEN_LINK_WID_SUP, 20, "link_width_supported"},
+	{OSMTEST_TOKEN_LINK_WID_ACT, 17, "link_width_active"},
+	{OSMTEST_TOKEN_LINK_SPEED_SUP, 20, "link_speed_supported"},
+	{OSMTEST_TOKEN_PORT_STATE, 10, "port_state"},
+	{OSMTEST_TOKEN_STATE_INFO2, 10, "state_info2"},
+	{OSMTEST_TOKEN_MKEY_PROT_BITS, 3, "mpb"},
+	{OSMTEST_TOKEN_LMC, 3, "lmc"},
+	{OSMTEST_TOKEN_LINK_SPEED, 10, "link_speed"},
+	{OSMTEST_TOKEN_MTU_SMSL, 8, "mtu_smsl"},
+	{OSMTEST_TOKEN_VL_CAP, 6, "vl_cap"},
+	{OSMTEST_TOKEN_VL_HIGH_LIMIT, 13, "vl_high_limit"},
+	{OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"},
+	{OSMTEST_TOKEN_VL_ARB_LOW_CAP, 14, "vl_arb_low_cap"},
+	{OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"},
+	{OSMTEST_TOKEN_VL_STALL_LIFE, 13, "vl_stall_life"},
+	{OSMTEST_TOKEN_VL_ENFORCE, 10, "vl_enforce"},
+	{OSMTEST_TOKEN_MKEY_VIOL, 16, "m_key_violations"},
+	{OSMTEST_TOKEN_PKEY_VIOL, 16, "p_key_violations"},
+	{OSMTEST_TOKEN_QKEY_VIOL, 16, "q_key_violations"},
+	{OSMTEST_TOKEN_GUID_CAP, 8, "guid_cap"},
+	{OSMTEST_TOKEN_SUBN_TIMEOUT, 14, "subnet_timeout"},
+	{OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"},
+	{OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"},
+	{OSMTEST_TOKEN_MTU, 3, "MTU"},	/*  must be after the other mtu... tokens. */
+	{OSMTEST_TOKEN_FROMLID, 8, "from_lid"},
+	{OSMTEST_TOKEN_FROMPORTNUM, 13, "from_port_num"},
+	{OSMTEST_TOKEN_TOPORTNUM, 11, "to_port_num"},
+	{OSMTEST_TOKEN_TOLID, 6, "to_lid"},
+	{OSMTEST_TOKEN_UNKNOWN, 0, ""}	/* must be last entry */
+};
+
+#define IB_MAD_STATUS_CLASS_MASK       (CL_HTON16(0xFF00))
+
+static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY";
+static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT";
+static const char ib_mad_status_str_unsup_class_ver[] =
+    "IB_MAD_STATUS_UNSUP_CLASS_VER";
+static const char ib_mad_status_str_unsup_method[] =
+    "IB_MAD_STATUS_UNSUP_METHOD";
+static const char ib_mad_status_str_unsup_method_attr[] =
+    "IB_MAD_STATUS_UNSUP_METHOD_ATTR";
+static const char ib_mad_status_str_invalid_field[] =
+    "IB_MAD_STATUS_INVALID_FIELD";
+static const char ib_mad_status_str_no_resources[] =
+    "IB_SA_MAD_STATUS_NO_RESOURCES";
+static const char ib_mad_status_str_req_invalid[] =
+    "IB_SA_MAD_STATUS_REQ_INVALID";
+static const char ib_mad_status_str_no_records[] =
+    "IB_SA_MAD_STATUS_NO_RECORDS";
+static const char ib_mad_status_str_too_many_records[] =
+    "IB_SA_MAD_STATUS_TOO_MANY_RECORDS";
+static const char ib_mad_status_str_invalid_gid[] =
+    "IB_SA_MAD_STATUS_INVALID_GID";
+static const char ib_mad_status_str_insuf_comps[] =
+    "IB_SA_MAD_STATUS_INSUF_COMPS";
+static const char generic_or_str[] = " | ";
+
+/**********************************************************************
+ **********************************************************************/
+const char *ib_get_mad_status_str(IN const ib_mad_t * const p_mad)
+{
+	static char line[512];
+	uint32_t offset = 0;
+	ib_net16_t status;
+	boolean_t first = TRUE;
+
+	line[offset] = '\0';
+
+	status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+
+	if (status == 0) {
+		strcat(&line[offset], "IB_SUCCESS");
+		return (line);
+	}
+
+	if (status & IB_MAD_STATUS_BUSY) {
+		strcat(&line[offset], ib_mad_status_str_busy);
+		offset += sizeof(ib_mad_status_str_busy);
+	}
+	if (status & IB_MAD_STATUS_REDIRECT) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_redirect);
+		offset += sizeof(ib_mad_status_str_redirect) - 1;
+	}
+	if ((status & IB_MAD_STATUS_INVALID_FIELD) ==
+	    IB_MAD_STATUS_UNSUP_CLASS_VER) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_unsup_class_ver);
+		offset += sizeof(ib_mad_status_str_unsup_class_ver) - 1;
+	}
+	if ((status & IB_MAD_STATUS_INVALID_FIELD) ==
+	    IB_MAD_STATUS_UNSUP_METHOD) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_unsup_method);
+		offset += sizeof(ib_mad_status_str_unsup_method) - 1;
+	}
+	if ((status & IB_MAD_STATUS_INVALID_FIELD) ==
+	    IB_MAD_STATUS_UNSUP_METHOD_ATTR) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_unsup_method_attr);
+		offset += sizeof(ib_mad_status_str_unsup_method_attr) - 1;
+	}
+	if ((status & IB_MAD_STATUS_INVALID_FIELD) ==
+	    IB_MAD_STATUS_INVALID_FIELD) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_invalid_field);
+		offset += sizeof(ib_mad_status_str_invalid_field) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) ==
+	    IB_SA_MAD_STATUS_NO_RESOURCES) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_no_resources);
+		offset += sizeof(ib_mad_status_str_no_resources) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_REQ_INVALID) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_req_invalid);
+		offset += sizeof(ib_mad_status_str_req_invalid) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_NO_RECORDS) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_no_records);
+		offset += sizeof(ib_mad_status_str_no_records) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) ==
+	    IB_SA_MAD_STATUS_TOO_MANY_RECORDS) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_too_many_records);
+		offset += sizeof(ib_mad_status_str_too_many_records) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_INVALID_GID) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_invalid_gid);
+		offset += sizeof(ib_mad_status_str_invalid_gid) - 1;
+	}
+	if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_INSUF_COMPS) {
+		if (!first) {
+			strcat(&line[offset], generic_or_str);
+			offset += sizeof(generic_or_str) - 1;
+		}
+		first = FALSE;
+		strcat(&line[offset], ib_mad_status_str_insuf_comps);
+		offset += sizeof(ib_mad_status_str_insuf_comps) - 1;
+	}
+
+	return (line);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void subnet_construct(IN subnet_t * const p_subn)
+{
+	cl_qmap_init(&p_subn->link_tbl);
+	cl_qmap_init(&p_subn->node_lid_tbl);
+	cl_qmap_init(&p_subn->node_guid_tbl);
+	cl_qmap_init(&p_subn->mgrp_mlid_tbl);
+
+	/* NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */
+	/* cl_qmap_init( &p_subn->port_lid_tbl ); */
+	/* cl_qmap_init( &p_subn->port_guid_tbl ); */
+
+	/* port key is a lid and num pair */
+	cl_qmap_init(&p_subn->port_key_tbl);
+	cl_qmap_init(&p_subn->path_tbl);
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t subnet_init(IN subnet_t * const p_subn)
+{
+	cl_status_t status = IB_SUCCESS;
+
+	subnet_construct(p_subn);
+
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osmtest_construct(IN osmtest_t * const p_osmt)
+{
+	memset(p_osmt, 0, sizeof(*p_osmt));
+	osm_log_construct(&p_osmt->log);
+	subnet_construct(&p_osmt->exp_subn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osmtest_destroy(IN osmtest_t * const p_osmt)
+{
+	cl_map_item_t *p_item, *p_next_item;
+
+	/* Currently there is a problem with IBAL exit flow - memory overrun,
+	   so bypass vendor deletion - it will be cleaned by the Windows OS */
+#ifndef __WIN__
+	if (p_osmt->p_vendor)
+		osm_vendor_delete(&p_osmt->p_vendor);
+#endif
+
+	cl_qpool_destroy(&p_osmt->port_pool);
+	cl_qpool_destroy(&p_osmt->node_pool);
+
+	/* destroy the qmap tables */
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.link_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.link_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.mgrp_mlid_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.mgrp_mlid_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.node_guid_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.node_guid_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.node_lid_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.node_lid_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.path_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.path_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+	p_next_item = cl_qmap_head(&p_osmt->exp_subn.port_key_tbl);
+	while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.port_key_tbl)) {
+		p_item = p_next_item;
+		p_next_item = cl_qmap_next(p_item);
+		free(p_item);
+	}
+
+	osm_log_destroy(&p_osmt->log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_init(IN osmtest_t * const p_osmt,
+	     IN const osmtest_opt_t * const p_opt,
+	     IN const osm_log_level_t log_flags)
+{
+	ib_api_status_t status;
+
+	/* Can't use log macros here, since we're initializing the log. */
+	osmtest_construct(p_osmt);
+
+	status = osm_log_init_v2(&p_osmt->log, p_opt->force_log_flush,
+				 0x0001, p_opt->log_file, 0, TRUE);
+	if (status != IB_SUCCESS)
+		return (status);
+
+	/* but we do not want any extra stuff here */
+	osm_log_set_level(&p_osmt->log, log_flags);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_FUNCS, "[\n");
+
+	p_osmt->opt = *p_opt;
+
+	status = cl_qpool_init(&p_osmt->node_pool, POOL_MIN_ITEMS, 0,
+			       POOL_MIN_ITEMS, sizeof(node_t), NULL, NULL,
+			       NULL);
+	CL_ASSERT(status == CL_SUCCESS);
+
+	status = cl_qpool_init(&p_osmt->port_pool, POOL_MIN_ITEMS, 0,
+			       POOL_MIN_ITEMS, sizeof(port_t), NULL, NULL,
+			       NULL);
+	CL_ASSERT(status == CL_SUCCESS);
+
+	p_osmt->p_vendor = osm_vendor_new(&p_osmt->log,
+					  p_opt->transaction_timeout);
+
+	if (p_osmt->p_vendor == NULL) {
+		status = IB_INSUFFICIENT_RESOURCES;
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0001: "
+			"Unable to allocate vendor object");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	osm_mad_pool_construct(&p_osmt->mad_pool);
+	status = osm_mad_pool_init(&p_osmt->mad_pool);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+Exit:
+	OSM_LOG(&p_osmt->log, OSM_LOG_FUNCS, "]\n");
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osmtest_query_res_cb(IN osmv_query_res_t * p_rec)
+{
+	osmtest_req_context_t *const p_ctxt =
+	    (osmtest_req_context_t *) p_rec->query_context;
+	osmtest_t *const p_osmt = p_ctxt->p_osmt;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_ctxt->result = *p_rec;
+
+	if (p_rec->status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0003: "
+			"Error on query (%s)\n", ib_get_err_str(p_rec->status));
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_all_recs(IN osmtest_t * const p_osmt,
+		     IN ib_net16_t const attr_id,
+		     IN size_t const attr_size,
+		     IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting all %s records\n",
+		ib_get_sa_attr_str(attr_id));
+
+	/*
+	 * Do a blocking query for all <attr_id> records in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+
+	p_context->p_osmt = p_osmt;
+	user.attr_id = attr_id;
+	user.attr_offset = cl_ntoh16((uint16_t) (attr_size >> 3));
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0004: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0064: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (p_context->result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osmtest_validate_sa_class_port_info(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_query_req_t req;
+	ib_class_port_info_t *p_cpi;
+	osmtest_req_context_t context;
+	osmtest_req_context_t *p_context = &context;
+	ib_sa_mad_t *p_resp_sa_madp;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting ClassPortInfo\n");
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+
+	p_context->p_osmt = p_osmt;
+	req.query_type = OSMV_QUERY_CLASS_PORT_INFO;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = 0;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0065: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0070: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (p_context->result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	/* ok we got it so please print it out */
+	p_resp_sa_madp =
+	    (ib_sa_mad_t *) osm_madw_get_mad_ptr(context.result.p_result_madw);
+	p_cpi =
+	    (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_madp);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"\n-----------------------------\n"
+		"SA Class Port Info:\n"
+		" base_ver:%u\n"
+		" class_ver:%u\n"
+		" cap_mask:0x%X\n"
+		" cap_mask2:0x%X\n"
+		" resp_time_val:0x%X\n"
+		"-----------------------------\n",
+		p_cpi->base_ver, p_cpi->class_ver, cl_ntoh16(p_cpi->cap_mask),
+		ib_class_cap_mask2(p_cpi), ib_class_resp_time_val(p_cpi));
+
+Exit:
+#if 0
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+#endif
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_node_rec(IN osmtest_t * const p_osmt,
+		     IN ib_net64_t const node_guid,
+		     IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_node_record_t record;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting node record for 0x%016" PRIx64 "\n",
+		cl_ntoh64(node_guid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.node_info.node_guid = node_guid;
+
+	p_context->p_osmt = p_osmt;
+	user.comp_mask = IB_NR_COMPMASK_NODEGUID;
+	user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0071: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0072: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (p_context->result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get a node record by node LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_node_rec_by_lid(IN osmtest_t * const p_osmt,
+			    IN ib_net16_t const lid,
+			    IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_node_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting node record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+
+	p_context->p_osmt = p_osmt;
+	user.comp_mask = IB_NR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0073: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0074: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_guid_pair(IN osmtest_t * const p_osmt,
+				  IN ib_net64_t sguid,
+				  IN ib_net64_t dguid,
+				  IN osmtest_req_context_t * p_context)
+{
+	cl_status_t status = IB_SUCCESS;
+	osmv_query_req_t req;
+	osmv_guid_pair_t guid_pair;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&req, 0, sizeof(req));
+	memset(p_context, 0, sizeof(*p_context));
+
+	p_context->p_osmt = p_osmt;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+
+	req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+
+	guid_pair.dest_guid = dguid;
+	guid_pair.src_guid = sguid;
+
+	req.p_query_input = &guid_pair;
+	req.sm_key = 0;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Query for path from 0x%" PRIx64 " to 0x%" PRIx64 "\n",
+		sguid, dguid);
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0063: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = (*p_context).result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0066: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      ((*p_context).result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_gid_pair(IN osmtest_t * const p_osmt,
+				 IN ib_gid_t sgid,
+				 IN ib_gid_t dgid,
+				 IN osmtest_req_context_t * p_context)
+{
+	cl_status_t status = IB_SUCCESS;
+	osmv_query_req_t req;
+	osmv_gid_pair_t gid_pair;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&req, 0, sizeof(req));
+	memset(p_context, 0, sizeof(*p_context));
+
+	p_context->p_osmt = p_osmt;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+
+	req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;
+
+	gid_pair.dest_gid = dgid;
+	gid_pair.src_gid = sgid;
+
+	req.p_query_input = &gid_pair;
+	req.sm_key = 0;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Query for path from 0x%016" PRIx64 " 0x%016" PRIx64
+		" to 0x%016" PRIx64 " 0x%016" PRIx64 "\n", sgid.unicast.prefix,
+		sgid.unicast.interface_id, dgid.unicast.prefix,
+		dgid.unicast.interface_id);
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006A: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = (*p_context).result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006B: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      ((*p_context).result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_multipath_rec(IN osmtest_t * const p_osmt,
+			  IN osmv_multipath_req_t * p_request,
+			  IN osmtest_req_context_t * p_context)
+{
+	cl_status_t status = IB_SUCCESS;
+	osmv_query_req_t req;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+
+	p_context->p_osmt = p_osmt;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+
+	req.query_type = OSMV_QUERY_MULTIPATH_REC;
+
+	req.p_query_input = p_request;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0068: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0069: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (p_context->result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_port_rec(IN osmtest_t * const p_osmt,
+		     IN ib_net16_t const lid,
+		     IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_portinfo_record_t record;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Getting PortInfoRecord for port with LID 0x%X\n",
+		cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+
+	p_context->p_osmt = p_osmt;
+	user.comp_mask = IB_PIR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0075: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0076: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (p_context->result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_port_rec_by_num(IN osmtest_t * const p_osmt,
+			    IN ib_net16_t const lid,
+			    IN uint8_t const port_num,
+			    IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_portinfo_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Getting PortInfoRecord for port with LID 0x%X Num:0x%X\n",
+		cl_ntoh16(lid), port_num);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	record.port_num = port_num;
+	user.p_attr = &record;
+
+	p_context->p_osmt = p_osmt;
+
+	req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0077: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0078: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_large(IN osmtest_t * const p_osmt,
+			       OUT uint32_t * const p_num_recs,
+			       OUT uint32_t * const p_num_queries)
+{
+	osmtest_req_context_t context;
+	ib_portinfo_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+	/*
+	 * Do a blocking query for all PortInfoRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0006: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Populate the database with the received records.
+	 */
+	num_recs = context.result.result_cnt;
+	*p_num_recs += num_recs;
+	++*p_num_queries;
+
+	if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Received %u records\n", num_recs);
+
+		for (i = 0; i < num_recs; i++) {
+			p_rec =
+			    osmv_get_query_portinfo_rec(context.result.
+							p_result_madw, i);
+			osm_dump_portinfo_record(&p_osmt->log, p_rec,
+						 OSM_LOG_VERBOSE);
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_node_recs_large(IN osmtest_t * const p_osmt,
+			       OUT uint32_t * const p_num_recs,
+			       OUT uint32_t * const p_num_queries)
+{
+	osmtest_req_context_t context;
+	ib_node_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0007: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Populate the database with the received records.
+	 */
+	num_recs = context.result.result_cnt;
+	*p_num_recs += num_recs;
+	++*p_num_queries;
+
+	if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Received %u records\n", num_recs);
+
+		for (i = 0; i < num_recs; i++) {
+			p_rec =
+			    osmv_get_query_node_rec(context.result.
+						    p_result_madw, i);
+			osm_dump_node_record(&p_osmt->log, p_rec,
+					     OSM_LOG_VERBOSE);
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_path_recs_large(IN osmtest_t * const p_osmt,
+			       OUT uint32_t * const p_num_recs,
+			       OUT uint32_t * const p_num_queries)
+{
+	osmtest_req_context_t context;
+	ib_path_rec_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all PathRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD,
+				      sizeof(*p_rec), &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0008: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Populate the database with the received records.
+	 */
+	num_recs = context.result.result_cnt;
+	*p_num_recs += num_recs;
+	++*p_num_queries;
+
+	if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Received %u records\n", num_recs);
+
+		for (i = 0; i < num_recs; i++) {
+			p_rec =
+			    osmv_get_query_path_rec(context.result.
+						    p_result_madw, i);
+			osm_dump_path_record(&p_osmt->log, p_rec,
+					     OSM_LOG_VERBOSE);
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_path_recs_by_guid(IN osmtest_t * const p_osmt,
+				 OUT uint32_t * const p_num_recs,
+				 OUT uint32_t * const p_num_queries)
+{
+	osmtest_req_context_t context;
+	ib_path_rec_t *p_rec;
+	uint32_t i;
+	cl_status_t status = IB_SUCCESS;
+	uint32_t num_recs = 0;
+	node_t *p_src_node, *p_dst_node;
+	cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+
+	p_tbl = &p_osmt->exp_subn.node_guid_tbl;
+
+	p_src_node = (node_t *) cl_qmap_head(p_tbl);
+
+	/*
+	 * Go over all nodes that exist in the subnet
+	 * for each pair that are not switch nodes get the path record
+	 */
+	while (p_src_node != (node_t *) cl_qmap_end(p_tbl)) {
+		p_dst_node = (node_t *) cl_qmap_head(p_tbl);
+
+		while (p_dst_node != (node_t *) cl_qmap_end(p_tbl)) {
+			/*
+			 * Do a blocking query for CA to CA Path Record
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+				"Source : guid = 0x%" PRIx64 " type = %d"
+				"Target : guid = 0x%" PRIx64 " type = %d\n",
+				cl_ntoh64(p_src_node->rec.node_info.port_guid),
+				p_src_node->rec.node_info.node_type,
+				cl_ntoh64(p_dst_node->rec.node_info.port_guid),
+				p_dst_node->rec.node_info.node_type);
+
+			if (p_src_node->rec.node_info.node_type ==
+			    IB_NODE_TYPE_CA
+			    && p_dst_node->rec.node_info.node_type ==
+			    IB_NODE_TYPE_CA) {
+				status =
+				    osmtest_get_path_rec_by_guid_pair(p_osmt,
+								      p_src_node->
+								      rec.
+								      node_info.
+								      port_guid,
+								      p_dst_node->
+								      rec.
+								      node_info.
+								      port_guid,
+								      &context);
+
+				/* In a case of TIMEOUT you still can try sending but cant count, maybe its a temporary issue */
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0009: "
+						"osmtest_get_path_rec_by_guid_pair failed (%s)\n",
+						ib_get_err_str(status));
+					if (status != IB_TIMEOUT)
+						goto Exit;
+				} else {
+					/* we might have received several records */
+					num_recs = context.result.result_cnt;
+					/*
+					 * Populate the database with the received records.
+					 */
+					*p_num_recs += num_recs;
+					++*p_num_queries;
+					OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+						"Received %u records\n", num_recs);
+					/* Dont waste time if not VERBOSE and above */
+					if (p_osmt->log.level & OSM_LOG_VERBOSE) {
+						for (i = 0; i < num_recs; i++) {
+							p_rec =
+							    osmv_get_query_path_rec
+							    (context.result.
+							     p_result_madw, i);
+							osm_dump_path_record
+							    (&p_osmt->log,
+							     p_rec,
+							     OSM_LOG_VERBOSE);
+						}
+					}
+				}
+				if (context.result.p_result_madw != NULL) {
+					osm_mad_pool_put(&p_osmt->mad_pool,
+							 context.result.
+							 p_result_madw);
+					context.result.p_result_madw = NULL;
+				}
+			}
+			/* next one please */
+			p_dst_node =
+			    (node_t *) cl_qmap_next(&p_dst_node->map_item);
+		}
+
+		p_src_node = (node_t *) cl_qmap_next(&p_src_node->map_item);
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_small(IN osmtest_t * const p_osmt,
+			       OUT uint32_t * const p_num_recs,
+			       OUT uint32_t * const p_num_queries)
+{
+	osmtest_req_context_t context;
+	ib_portinfo_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for our own PortInfoRecord in the subnet.
+	 */
+	status = osmtest_get_port_rec(p_osmt,
+				      cl_ntoh16(p_osmt->local_port.lid),
+				      &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0010: "
+			"osmtest_get_port_rec failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Populate the database with the received records.
+	 */
+	num_recs = context.result.result_cnt;
+	*p_num_recs += num_recs;
+	++*p_num_queries;
+
+	if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+			"Received %u records\n", num_recs);
+
+		for (i = 0; i < num_recs; i++) {
+			p_rec =
+			    osmv_get_query_portinfo_rec(context.result.
+							p_result_madw, i);
+			osm_dump_portinfo_record(&p_osmt->log, p_rec,
+						 OSM_LOG_VERBOSE);
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_local_port_lmc(IN osmtest_t * const p_osmt,
+			   IN ib_net16_t lid, OUT uint8_t * const p_lmc)
+{
+	osmtest_req_context_t context;
+	ib_portinfo_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	uint32_t num_recs = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for our own PortInfoRecord in the subnet.
+	 */
+	status = osmtest_get_port_rec(p_osmt, cl_ntoh16(lid), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 001A: "
+			"osmtest_get_port_rec failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_portinfo_rec(context.result.p_result_madw,
+						i);
+		osm_dump_portinfo_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE);
+		if (p_lmc) {
+			*p_lmc = ib_port_info_get_lmc(&p_rec->port_info);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "LMC %d\n", *p_lmc);
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Use a wrong SM_Key in a simple port query and report success if
+ * failed.
+ **********************************************************************/
+ib_api_status_t osmtest_wrong_sm_key_ignored(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_portinfo_record_t record;
+	osmtest_req_context_t context;
+	osmtest_req_context_t *p_context = &context;
+	uint8_t port_num = 1;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+		"Trying PortInfoRecord for port with LID 0x%X Num:0x%X\n",
+		p_osmt->local_port.sm_lid, port_num);
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = p_osmt->local_port.sm_lid;
+	record.port_num = port_num;
+	user.p_attr = &record;
+
+	p_context->p_osmt = p_osmt;
+
+	req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 9999;
+	context.result.p_result_madw = NULL;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	/* since we use a wrong sm_key we should get a timeout */
+	if (status != IB_TIMEOUT) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0011: "
+			"Did not get a timeout but got (%s)\n",
+			ib_get_err_str(status));
+		if (status == IB_SUCCESS) {
+			/* assign some error value to status, since IB_SUCCESS is a bad rc */
+			status = IB_ERROR;
+		}
+		goto Exit;
+	} else {
+		status = IB_SUCCESS;
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_port_info(IN osmtest_t * const p_osmt,
+			IN FILE * fh,
+			IN const ib_portinfo_record_t * const p_rec)
+{
+	int result;
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	result = fprintf(fh,
+			 "DEFINE_PORT\n"
+			 "lid                     0x%X\n"
+			 "port_num                0x%X\n"
+			 "m_key                   0x%016" PRIx64 "\n"
+			 "subnet_prefix           0x%016" PRIx64 "\n"
+			 "base_lid                0x%X\n"
+			 "master_sm_base_lid      0x%X\n"
+			 "capability_mask         0x%X\n"
+			 "diag_code               0x%X\n"
+			 "m_key_lease_period      0x%X\n"
+			 "local_port_num          0x%X\n"
+			 "link_width_enabled      0x%X\n"
+			 "link_width_supported    0x%X\n"
+			 "link_width_active       0x%X\n"
+			 "link_speed_supported    0x%X\n"
+			 "port_state              %s\n"
+			 "state_info2             0x%X\n"
+			 "mpb                     0x%X\n"
+			 "lmc                     0x%X\n"
+			 "link_speed              0x%X\n"
+			 "mtu_smsl                0x%X\n"
+			 "vl_cap                  0x%X\n"
+			 "vl_high_limit           0x%X\n"
+			 "vl_arb_high_cap         0x%X\n"
+			 "vl_arb_low_cap          0x%X\n"
+			 "mtu_cap                 0x%X\n"
+			 "vl_stall_life           0x%X\n"
+			 "vl_enforce              0x%X\n"
+			 "m_key_violations        0x%X\n"
+			 "p_key_violations        0x%X\n"
+			 "q_key_violations        0x%X\n"
+			 "guid_cap                0x%X\n"
+			 "subnet_timeout          0x%X\n"
+			 "resp_time_value         0x%X\n"
+			 "error_threshold         0x%X\n"
+			 "END\n\n",
+			 cl_ntoh16(p_rec->lid),
+			 p_rec->port_num,
+			 cl_ntoh64(p_rec->port_info.m_key),
+			 cl_ntoh64(p_rec->port_info.subnet_prefix),
+			 cl_ntoh16(p_rec->port_info.base_lid),
+			 cl_ntoh16(p_rec->port_info.master_sm_base_lid),
+			 cl_ntoh32(p_rec->port_info.capability_mask),
+			 cl_ntoh16(p_rec->port_info.diag_code),
+			 cl_ntoh16(p_rec->port_info.m_key_lease_period),
+			 p_rec->port_info.local_port_num,
+			 p_rec->port_info.link_width_enabled,
+			 p_rec->port_info.link_width_supported,
+			 p_rec->port_info.link_width_active,
+			 ib_port_info_get_link_speed_sup(&p_rec->port_info),
+			 ib_get_port_state_str(ib_port_info_get_port_state
+					       (&p_rec->port_info)),
+			 p_rec->port_info.state_info2,
+			 ib_port_info_get_mpb(&p_rec->port_info),
+			 ib_port_info_get_lmc(&p_rec->port_info),
+			 p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl,
+			 p_rec->port_info.vl_cap,
+			 p_rec->port_info.vl_high_limit,
+			 p_rec->port_info.vl_arb_high_cap,
+			 p_rec->port_info.vl_arb_low_cap,
+			 p_rec->port_info.mtu_cap,
+			 p_rec->port_info.vl_stall_life,
+			 p_rec->port_info.vl_enforce,
+			 cl_ntoh16(p_rec->port_info.m_key_violations),
+			 cl_ntoh16(p_rec->port_info.p_key_violations),
+			 cl_ntoh16(p_rec->port_info.q_key_violations),
+			 p_rec->port_info.guid_cap,
+			 ib_port_info_get_timeout(&p_rec->port_info),
+			 p_rec->port_info.resp_time_value,
+			 p_rec->port_info.error_threshold);
+
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0161: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_path_info(IN osmtest_t * const p_osmt,
+			IN FILE * fh, IN const ib_path_rec_t * const p_rec)
+{
+	int result;
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	result = fprintf(fh,
+			 "DEFINE_PATH\n"
+			 "dgid                    0x%016" PRIx64 " 0x%016"
+			 PRIx64 "\nsgid                    0x%016" PRIx64
+			 " 0x%016" PRIx64 "\ndlid                    0x%X\n"
+			 "slid                    0x%X\n"
+			 "# hop_flow_raw          0x%X\n"
+			 "# tclass                0x%X\n"
+			 "# num_path              0x%X\n"
+			 "pkey                    0x%X\n"
+			 "# sl                    0x%X\n"
+			 "# qos_class             0x%X\n"
+			 "# mtu                   0x%X\n"
+			 "# rate                  0x%X\n"
+			 "# pkt_life              0x%X\n"
+			 "# preference            0x%X\n" "END\n\n",
+			 cl_ntoh64(p_rec->dgid.unicast.prefix),
+			 cl_ntoh64(p_rec->dgid.unicast.interface_id),
+			 cl_ntoh64(p_rec->sgid.unicast.prefix),
+			 cl_ntoh64(p_rec->sgid.unicast.interface_id),
+			 cl_ntoh16(p_rec->dlid), cl_ntoh16(p_rec->slid),
+			 cl_ntoh32(p_rec->hop_flow_raw), p_rec->tclass,
+			 p_rec->num_path, cl_ntoh16(p_rec->pkey),
+			 ib_path_rec_sl(p_rec), ib_path_rec_qos_class(p_rec),
+			 p_rec->mtu, p_rec->rate, p_rec->pkt_life,
+			 p_rec->preference);
+
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0162: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_node_info(IN osmtest_t * const p_osmt,
+			IN FILE * fh, IN const ib_node_record_t * const p_rec)
+{
+	int result;
+	cl_status_t status = IB_SUCCESS;
+	char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memcpy(desc, p_rec->node_desc.description, IB_NODE_DESCRIPTION_SIZE);
+	desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+	result = fprintf(fh,
+			 "DEFINE_NODE\n"
+			 "lid                     0x%X\n"
+			 "base_version            0x%X\n"
+			 "class_version           0x%X\n"
+			 "node_type               0x%X # (%s)\n"
+			 "num_ports               0x%X\n"
+			 "sys_guid                0x%016" PRIx64 "\n"
+			 "node_guid               0x%016" PRIx64 "\n"
+			 "port_guid               0x%016" PRIx64 "\n"
+			 "partition_cap           0x%X\n"
+			 "device_id               0x%X\n"
+			 "revision                0x%X\n"
+			 "# port_num              0x%X\n"
+			 "# vendor_id             0x%X\n"
+			 "# node_desc             %s\n"
+			 "END\n\n",
+			 cl_ntoh16(p_rec->lid),
+			 p_rec->node_info.base_version,
+			 p_rec->node_info.class_version,
+			 p_rec->node_info.node_type,
+			 ib_get_node_type_str(p_rec->node_info.node_type),
+			 p_rec->node_info.num_ports,
+			 cl_ntoh64(p_rec->node_info.sys_guid),
+			 cl_ntoh64(p_rec->node_info.node_guid),
+			 cl_ntoh64(p_rec->node_info.port_guid),
+			 cl_ntoh16(p_rec->node_info.partition_cap),
+			 cl_ntoh16(p_rec->node_info.device_id),
+			 cl_ntoh32(p_rec->node_info.revision),
+			 ib_node_info_get_local_port_num(&p_rec->node_info),
+			 cl_ntoh32(ib_node_info_get_vendor_id
+				   (&p_rec->node_info)), desc);
+
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0163: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_link(IN osmtest_t * const p_osmt,
+		   IN FILE * fh, IN const ib_link_record_t * const p_rec)
+{
+	int result;
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	result = fprintf(fh,
+			 "DEFINE_LINK\n"
+			 "from_lid                0x%X\n"
+			 "from_port_num           0x%X\n"
+			 "to_port_num             0x%X\n"
+			 "to_lid                  0x%X\n"
+			 "END\n\n",
+			 cl_ntoh16(p_rec->from_lid),
+			 p_rec->from_port_num,
+			 p_rec->to_port_num, cl_ntoh16(p_rec->to_lid));
+
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0164: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_link_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_link_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+	int result;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_LINK_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0165: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Write the received records out to the file.
+	 */
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Received %zu records\n", num_recs);
+
+	result = fprintf(fh, "#\n" "# Link Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0166: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    (ib_link_record_t *) osmv_get_query_result(context.result.
+							       p_result_madw,
+							       i);
+
+		osmtest_write_link(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_lid_pair(IN osmtest_t * const p_osmt,
+				 IN ib_net16_t slid,
+				 IN ib_net16_t dlid,
+				 IN osmtest_req_context_t * p_context)
+{
+	cl_status_t status = IB_SUCCESS;
+	osmv_query_req_t req;
+	osmv_lid_pair_t lid_pair;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&req, 0, sizeof(req));
+	memset(p_context, 0, sizeof(*p_context));
+
+	p_context->p_osmt = p_osmt;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+
+	req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;
+
+	lid_pair.dest_lid = dlid;
+	lid_pair.src_lid = slid;
+
+	req.p_query_input = &lid_pair;
+	req.sm_key = 0;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Query for path from 0x%X to 0x%X\n", slid, dlid);
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0053: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = (*p_context).result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0067: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      ((*p_context).result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ * ASSUMES RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_node_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_node_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+	int result;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0022: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Write the received records out to the file.
+	 */
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs);
+
+	result = fprintf(fh, "#\n" "# Node Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0023: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_node_rec(context.result.p_result_madw, i);
+		osmtest_write_node_info(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * ASSUMES RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_port_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_portinfo_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+	int result;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0167: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Write the received records out to the file.
+	 */
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs);
+
+	result = fprintf(fh, "#\n" "# PortInfo Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0024: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_portinfo_rec(context.result.p_result_madw,
+						i);
+		osmtest_write_port_info(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * ASSUMES RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_path_rec_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+	int result;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all PathRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0025: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Write the received records out to the file.
+	 */
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs);
+
+	result = fprintf(fh, "#\n" "# Path Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0026: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_path_rec(context.result.p_result_madw, i);
+		osmtest_write_path_info(p_osmt, fh, p_rec);
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+#else
+/*
+ * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER
+ */
+static ib_api_status_t
+osmtest_write_all_node_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	node_t *p_node;
+	node_t *p_guid_node;
+	const ib_node_record_t *p_rec;
+	cl_status_t status = CL_SUCCESS;
+	int result;
+	uint16_t lid;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	result = fprintf(fh, "#\n" "# Node Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0027: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*
+	 * Go over all LIDs in the range 1 to max_lid and do a
+	 * NodeRecord query by that lid.
+	 */
+	for (lid = 1; lid <= p_osmt->max_lid; lid++) {
+		/* prepare the query context */
+		memset(&context, 0, sizeof(context));
+
+		status =
+		    osmtest_get_node_rec_by_lid(p_osmt, cl_ntoh16(lid),
+						&context);
+		if (status != IB_SUCCESS) {
+			if (status != IB_SA_MAD_STATUS_NO_RECORDS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "ERR 0028: "
+					"failed to get node info for LID:0x%02X (%s)\n",
+					cl_ntoh16(lid), ib_get_err_str(status));
+				goto Exit;
+			} else {
+				OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "WRN 0121: "
+					"failed to get node info for LID:0x%02X (%s)\n",
+					cl_ntoh16(lid), ib_get_err_str(status));
+				status = IB_SUCCESS;
+			}
+		} else {
+			/* OK we got something */
+			p_rec =
+			    osmv_get_query_node_rec(context.result.
+						    p_result_madw, 0);
+			osmtest_write_node_info(p_osmt, fh, p_rec);
+
+			/* create a subnet object */
+			p_node = node_new();
+			CL_ASSERT(p_node != NULL);
+
+			/* copy the info to the subnet node object */
+			p_node->rec = *p_rec;
+
+			cl_qmap_insert(&p_osmt->exp_subn.node_lid_tbl,
+				       p_node->rec.lid, &p_node->map_item);
+
+			p_guid_node = node_new();
+			CL_ASSERT(p_guid_node != NULL);
+
+			*p_guid_node = *p_node;
+
+			cl_qmap_insert(&p_osmt->exp_subn.node_guid_tbl,
+				       p_guid_node->rec.node_info.node_guid,
+				       &p_guid_node->map_item);
+
+		}
+
+		if (context.result.p_result_madw != NULL) {
+			osm_mad_pool_put(&p_osmt->mad_pool,
+					 context.result.p_result_madw);
+			context.result.p_result_madw = NULL;
+		}
+	}
+
+Exit:
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/*
+ * GET ALL PORT RECORDS IN THE FABRIC -
+ * one by one by using the node info received
+ */
+static ib_api_status_t
+osmtest_write_all_port_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_node_record_t *p_node_rec;
+	const ib_portinfo_record_t *p_rec;
+	uint8_t port_num;
+	cl_status_t status = CL_SUCCESS;
+	cl_qmap_t *p_tbl;
+	node_t *p_node;
+	port_t *p_port;
+	int result;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/* print header */
+	result = fprintf(fh, "#\n" "# PortInfo Records\n" "#\n");
+	if (result < 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0029: "
+			"Write failed\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* use the pre-explored set of nodes */
+	p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+	p_node = (node_t *) cl_qmap_head(p_tbl);
+
+	/*
+	 * Go over all LIDs in the range 1 to max_lid and do a
+	 * NodeRecord query by that lid.
+	 */
+	while (p_node != (node_t *) cl_qmap_end(p_tbl)) {
+
+		p_node_rec = &(p_node->rec);
+
+		/* go through all ports of the node: */
+		for (port_num = 0; port_num <= p_node_rec->node_info.num_ports;
+		     port_num++) {
+			/* prepare the query context */
+			memset(&context, 0, sizeof(context));
+
+			status = osmtest_get_port_rec_by_num(p_osmt,
+							     p_node_rec->lid,
+							     port_num,
+							     &context);
+			if (status != IB_SUCCESS) {
+				if (status != IB_SA_MAD_STATUS_NO_RECORDS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"WRN 0122: "
+						"Error encountered getting port info for LID:0x%04X Num:0x%02X (%s)\n",
+						p_node_rec->lid, port_num,
+						ib_get_err_str(status));
+					goto Exit;
+				} else {
+					OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+						"WRN 0123: "
+						"failed to get port info for LID:0x%04X Num:0x%02X (%s)\n",
+						p_node_rec->lid, port_num,
+						ib_get_err_str(status));
+					status = IB_SUCCESS;
+				}
+			} else {
+				/* OK we got something */
+				p_rec =
+				    osmv_get_query_portinfo_rec(context.result.
+								p_result_madw,
+								0);
+				osmtest_write_port_info(p_osmt, fh, p_rec);
+
+				/* create a subnet object */
+				p_port = port_new();
+				CL_ASSERT(p_port != NULL);
+
+				/* copy the info to the subnet node object */
+				p_port->rec = *p_rec;
+
+				cl_qmap_insert(&p_osmt->exp_subn.port_key_tbl,
+					       port_gen_id(p_node_rec->lid,
+							   port_num),
+					       &p_port->map_item);
+			}
+
+			if (context.result.p_result_madw != NULL) {
+				osm_mad_pool_put(&p_osmt->mad_pool,
+						 context.result.p_result_madw);
+				context.result.p_result_madw = NULL;
+			}
+		}
+		p_node = (node_t *) cl_qmap_next(&p_node->map_item);
+	}
+
+	/* we must set the exist status to avoid abort of the over all algorith */
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * ASSUMES NO RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs(IN osmtest_t * const p_osmt, IN FILE * fh)
+{
+	osmtest_req_context_t context;
+	const ib_path_rec_t *p_rec;
+	cl_status_t status = CL_SUCCESS;
+	int num_recs, i;
+	cl_qmap_t *p_tbl;
+	node_t *p_src_node, *p_dst_node;
+	ib_api_status_t got_status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Go over all nodes that exist in the subnet
+	 * for each pair that are not switch nodes get the path record
+	 */
+
+	context.p_osmt = p_osmt;
+
+	p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+	p_src_node = (node_t *) cl_qmap_head(p_tbl);
+
+	while (p_src_node != (node_t *) cl_qmap_end(p_tbl)) {
+		/* HACK we use capability_mask to know diff a CA node from switch node */
+		/* if(p_src_node->rec.node_info.capability_mask  ) { */
+		p_dst_node = (node_t *) cl_qmap_head(p_tbl);
+
+		while (p_dst_node != (node_t *) cl_qmap_end(p_tbl)) {
+			/* HACK we use capability_mask to know diff a CA node from switch node */
+			/* if (p_dst_node->rec.node_info.capability_mask) { */
+
+			/* query for it: */
+			status = osmtest_get_path_rec_by_lid_pair(p_osmt,
+								  p_src_node->
+								  rec.lid,
+								  p_dst_node->
+								  rec.lid,
+								  &context);
+
+			if (status != IB_SUCCESS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012D: "
+					"failed to get path info from LID:0x%X To LID:0x%X (%s)\n",
+					p_src_node->rec.lid,
+					p_dst_node->rec.lid,
+					ib_get_err_str(status));
+				/* remember the first error status */
+				got_status =
+				    (got_status ==
+				     IB_SUCCESS) ? status : got_status;
+			} else {
+				/* we might have received several records */
+				num_recs = context.result.result_cnt;
+				for (i = 0; i < num_recs; i++) {
+					p_rec =
+					    osmv_get_query_path_rec(context.
+								    result.
+								    p_result_madw,
+								    i);
+					osmtest_write_path_info(p_osmt, fh,
+								p_rec);
+				}
+			}
+/*  } */
+
+			if (context.result.p_result_madw != NULL) {
+				osm_mad_pool_put(&p_osmt->mad_pool,
+						 context.result.p_result_madw);
+				context.result.p_result_madw = NULL;
+			}
+
+			/* next one please */
+			p_dst_node =
+			    (node_t *) cl_qmap_next(&p_dst_node->map_item);
+		}
+/* } */
+
+		p_src_node = (node_t *) cl_qmap_next(&p_src_node->map_item);
+	}
+
+	if (got_status != IB_SUCCESS)
+		status = got_status;
+
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_create_inventory_file(IN osmtest_t * const p_osmt)
+{
+	FILE *fh;
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	fh = fopen(p_osmt->opt.file_name, "w");
+	if (fh == NULL) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0079: "
+			"Unable to open inventory file (%s)\n",
+			p_osmt->opt.file_name);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/* HACK: the order is important: nodes ports paths */
+	status = osmtest_write_all_node_recs(p_osmt, fh);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	status = osmtest_write_all_port_recs(p_osmt, fh);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (!p_osmt->opt.ignore_path_records) {
+		status = osmtest_write_all_path_recs(p_osmt, fh);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	status = osmtest_write_all_link_recs(p_osmt, fh);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	fclose(fh);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_stress_large_rmpp_pr(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint64_t num_recs = 0;
+	uint64_t num_queries = 0;
+	uint32_t delta_recs;
+	uint32_t delta_queries;
+	uint32_t print_freq = 0;
+	struct timeval start_tv, end_tv;
+	long sec_diff, usec_diff;
+	float ratio;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+	gettimeofday(&start_tv, NULL);
+	printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec,
+	       (long)start_tv.tv_usec);
+
+	while (num_queries < STRESS_LARGE_PR_RMPP_THR) {
+		delta_recs = 0;
+		delta_queries = 0;
+
+		status = osmtest_stress_path_recs_by_guid(p_osmt, &delta_recs,
+							  &delta_queries);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		num_recs += delta_recs;
+		num_queries += delta_queries;
+
+		print_freq += delta_recs;
+		if (print_freq > 10000) {
+			gettimeofday(&end_tv, NULL);
+			if (end_tv.tv_usec > start_tv.tv_usec) {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+				usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+			} else {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+				usec_diff =
+				    1000000 - (start_tv.tv_usec -
+					       end_tv.tv_usec);
+			}
+			printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+			       end_tv.tv_sec, (long)end_tv.tv_usec);
+			printf("-I- Querying %" PRId64
+			       " Path Record queries CA to CA (rmpp)\n\ttook %04ld:%06ld [sec:usec]\n",
+			       num_queries, sec_diff, usec_diff);
+			if (num_recs == 0)
+				ratio = 0;
+			else
+				ratio = ((float)num_queries / (float)num_recs);
+			printf("-I- Queries to Record Ratio is %" PRIu64
+			       " records, %" PRIu64 " queries : %.2f \n",
+			       num_recs, num_queries, ratio);
+			print_freq = 0;
+		}
+	}
+
+Exit:
+	gettimeofday(&end_tv, NULL);
+	printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+	       end_tv.tv_sec, (long)end_tv.tv_usec);
+	if (end_tv.tv_usec > start_tv.tv_usec) {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+		usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+	} else {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+		usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+	}
+
+	printf("-I- Querying %" PRId64
+	       " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n",
+	       num_queries, sec_diff, usec_diff);
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_stress_large_rmpp(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint64_t num_recs = 0;
+	uint64_t num_queries = 0;
+	uint32_t delta_recs;
+	uint32_t delta_queries;
+	uint32_t print_freq = 0;
+	struct timeval start_tv, end_tv;
+	long sec_diff, usec_diff;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+	gettimeofday(&start_tv, NULL);
+	printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec,
+	       (long)start_tv.tv_usec);
+
+	while (num_queries < STRESS_LARGE_RMPP_THR) {
+		delta_recs = 0;
+		delta_queries = 0;
+
+		status = osmtest_stress_node_recs_large(p_osmt, &delta_recs,
+							&delta_queries);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		status = osmtest_stress_path_recs_large(p_osmt, &delta_recs,
+							&delta_queries);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		status = osmtest_stress_port_recs_large(p_osmt, &delta_recs,
+							&delta_queries);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		num_recs += delta_recs;
+		num_queries += delta_queries;
+
+		print_freq += delta_recs;
+
+		if (print_freq > 100000) {
+			gettimeofday(&end_tv, NULL);
+			if (end_tv.tv_usec > start_tv.tv_usec) {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+				usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+			} else {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+				usec_diff =
+				    1000000 - (start_tv.tv_usec -
+					       end_tv.tv_usec);
+			}
+			printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+			       end_tv.tv_sec, (long)end_tv.tv_usec);
+			printf("-I- Querying %" PRId64
+			       " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",
+			       num_queries, sec_diff, usec_diff);
+			printf("%" PRIu64 " records, %" PRIu64 " queries\n",
+			       num_recs, num_queries);
+			print_freq = 0;
+		}
+	}
+
+Exit:
+	gettimeofday(&end_tv, NULL);
+	printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+	       end_tv.tv_sec, (long)end_tv.tv_usec);
+	if (end_tv.tv_usec > start_tv.tv_usec) {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+		usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+	} else {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+		usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+	}
+
+	printf("-I- Querying %" PRId64
+	       " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",
+	       num_queries, sec_diff, usec_diff);
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_stress_small_rmpp(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint64_t num_recs = 0;
+	uint64_t num_queries = 0;
+	uint32_t delta_recs;
+	uint32_t delta_queries;
+	uint32_t print_freq = 0;
+	int num_timeouts = 0;
+	struct timeval start_tv, end_tv;
+	long sec_diff, usec_diff;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+	gettimeofday(&start_tv, NULL);
+	printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",
+	       start_tv.tv_sec, (long)start_tv.tv_usec);
+
+	while ((num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100)) {
+		delta_recs = 0;
+		delta_queries = 0;
+
+		status = osmtest_stress_port_recs_small(p_osmt, &delta_recs,
+							&delta_queries);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		num_recs += delta_recs;
+		num_queries += delta_queries;
+
+		print_freq += delta_recs;
+		if (print_freq > 5000) {
+			gettimeofday(&end_tv, NULL);
+			printf("%" PRIu64 " records, %" PRIu64 " queries\n",
+			       num_recs, num_queries);
+			if (end_tv.tv_usec > start_tv.tv_usec) {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+				usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+			} else {
+				sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+				usec_diff =
+				    1000000 - (start_tv.tv_usec -
+					       end_tv.tv_usec);
+			}
+			printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+			       end_tv.tv_sec, (long)end_tv.tv_usec);
+			printf("-I- Querying %" PRId64
+			       " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",
+			       num_queries, sec_diff, usec_diff);
+			print_freq = 0;
+		}
+	}
+
+Exit:
+	gettimeofday(&end_tv, NULL);
+	printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+	       end_tv.tv_sec, (long)end_tv.tv_usec);
+	if (end_tv.tv_usec > start_tv.tv_usec) {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec;
+		usec_diff = end_tv.tv_usec - start_tv.tv_usec;
+	} else {
+		sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1;
+		usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+	}
+
+	printf("-I- Querying %" PRId64
+	       " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",
+	       num_queries, sec_diff, usec_diff);
+	if (num_timeouts > 50) {
+		status = IB_TIMEOUT;
+	}
+	/* Exit: */
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osmtest_prepare_db_generic(IN osmtest_t * const p_osmt,
+			   IN cl_qmap_t * const p_tbl)
+{
+	generic_t *p_generic;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_generic = (generic_t *) cl_qmap_head(p_tbl);
+
+	while (p_generic != (generic_t *) cl_qmap_end(p_tbl)) {
+		p_generic->count = 0;
+		p_generic = (generic_t *) cl_qmap_next(&p_generic->map_item);
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void osmtest_prepare_db(IN osmtest_t * const p_osmt)
+{
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	osmtest_prepare_db_generic(p_osmt, &p_osmt->exp_subn.node_lid_tbl);
+	osmtest_prepare_db_generic(p_osmt, &p_osmt->exp_subn.path_tbl);
+
+	OSM_LOG_EXIT(&p_osmt->log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_check_missing_nodes(IN osmtest_t * const p_osmt)
+{
+	const node_t *p_node;
+	cl_status_t status = IB_SUCCESS;
+	cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+	p_node = (node_t *) cl_qmap_head(p_tbl);
+
+	while (p_node != (node_t *) cl_qmap_end(p_tbl)) {
+		if (p_node->count == 0) {
+			/*
+			 * This node was not reported by the SA
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0080: "
+				"Missing node 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_node->rec.node_info.node_guid));
+			status = IB_ERROR;
+		}
+
+		p_node = (node_t *) cl_qmap_next(&p_node->map_item);
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_check_missing_ports(IN osmtest_t * const p_osmt)
+{
+	const port_t *p_port;
+	cl_status_t status = IB_SUCCESS;
+	cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+	p_port = (port_t *) cl_qmap_head(p_tbl);
+
+	while (p_port != (port_t *) cl_qmap_end(p_tbl)) {
+		if (p_port->count == 0) {
+			/*
+			 * This port was not reported by the SA
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0081: "
+				"Missing port LID:0x%X Num:0x%X\n",
+				cl_ntoh16(p_port->rec.lid),
+				p_port->rec.port_num);
+			status = IB_ERROR;
+		}
+
+		p_port = (port_t *) cl_qmap_next(&p_port->map_item);
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_check_missing_paths(IN osmtest_t * const p_osmt)
+{
+	const path_t *p_path;
+	cl_status_t status = IB_SUCCESS;
+	cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_tbl = &p_osmt->exp_subn.path_tbl;
+
+	p_path = (path_t *) cl_qmap_head(p_tbl);
+
+	while (p_path != (path_t *) cl_qmap_end(p_tbl)) {
+		if (p_path->count == 0) {
+			/*
+			 * This path was not reported by the SA
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0051: "
+				"SA did not return path SLID 0x%X to DLID 0x%X\n",
+				cl_ntoh16(p_path->rec.slid),
+				cl_ntoh16(p_path->rec.dlid));
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		p_path = (path_t *) cl_qmap_next(&p_path->map_item);
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+inline uint32_t osmtest_path_rec_key_get(IN const ib_path_rec_t * const p_rec)
+{
+	return (p_rec->dlid << 16 | p_rec->slid);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+osmtest_path_rec_kay_is_valid(IN osmtest_t * const p_osmt,
+			      IN const path_t * const p_path)
+{
+	if ((p_path->comp.dlid == 0) || (p_path->comp.slid == 0)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0168: "
+			"SLID and DLID must be specified for defined paths\n");
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_data(IN osmtest_t * const p_osmt,
+			   IN path_t * const p_path,
+			   IN const ib_path_rec_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+	uint8_t lmc = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+		"Checking path SLID 0x%X to DLID 0x%X\n",
+		cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid));
+
+	status =
+	    osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* HACK: Assume uniform LMC across endports in the subnet */
+	/* This is the only LMC mode which OpenSM currently supports */
+	/* In absence of this assumption, validation of this is much more complicated */
+	if (lmc == 0) {
+		/*
+		 * Has this record already been returned?
+		 */
+		if (p_path->count != 0) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0056: "
+				"Already received path SLID 0x%X to DLID 0x%X\n",
+				cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid));
+			status = IB_ERROR;
+			goto Exit;
+		}
+	} else {
+		/* Also, this doesn't detect fewer than the correct number of paths being returned */
+		if (p_path->count >= (uint32_t) (1 << (2 * lmc))) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0052: "
+				"Already received path SLID 0x%X to DLID 0x%X count %d LMC %d\n",
+				cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid),
+				p_path->count, lmc);
+			status = IB_ERROR;
+			goto Exit;
+		}
+	}
+
+	++p_path->count;
+
+	/*
+	 * Check the fields the user wants checked.
+	 */
+	if ((p_path->comp.dgid.unicast.interface_id &
+	     p_path->rec.dgid.unicast.interface_id) !=
+	    (p_path->comp.dgid.unicast.interface_id &
+	     p_rec->dgid.unicast.interface_id)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0169: "
+			"DGID mismatch on path SLID 0x%X to DLID 0x%X\n"
+			"\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 "\n"
+			"\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
+			cl_ntoh16(p_path->rec.slid),
+			cl_ntoh16(p_path->rec.dlid),
+			cl_ntoh64(p_path->rec.dgid.unicast.prefix),
+			cl_ntoh64(p_path->rec.dgid.unicast.interface_id),
+			cl_ntoh64(p_rec->dgid.unicast.prefix),
+			cl_ntoh64(p_rec->dgid.unicast.interface_id));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*
+	 * Check the fields the user wants checked.
+	 */
+	if ((p_path->comp.sgid.unicast.interface_id &
+	     p_path->rec.sgid.unicast.interface_id) !=
+	    (p_path->comp.sgid.unicast.interface_id &
+	     p_rec->sgid.unicast.interface_id)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0057: "
+			"SGID mismatch on path SLID 0x%X to DLID 0x%X\n"
+			"\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"
+			"\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+			cl_ntoh16(p_path->rec.slid),
+			cl_ntoh16(p_path->rec.dlid),
+			cl_ntoh64(p_path->rec.sgid.unicast.prefix),
+			cl_ntoh64(p_path->rec.sgid.unicast.interface_id),
+			cl_ntoh64(p_rec->sgid.unicast.prefix),
+			cl_ntoh64(p_rec->sgid.unicast.interface_id));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*
+	 * Compare the fields the user wishes to validate.
+	 */
+	if ((p_path->comp.pkey & p_path->rec.pkey) !=
+	    (p_path->comp.pkey & p_rec->pkey)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0012: "
+			"PKEY mismatch on path SLID 0x%X to DLID 0x%X\n"
+			"\t\t\t\tExpected 0x%X, received 0x%X\n",
+			cl_ntoh16(p_path->rec.slid),
+			cl_ntoh16(p_path->rec.dlid),
+			cl_ntoh16(p_path->rec.pkey), cl_ntoh16(p_rec->pkey));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_data(IN osmtest_t * const p_osmt,
+			   IN node_t * const p_node,
+			   IN const ib_node_record_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+		"Checking node 0x%016" PRIx64 ", LID 0x%X\n",
+		cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid));
+
+	/*
+	 * Has this record already been returned?
+	 */
+	if (p_node->count != 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0013: "
+			"Already received node 0x%016" PRIx64 "\n",
+			cl_ntoh64(p_node->rec.node_info.node_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	++p_node->count;
+
+	/*
+	 * Compare the fields the user wishes to validate.
+	 */
+	if ((p_node->comp.lid & p_node->rec.lid) !=
+	    (p_node->comp.lid & p_rec->lid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0014: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected LID 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid), p_node->rec.lid, p_rec->lid);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.base_version &
+	     p_node->rec.node_info.base_version) !=
+	    (p_node->comp.node_info.base_version &
+	     p_rec->node_info.base_version)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0015: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected base_version 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			p_node->rec.node_info.base_version,
+			p_rec->node_info.base_version);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.class_version &
+	     p_node->rec.node_info.class_version) !=
+	    (p_node->comp.node_info.class_version &
+	     p_rec->node_info.class_version)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0016: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected class_version 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			p_node->rec.node_info.class_version,
+			p_rec->node_info.class_version);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.node_type &
+	     p_node->rec.node_info.node_type) !=
+	    (p_node->comp.node_info.node_type & p_rec->node_info.node_type)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0017: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected node_type 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			p_node->rec.node_info.node_type,
+			p_rec->node_info.node_type);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.sys_guid &
+	     p_node->rec.node_info.sys_guid) !=
+	    (p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0018: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected sys_guid 0x%016" PRIx64
+			", received 0x%016" PRIx64 "\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh64(p_node->rec.node_info.sys_guid),
+			cl_ntoh64(p_rec->node_info.sys_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.node_guid &
+	     p_node->rec.node_info.node_guid) !=
+	    (p_node->comp.node_info.node_guid & p_rec->node_info.node_guid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0019: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected node_guid 0x%016" PRIx64
+			", received 0x%016" PRIx64 "\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh64(p_node->rec.node_info.node_guid),
+			cl_ntoh64(p_rec->node_info.node_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.port_guid &
+	     p_node->rec.node_info.port_guid) !=
+	    (p_node->comp.node_info.port_guid & p_rec->node_info.port_guid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0031: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected port_guid 0x%016" PRIx64
+			", received 0x%016" PRIx64 "\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh64(p_node->rec.node_info.port_guid),
+			cl_ntoh64(p_rec->node_info.port_guid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.partition_cap &
+	     p_node->rec.node_info.partition_cap) !=
+	    (p_node->comp.node_info.partition_cap &
+	     p_rec->node_info.partition_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0032: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected partition_cap 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh16(p_node->rec.node_info.partition_cap),
+			cl_ntoh16(p_rec->node_info.partition_cap));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.device_id &
+	     p_node->rec.node_info.device_id) !=
+	    (p_node->comp.node_info.device_id & p_rec->node_info.device_id)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0033: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected device_id 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh16(p_node->rec.node_info.device_id),
+			cl_ntoh16(p_rec->node_info.device_id));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_node->comp.node_info.revision &
+	     p_node->rec.node_info.revision) !=
+	    (p_node->comp.node_info.revision & p_rec->node_info.revision)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0034: "
+			"Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"
+			"\t\t\t\tExpected revision 0x%X, received 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid),
+			cl_ntoh32(p_node->rec.node_info.revision),
+			cl_ntoh32(p_rec->node_info.revision));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_rec(IN osmtest_t * const p_osmt,
+			  IN const ib_node_record_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+	node_t *p_node;
+	const cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Find proper node record in the database.
+	 */
+	p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+	p_node = (node_t *) cl_qmap_get(p_tbl, p_rec->lid);
+	if (p_node == (node_t *) cl_qmap_end(p_tbl)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0035: "
+			"Unexpected node 0x%016" PRIx64 ", LID 0x%X\n",
+			cl_ntoh64(p_rec->node_info.node_guid),
+			cl_ntoh16(p_rec->lid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	status = osmtest_validate_node_data(p_osmt, p_node, p_rec);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_data(IN osmtest_t * const p_osmt,
+			   IN port_t * const p_port,
+			   IN const ib_portinfo_record_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+		"Checking port LID 0x%X, Num 0x%X\n",
+		cl_ntoh16(p_rec->lid), p_rec->port_num);
+
+	/*
+	 * Has this record already been returned?
+	 */
+	if (p_port->count != 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0036: "
+			"Already received port LID 0x%X, Num 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	++p_port->count;
+
+	/*
+	 * Compare the fields the user wishes to validate.
+	 */
+	if ((p_port->comp.lid & p_port->rec.lid) !=
+	    (p_port->comp.lid & p_rec->lid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0037: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected LID 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.lid, p_rec->lid);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_num & p_port->rec.port_num) !=
+	    (p_port->comp.port_num & p_rec->port_num)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0038: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected port_num 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_num, p_rec->port_num);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.m_key & p_port->rec.port_info.m_key) !=
+	    (p_port->comp.port_info.m_key & p_rec->port_info.m_key)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0039: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected m_key 0x%016" PRIx64
+			", received 0x%016" PRIx64 "\n", cl_ntoh16(p_rec->lid),
+			p_rec->port_num, p_port->rec.port_info.m_key,
+			p_rec->port_info.m_key);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.subnet_prefix & p_port->rec.port_info.
+	     subnet_prefix) !=
+	    (p_port->comp.port_info.subnet_prefix & p_rec->port_info.
+	     subnet_prefix)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0040: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected subnet_prefix 0x%016" PRIx64
+			", received 0x%016" PRIx64 "\n", cl_ntoh16(p_rec->lid),
+			p_rec->port_num, p_port->rec.port_info.subnet_prefix,
+			p_rec->port_info.subnet_prefix);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.base_lid & p_port->rec.port_info.
+	     base_lid) !=
+	    (p_port->comp.port_info.base_lid & p_rec->port_info.base_lid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0041: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected base_lid 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.base_lid,
+			p_rec->port_info.base_lid);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info.
+	     master_sm_base_lid) !=
+	    (p_port->comp.port_info.master_sm_base_lid & p_rec->port_info.
+	     master_sm_base_lid)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0042: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.master_sm_base_lid,
+			p_rec->port_info.master_sm_base_lid);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.capability_mask & p_port->rec.port_info.
+	     capability_mask) !=
+	    (p_port->comp.port_info.capability_mask & p_rec->port_info.
+	     capability_mask)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0043: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected capability_mask 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			cl_ntoh32(p_port->rec.port_info.capability_mask),
+			cl_ntoh32(p_rec->port_info.capability_mask));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.diag_code & p_port->rec.port_info.
+	     diag_code) !=
+	    (p_port->comp.port_info.diag_code & p_rec->port_info.diag_code)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0044: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected diag_code 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.diag_code,
+			p_rec->port_info.diag_code);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info.
+	     m_key_lease_period) !=
+	    (p_port->comp.port_info.m_key_lease_period & p_rec->port_info.
+	     m_key_lease_period)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0045: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.m_key_lease_period,
+			p_rec->port_info.m_key_lease_period);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.local_port_num & p_port->rec.port_info.
+	     local_port_num) !=
+	    (p_port->comp.port_info.local_port_num & p_rec->port_info.
+	     local_port_num)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0046: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected local_port_num 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.local_port_num,
+			p_rec->port_info.local_port_num);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.link_width_enabled & p_port->rec.port_info.
+	     link_width_enabled) !=
+	    (p_port->comp.port_info.link_width_enabled & p_rec->port_info.
+	     link_width_enabled)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0047: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.link_width_enabled,
+			p_rec->port_info.link_width_enabled);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.link_width_supported & p_port->rec.
+	     port_info.link_width_supported) !=
+	    (p_port->comp.port_info.link_width_supported & p_rec->port_info.
+	     link_width_supported)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0048: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected link_width_supported 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.link_width_supported,
+			p_rec->port_info.link_width_supported);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.link_width_active & p_port->rec.port_info.
+	     link_width_active) !=
+	    (p_port->comp.port_info.link_width_active & p_rec->port_info.
+	     link_width_active)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0049: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected link_width_active 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.link_width_active,
+			p_rec->port_info.link_width_active);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.link_speed & p_port->rec.port_info.
+	     link_speed) !=
+	    (p_port->comp.port_info.link_speed & p_rec->port_info.link_speed)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0054: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.link_speed,
+			p_rec->port_info.link_speed);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.state_info1 & p_port->rec.port_info.
+	     state_info1) !=
+	    (p_port->comp.port_info.state_info1 & p_rec->port_info.
+	     state_info1)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0055: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected state_info1 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.state_info1,
+			p_rec->port_info.state_info1);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.state_info2 & p_port->rec.port_info.
+	     state_info2) !=
+	    (p_port->comp.port_info.state_info2 & p_rec->port_info.
+	     state_info2)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0058: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected state_info2 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.state_info2,
+			p_rec->port_info.state_info2);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.mkey_lmc & p_port->rec.port_info.
+	     mkey_lmc) !=
+	    (p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0059: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.mkey_lmc,
+			p_rec->port_info.mkey_lmc);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.link_speed & p_port->rec.port_info.
+	     link_speed) !=
+	    (p_port->comp.port_info.link_speed & p_rec->port_info.link_speed)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0060: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.link_speed,
+			p_rec->port_info.link_speed);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.mtu_smsl & p_port->rec.port_info.
+	     mtu_smsl) !=
+	    (p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0061: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.mtu_smsl,
+			p_rec->port_info.mtu_smsl);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap) !=
+	    (p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0062: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_cap 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.vl_high_limit & p_port->rec.port_info.
+	     vl_high_limit) !=
+	    (p_port->comp.port_info.vl_high_limit & p_rec->port_info.
+	     vl_high_limit)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0082: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_high_limit,
+			p_rec->port_info.vl_high_limit);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info.
+	     vl_arb_high_cap) !=
+	    (p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info.
+	     vl_arb_high_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0083: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_arb_high_cap,
+			p_rec->port_info.vl_arb_high_cap);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info.
+	     vl_arb_low_cap) !=
+	    (p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info.
+	     vl_arb_low_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0084: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_arb_low_cap,
+			p_rec->port_info.vl_arb_low_cap);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap) !=
+	    (p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0085: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected mtu_cap 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.mtu_cap,
+			p_rec->port_info.mtu_cap);
+		status = IB_ERROR;
+		goto Exit;
+	}
+#if 0
+	/* this is a dynamic attribute */
+	if ((p_port->comp.port_info.vl_stall_life & p_port->rec.port_info.
+	     vl_stall_life) !=
+	    (p_port->comp.port_info.vl_stall_life & p_rec->port_info.
+	     vl_stall_life)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012F: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_stall_life,
+			p_rec->port_info.vl_stall_life);
+		status = IB_ERROR;
+		goto Exit;
+	}
+#endif
+
+	if ((p_port->comp.port_info.vl_enforce & p_port->rec.port_info.
+	     vl_enforce) !=
+	    (p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0086: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected vl_enforce 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.vl_enforce,
+			p_rec->port_info.vl_enforce);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.m_key_violations & p_port->rec.port_info.
+	     m_key_violations) !=
+	    (p_port->comp.port_info.m_key_violations & p_rec->port_info.
+	     m_key_violations)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0087: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected m_key_violations 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			cl_ntoh16(p_port->rec.port_info.m_key_violations),
+			cl_ntoh16(p_rec->port_info.m_key_violations));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.p_key_violations & p_port->rec.port_info.
+	     p_key_violations) !=
+	    (p_port->comp.port_info.p_key_violations & p_rec->port_info.
+	     p_key_violations)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0088: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected p_key_violations 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			cl_ntoh16(p_port->rec.port_info.p_key_violations),
+			cl_ntoh16(p_rec->port_info.p_key_violations));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.q_key_violations & p_port->rec.port_info.
+	     q_key_violations) !=
+	    (p_port->comp.port_info.q_key_violations & p_rec->port_info.
+	     q_key_violations)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0089: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected q_key_violations 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			cl_ntoh16(p_port->rec.port_info.q_key_violations),
+			cl_ntoh16(p_rec->port_info.q_key_violations));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.guid_cap & p_port->rec.port_info.
+	     guid_cap) !=
+	    (p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0090: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected guid_cap 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.guid_cap,
+			p_rec->port_info.guid_cap);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.subnet_timeout & p_port->rec.port_info.
+	     subnet_timeout) !=
+	    (p_port->comp.port_info.subnet_timeout & p_rec->port_info.
+	     subnet_timeout)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0091: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			ib_port_info_get_timeout(&p_port->rec.port_info),
+			ib_port_info_get_timeout(&p_rec->port_info));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.resp_time_value & p_port->rec.port_info.
+	     resp_time_value) !=
+	    (p_port->comp.port_info.resp_time_value & p_rec->port_info.
+	     resp_time_value)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0092: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected resp_time_value 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.resp_time_value,
+			p_rec->port_info.resp_time_value);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	if ((p_port->comp.port_info.error_threshold & p_port->rec.port_info.
+	     error_threshold) !=
+	    (p_port->comp.port_info.error_threshold & p_rec->port_info.
+	     error_threshold)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0093: "
+			"Field mismatch port LID 0x%X Num:0x%X\n"
+			"\t\t\t\tExpected error_threshold 0x%X, received 0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num,
+			p_port->rec.port_info.error_threshold,
+			p_rec->port_info.error_threshold);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_rec(IN osmtest_t * const p_osmt,
+			  IN const ib_portinfo_record_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+	port_t *p_port;
+	const cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Find proper port record in the database.
+	 * (we use by guid - since lid is not unique)
+	 */
+	p_tbl = &p_osmt->exp_subn.port_key_tbl;
+	p_port =
+	    (port_t *) cl_qmap_get(p_tbl,
+				   port_gen_id(p_rec->lid, p_rec->port_num));
+	if (p_port == (port_t *) cl_qmap_end(p_tbl)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0094: "
+			"Unexpected port LID 0x%X, Num:0x%X\n",
+			cl_ntoh16(p_rec->lid), p_rec->port_num);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	status = osmtest_validate_port_data(p_osmt, p_port, p_rec);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_rec(IN osmtest_t * const p_osmt,
+			  IN const ib_path_rec_t * const p_rec)
+{
+	cl_status_t status = IB_SUCCESS;
+	path_t *p_path;
+	const cl_qmap_t *p_tbl;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Find proper path record in the database.
+	 */
+	p_tbl = &p_osmt->exp_subn.path_tbl;
+	p_path = (path_t *) cl_qmap_get(p_tbl, osmtest_path_rec_key_get(p_rec));
+	if (p_path == (path_t *) cl_qmap_end(p_tbl)) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0095: "
+			"Unexpected path SLID 0x%X to DLID 0x%X\n",
+			cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid));
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	status = osmtest_validate_path_data(p_osmt, p_path, p_rec);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+ib_net64_t portguid = 0;
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_node_recs(IN osmtest_t * const p_osmt)
+{
+	osmtest_req_context_t context;
+	const ib_node_record_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all NodeRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0096: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n",
+		num_recs);
+
+	/*
+	 * Compare the received records to the database.
+	 */
+	osmtest_prepare_db(p_osmt);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_node_rec(context.result.p_result_madw, i);
+
+		status = osmtest_validate_node_rec(p_osmt, p_rec);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0097: "
+				"osmtest_valid_node_rec failed (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		if (!portguid)
+			portguid = p_rec->node_info.port_guid;
+	}
+
+	status = osmtest_check_missing_nodes(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0098: "
+			"osmtest_check_missing_nodes failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_guidinfo_recs(IN osmtest_t * const p_osmt)
+{
+	osmtest_req_context_t context;
+	const ib_guidinfo_record_t *p_rec;
+	cl_status_t status;
+	size_t num_recs;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all GuidInfoRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_GUIDINFO_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0099: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n",
+		num_recs);
+
+	/* No validation as yet */
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_path_recs(IN osmtest_t * const p_osmt)
+{
+	osmtest_req_context_t context;
+	const ib_path_rec_t *p_rec;
+	uint32_t i;
+	cl_status_t status;
+	size_t num_recs;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	/*
+	 * Do a blocking query for all PathRecords in the subnet.
+	 */
+	status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD,
+				      sizeof(*p_rec), &context);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009A: "
+			"osmtest_get_all_recs failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n",
+		num_recs);
+
+	/*
+	 * Compare the received records to the database.
+	 */
+	osmtest_prepare_db(p_osmt);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_path_rec(context.result.p_result_madw, i);
+
+		status = osmtest_validate_path_rec(p_osmt, p_rec);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0100: "
+				"osmtest_validate_path_rec failed (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+	}
+
+	status = osmtest_check_missing_paths(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0101: "
+			"osmtest_check_missing_paths failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get link record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_link_rec_by_lid(IN osmtest_t * const p_osmt,
+			    IN ib_net16_t const from_lid,
+			    IN ib_net16_t const to_lid,
+			    IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_link_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting link record from LID 0x%02X to LID 0x%02X\n",
+		cl_ntoh16(from_lid), cl_ntoh16(to_lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.from_lid = from_lid;
+	record.to_lid = to_lid;
+	p_context->p_osmt = p_osmt;
+	if (from_lid)
+		user.comp_mask |= IB_LR_COMPMASK_FROM_LID;
+	if (to_lid)
+		user.comp_mask |= IB_LR_COMPMASK_TO_LID;
+	user.attr_id = IB_MAD_ATTR_LINK_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007A: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007B: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"osmtest_get_link_rec_by_lid: "
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get GUIDInfo record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_guidinfo_rec_by_lid(IN osmtest_t * const p_osmt,
+				IN ib_net16_t const lid,
+				IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_guidinfo_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting GUIDInfo record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	p_context->p_osmt = p_osmt;
+	user.comp_mask = IB_GIR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_GUIDINFO_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007C: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007D: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get PKeyTable record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_pkeytbl_rec_by_lid(IN osmtest_t * const p_osmt,
+			       IN ib_net16_t const lid,
+			       IN ib_net64_t const sm_key,
+			       IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_pkey_table_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting PKeyTable record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	p_context->p_osmt = p_osmt;
+	user.comp_mask = IB_PKEY_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_PKEY_TBL_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = sm_key;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007E: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007F: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get SwitchInfo record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_sw_info_rec_by_lid(IN osmtest_t * const p_osmt,
+			       IN ib_net16_t const lid,
+			       IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_switch_info_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting SwitchInfo record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	p_context->p_osmt = p_osmt;
+	if (lid)
+		user.comp_mask = IB_SWIR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_SWITCH_INFO_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006C: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006D: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get LFT record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_lft_rec_by_lid(IN osmtest_t * const p_osmt,
+			   IN ib_net16_t const lid,
+			   IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_lft_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting LFT record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	p_context->p_osmt = p_osmt;
+	if (lid)
+		user.comp_mask = IB_LFTR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_LFT_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008A: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008B: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ * Get MFT record by LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_mft_rec_by_lid(IN osmtest_t * const p_osmt,
+			   IN ib_net16_t const lid,
+			   IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_mft_record_t record;
+	ib_mad_t *p_mad;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Getting MFT record for LID 0x%02X\n", cl_ntoh16(lid));
+
+	/*
+	 * Do a blocking query for this record in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+	p_context->p_osmt = p_osmt;
+	if (lid)
+		user.comp_mask = IB_MFTR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_MFT_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009B: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009C: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_sminfo_record_request(IN osmtest_t * const p_osmt,
+			      IN uint8_t method,
+			      IN void *p_options,
+			      IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_sminfo_record_t record;
+	ib_mad_t *p_mad;
+	osmtest_sm_info_rec_t *p_sm_info_opt;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Do a blocking query for these records in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	p_context->p_osmt = p_osmt;
+	user.attr_id = IB_MAD_ATTR_SMINFO_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	p_sm_info_opt = p_options;
+	if (p_sm_info_opt->sm_guid != 0) {
+		record.sm_info.guid = p_sm_info_opt->sm_guid;
+		user.comp_mask |= IB_SMIR_COMPMASK_GUID;
+	}
+	if (p_sm_info_opt->lid != 0) {
+		record.lid = p_sm_info_opt->lid;
+		user.comp_mask |= IB_SMIR_COMPMASK_LID;
+	}
+	if (p_sm_info_opt->priority != 0) {
+		record.sm_info.pri_state =
+		    (p_sm_info_opt->priority & 0x0F) << 4;
+		user.comp_mask |= IB_SMIR_COMPMASK_PRIORITY;
+	}
+	if (p_sm_info_opt->sm_state != 0) {
+		record.sm_info.pri_state |= p_sm_info_opt->sm_state & 0x0F;
+		user.comp_mask |= IB_SMIR_COMPMASK_SMSTATE;
+	}
+
+	user.method = method;
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008C: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		if (status != IB_INVALID_PARAMETER) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008D: "
+				"ib_query failed (%s)\n",
+				ib_get_err_str(status));
+		}
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_informinfo_request(IN osmtest_t * const p_osmt,
+			   IN ib_net16_t attr_id,
+			   IN uint8_t method,
+			   IN void *p_options,
+			   IN OUT osmtest_req_context_t * const p_context)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_inform_info_t rec;
+	ib_inform_info_record_t record;
+	ib_mad_t *p_mad;
+	osmtest_inform_info_t *p_inform_info_opt;
+	osmtest_inform_info_rec_t *p_inform_info_rec_opt;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Do a blocking query for these records in the subnet.
+	 * The result is returned in the result field of the caller's
+	 * context structure.
+	 *
+	 * The query structures are locals.
+	 */
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&rec, 0, sizeof(rec));
+	memset(&record, 0, sizeof(record));
+
+	p_context->p_osmt = p_osmt;
+	user.attr_id = attr_id;
+	if (attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD) {
+		user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+		p_inform_info_rec_opt = p_options;
+		if (p_inform_info_rec_opt->subscriber_gid.unicast.prefix != 0 &&
+		    p_inform_info_rec_opt->subscriber_gid.unicast.
+		    interface_id != 0) {
+			record.subscriber_gid =
+			    p_inform_info_rec_opt->subscriber_gid;
+			user.comp_mask = IB_IIR_COMPMASK_SUBSCRIBERGID;
+		}
+		record.subscriber_enum =
+		    cl_hton16(p_inform_info_rec_opt->subscriber_enum);
+		user.comp_mask |= IB_IIR_COMPMASK_ENUM;
+		user.p_attr = &record;
+	} else {
+		user.attr_offset = cl_ntoh16((uint16_t) (sizeof(rec) >> 3));
+		/* comp mask bits below are for InformInfoRecord rather than InformInfo */
+		/* as currently no comp mask bits defined for InformInfo!!! */
+		user.comp_mask = IB_IIR_COMPMASK_SUBSCRIBE;
+		p_inform_info_opt = p_options;
+		rec.subscribe = (uint8_t) p_inform_info_opt->subscribe;
+		if (p_inform_info_opt->qpn) {
+			rec.g_or_v.generic.qpn_resp_time_val =
+			    cl_hton32(p_inform_info_opt->qpn << 8);
+			user.comp_mask |= IB_IIR_COMPMASK_QPN;
+		}
+		if (p_inform_info_opt->trap) {
+			rec.g_or_v.generic.trap_num =
+			    cl_hton16(p_inform_info_opt->trap);
+			user.comp_mask |= IB_IIR_COMPMASK_TRAPNUMB;
+		}
+		user.p_attr = &rec;
+	}
+	user.method = method;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = p_context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008E: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = p_context->result.status;
+
+	if (status != IB_SUCCESS) {
+		if (status != IB_INVALID_PARAMETER) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008F: "
+				"ib_query failed (%s)\n",
+				ib_get_err_str(status));
+		}
+		if (status == IB_REMOTE_ERROR) {
+			p_mad =
+			    osm_madw_get_mad_ptr(p_context->result.
+						 p_result_madw);
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(p_mad));
+
+			status =
+			    (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK);
+		}
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_rec_lid_pair(IN osmtest_t * const p_osmt,
+					  IN path_t * const p_path)
+{
+	osmtest_req_context_t context;
+	const ib_path_rec_t *p_rec;
+	cl_status_t status = IB_SUCCESS;
+	size_t num_recs;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	status = osmtest_get_path_rec_by_lid_pair(p_osmt,
+						  p_path->rec.slid,
+						  p_path->rec.dlid, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0102: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+	if (num_recs != 1) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0103: "
+			"Too many records. Expected 1, received %zu\n",
+			num_recs);
+
+		status = IB_ERROR;
+	} else {
+		p_rec =
+		    osmv_get_query_path_rec(context.result.p_result_madw, 0);
+
+		status = osmtest_validate_path_data(p_osmt, p_path, p_rec);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0104: "
+				"osmtest_validate_path_data failed (%s)\n",
+				ib_get_err_str(status));
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_node_rec_lid(IN osmtest_t * const p_osmt,
+				     IN ib_net16_t const lid,
+				     IN node_t * const p_node)
+{
+	cl_status_t status = IB_SUCCESS;
+	osmv_user_query_t user;
+	osmv_query_req_t req;
+	ib_node_record_t record;
+
+	osmtest_req_context_t context;
+	const ib_node_record_t *p_rec;
+	int num_recs, i;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Getting NodeRecord for node with LID 0x%X\n", cl_ntoh16(lid));
+
+	memset(&context, 0, sizeof(context));
+	memset(&req, 0, sizeof(req));
+	memset(&user, 0, sizeof(user));
+	memset(&record, 0, sizeof(record));
+
+	record.lid = lid;
+
+	context.p_osmt = p_osmt;
+	user.comp_mask = IB_NR_COMPMASK_LID;
+	user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+	user.attr_offset = cl_ntoh16((uint16_t) (sizeof(record) >> 3));
+	user.p_attr = &record;
+
+	req.query_type = OSMV_QUERY_USER_DEFINED;
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+	req.p_query_input = &user;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0105: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0106: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Received %d nodes\n", num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_node_rec(context.result.p_result_madw, i);
+
+		status = osmtest_validate_node_rec(p_osmt, p_rec);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0107: "
+				"osmtest_validate_node_data failed (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_port_rec_lid(IN osmtest_t * const p_osmt,
+				     IN port_t * const p_port)
+{
+	osmtest_req_context_t context;
+
+	const ib_portinfo_record_t *p_rec;
+	cl_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&context, 0, sizeof(context));
+
+	context.p_osmt = p_osmt;
+	osmtest_get_port_rec_by_num(p_osmt,
+				    p_port->rec.lid,
+				    p_port->rec.port_num, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0108: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		goto Exit;
+	}
+
+	/* we should have got exactly one port */
+	p_rec = osmv_get_query_portinfo_rec(context.result.p_result_madw, 0);
+	status = osmtest_validate_port_rec(p_osmt, p_rec);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0109: "
+			"osmtest_validate_port_data failed (%s)\n",
+			ib_get_err_str(status));
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_rec_guid_pair(IN osmtest_t * const p_osmt,
+					   IN const osmv_guid_pair_t *
+					   const p_pair)
+{
+	osmtest_req_context_t context;
+	const ib_path_rec_t *p_rec;
+	cl_status_t status = IB_SUCCESS;
+	size_t num_recs;
+	osmv_query_req_t req;
+	uint32_t i;
+	boolean_t got_error = FALSE;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	memset(&req, 0, sizeof(req));
+	memset(&context, 0, sizeof(context));
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+		"\n\t\t\t\tChecking src 0x%016" PRIx64
+		" to dest 0x%016" PRIx64 "\n",
+		cl_ntoh64(p_pair->src_guid), cl_ntoh64(p_pair->dest_guid));
+
+	context.p_osmt = p_osmt;
+
+	req.timeout_ms = p_osmt->opt.transaction_timeout;
+	req.retry_cnt = p_osmt->opt.retry_count;
+	req.flags = OSM_SA_FLAGS_SYNC;
+	req.query_context = &context;
+	req.pfn_query_cb = osmtest_query_res_cb;
+
+	req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+	req.p_query_input = p_pair;
+	req.sm_key = 0;
+
+	status = osmv_query_sa(p_osmt->h_bind, &req);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0110: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+		goto Exit;
+	}
+
+	status = context.result.status;
+
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0111: "
+			"ib_query failed (%s)\n", ib_get_err_str(status));
+
+		if (status == IB_REMOTE_ERROR) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				"Remote error = %s\n",
+				ib_get_mad_status_str(osm_madw_get_mad_ptr
+						      (context.result.
+						       p_result_madw)));
+		}
+		goto Exit;
+	}
+
+	num_recs = context.result.result_cnt;
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "%zu records\n", num_recs);
+
+	for (i = 0; i < num_recs; i++) {
+		p_rec =
+		    osmv_get_query_path_rec(context.result.p_result_madw, i);
+
+		/*
+		 * Make sure the GUID values are correct
+		 */
+		if (p_rec->dgid.unicast.interface_id != p_pair->dest_guid) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0112: "
+				"Destination GUID mismatch\n"
+				"\t\t\t\texpected 0x%016" PRIx64
+				", received 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_pair->dest_guid),
+				cl_ntoh64(p_rec->dgid.unicast.interface_id));
+			got_error = TRUE;
+		}
+
+		if (p_rec->sgid.unicast.interface_id != p_pair->src_guid) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0113: "
+				"Source GUID mismatch\n"
+				"\t\t\t\texpected 0x%016" PRIx64
+				", received 0x%016" PRIx64 ".\n",
+				cl_ntoh64(p_pair->src_guid),
+				cl_ntoh64(p_rec->sgid.unicast.interface_id));
+			got_error = TRUE;
+		}
+
+		status = osmtest_validate_path_rec(p_osmt, p_rec);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0114: "
+				"osmtest_validate_path_rec failed (%s)\n",
+				ib_get_err_str(status));
+			got_error = TRUE;
+		}
+		if (got_error || (status != IB_SUCCESS)) {
+			osm_dump_path_record(&p_osmt->log, p_rec,
+					     OSM_LOG_VERBOSE);
+			if (status == IB_SUCCESS)
+				status = IB_ERROR;
+			goto Exit;
+		}
+	}
+
+Exit:
+	/*
+	 * Return the IB query MAD to the pool as necessary.
+	 */
+	if (context.result.p_result_madw != NULL) {
+		osm_mad_pool_put(&p_osmt->mad_pool,
+				 context.result.p_result_madw);
+		context.result.p_result_madw = NULL;
+	}
+
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_recs(IN osmtest_t * const p_osmt)
+{
+	path_t *p_path;
+	cl_status_t status = IB_SUCCESS;
+	const cl_qmap_t *p_path_tbl;
+/* We skip node to node path record validation since it might contains
+   NONEXISTENT PATHS, i.e. when using UPDN */
+	osmv_guid_pair_t guid_pair;
+	uint16_t cnt;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Validating individual path record queries\n");
+	p_path_tbl = &p_osmt->exp_subn.path_tbl;
+
+	osmtest_prepare_db(p_osmt);
+
+	/*
+	 * Walk the list of all path records, and ask for each one
+	 * specifically.  Make sure we get it.
+	 */
+	cnt = 0;
+	p_path = (path_t *) cl_qmap_head(p_path_tbl);
+	while (p_path != (path_t *) cl_qmap_end(p_path_tbl)) {
+		status =
+		    osmtest_validate_single_path_rec_lid_pair(p_osmt, p_path);
+		if (status != IB_SUCCESS)
+			goto Exit;
+		cnt++;
+		p_path = (path_t *) cl_qmap_next(&p_path->map_item);
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Total of %u path records validated using LID based query\n",
+		cnt);
+
+	status = osmtest_check_missing_paths(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0115: "
+			"osmtest_check_missing_paths failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	/*
+	 * Do the whole thing again with port GUID pairs.
+	 * Note that multiple path records may be returned
+	 * for each guid pair if LMC > 0.
+	 */
+	osmtest_prepare_db(p_osmt);
+	cnt = 0;
+	p_path = (path_t *) cl_qmap_head(p_path_tbl);
+	while (p_path != (path_t *) cl_qmap_end(p_path_tbl)) {
+		guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id;
+		guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id;
+		status = osmtest_validate_single_path_rec_guid_pair(p_osmt,
+								    &guid_pair);
+		if (status != IB_SUCCESS)
+			goto Exit;
+		cnt++;
+		p_path = (path_t *) cl_qmap_next(&p_path->map_item);
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Total of %u path records validated using GUID based query\n",
+		cnt);
+
+	status = osmtest_check_missing_paths(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0116: "
+			"osmtest_check_missing_paths failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_node_recs(IN osmtest_t * const p_osmt)
+{
+	node_t *p_node;
+	cl_status_t status = IB_SUCCESS;
+	const cl_qmap_t *p_node_lid_tbl;
+	uint16_t cnt = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+	osmtest_prepare_db(p_osmt);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Validating individual node record queries\n");
+
+	/*
+	 * Walk the list of all node records, and ask for each one
+	 * specifically.  Make sure we get it.
+	 */
+	p_node = (node_t *) cl_qmap_head(p_node_lid_tbl);
+	while (p_node != (node_t *) cl_qmap_end(p_node_lid_tbl)) {
+		status = osmtest_validate_single_node_rec_lid(p_osmt,
+							      (ib_net16_t)
+							      cl_qmap_key((cl_map_item_t *) p_node), p_node);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 011A: "
+				"osmtest_validate_single_node_rec_lid (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		cnt++;
+		p_node = (node_t *) cl_qmap_next(&p_node->map_item);
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Total of %u node records validated\n", cnt);
+
+	status = osmtest_check_missing_nodes(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0117: "
+			"osmtest_check_missing_nodes (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_port_recs(IN osmtest_t * const p_osmt)
+{
+	port_t *p_port;
+	cl_status_t status = IB_SUCCESS;
+	const cl_qmap_t *p_port_key_tbl;
+	uint16_t cnt = 0;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+	osmtest_prepare_db(p_osmt);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Validating individual port record queries\n");
+
+	/*
+	 * Walk the list of all port records, and ask for each one
+	 * specifically.  Make sure we get it.
+	 */
+	p_port = (port_t *) cl_qmap_head(p_port_key_tbl);
+	while (p_port != (port_t *) cl_qmap_end(p_port_key_tbl)) {
+		status = osmtest_validate_single_port_rec_lid(p_osmt, p_port);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 011B: "
+				"osmtest_validate_single_port_rec_lid (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+		cnt++;
+		p_port = (port_t *) cl_qmap_next(&p_port->map_item);
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
+		"Total of %u port records validated\n", cnt);
+
+	status = osmtest_check_missing_ports(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0118: "
+			"osmtest_check_missing_paths failed (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_validate_against_db(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	ib_gid_t portgid, mgid;
+	osmtest_sm_info_rec_t sm_info_rec_opt;
+	osmtest_inform_info_t inform_info_opt;
+	osmtest_inform_info_rec_t inform_info_rec_opt;
+#ifdef VENDOR_RMPP_SUPPORT
+	ib_net64_t sm_key;
+	ib_net16_t test_lid;
+	uint8_t lmc;
+	osmtest_req_context_t context;
+#ifdef DUAL_SIDED_RMPP
+	osmv_multipath_req_t request;
+#endif
+	uint8_t i;
+#endif
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+#ifdef VENDOR_RMPP_SUPPORT
+	status = osmtest_validate_all_node_recs(p_osmt);
+	if (status != IB_SUCCESS)
+		goto Exit;
+#endif
+
+	status = osmtest_validate_single_node_recs(p_osmt);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Exercise SA PathRecord multicast destination code */
+	memset(&context, 0, sizeof(context));
+	ib_gid_set_default(&portgid, portguid);
+	/* Set IPoIB broadcast MGID */
+	mgid.unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);
+	mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);
+	/* Can't check status as don't know whether port is running IPoIB */
+	osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context);
+
+	/* Other link local unicast PathRecord */
+	memset(&context, 0, sizeof(context));
+	ib_gid_set_default(&portgid, portguid);
+	ib_gid_set_default(&mgid, portguid);
+	mgid.raw[7] = 0xff;	/* not default GID prefix */
+	/* Can't check status as don't know whether ??? */
+	osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context);
+
+	/* Off subnet (site local) unicast PathRecord */
+	memset(&context, 0, sizeof(context));
+	ib_gid_set_default(&portgid, portguid);
+	ib_gid_set_default(&mgid, portguid);
+	mgid.raw[1] = 0xc0;	/* site local */
+	/* Can't check status as don't know whether ??? */
+	osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context);
+
+	/* More than link local scope multicast PathRecord */
+	memset(&context, 0, sizeof(context));
+	ib_gid_set_default(&portgid, portguid);
+	/* Set IPoIB broadcast MGID */
+	mgid.unicast.prefix = CL_HTON64(0xff15401bffff0000ULL);	/* site local */
+	mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);
+	/* Can't check status as don't know whether port is running IPoIB */
+	osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context);
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+	memset(&context, 0, sizeof(context));
+	memset(&request, 0, sizeof(request));
+	request.comp_mask =
+	    IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;
+	request.sgid_count = 1;
+	request.dgid_count = 1;
+	ib_gid_set_default(&request.gids[0], portguid);
+	ib_gid_set_default(&request.gids[1], portguid);
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+	memset(&request, 0, sizeof(request));
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Got error %s\n", ib_get_err_str(status));
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	memset(&context, 0, sizeof(context));
+	memset(&request, 0, sizeof(request));
+	request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT;
+	request.sgid_count = 1;
+	ib_gid_set_default(&request.gids[0], portguid);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Got error %s\n", ib_get_err_str(status));
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	memset(&context, 0, sizeof(context));
+	memset(&request, 0, sizeof(request));
+	request.comp_mask =
+	    IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;
+	request.sgid_count = 1;
+	request.dgid_count = 1;
+	ib_gid_set_default(&request.gids[0], portguid);
+	/* Set IPoIB broadcast MGID as DGID */
+	request.gids[1].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);
+	request.gids[1].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Got error %s\n", ib_get_err_str(status));
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	memset(&context, 0, sizeof(context));
+	request.comp_mask =
+	    IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;
+	request.sgid_count = 1;
+	request.dgid_count = 1;
+	/* Set IPoIB broadcast MGID as SGID */
+	request.gids[0].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);
+	request.gids[0].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);
+	ib_gid_set_default(&request.gids[1], portguid);
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Got error %s\n", ib_get_err_str(status));
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	memset(&context, 0, sizeof(context));
+	memset(&request, 0, sizeof(request));
+	request.comp_mask =
+	    IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT |
+	    IB_MPR_COMPMASK_NUMBPATH;
+	request.sgid_count = 2;
+	request.dgid_count = 2;
+	request.num_path = 2;
+	ib_gid_set_default(&request.gids[0], portguid);
+	ib_gid_set_default(&request.gids[1], portguid);
+	ib_gid_set_default(&request.gids[2], portguid);
+	ib_gid_set_default(&request.gids[3], portguid);
+	status = osmtest_get_multipath_rec(p_osmt, &request, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+#endif
+
+#ifdef VENDOR_RMPP_SUPPORT
+	/* GUIDInfoRecords */
+	status = osmtest_validate_all_guidinfo_recs(p_osmt);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* If LMC > 0, test non base LID SA PortInfoRecord request */
+	status =
+	    osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (lmc != 0) {
+		status =
+		    osmtest_get_local_port_lmc(p_osmt,
+					       p_osmt->local_port.lid + 1,
+					       NULL);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	status = osmtest_get_local_port_lmc(p_osmt, 0xffff, NULL);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	test_lid = cl_ntoh16(p_osmt->local_port.lid);
+
+	/* More GUIDInfo Record tests */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_guidinfo_rec_by_lid(p_osmt, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_guidinfo_rec_by_lid(p_osmt, 0xffff, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Some PKeyTable Record tests */
+	sm_key = OSM_DEFAULT_SM_KEY;
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, sm_key, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n");
+	status = osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, 0, &context);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+			"Got error %s\n", ib_get_err_str(status));
+	}
+	OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n");
+
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_get_pkeytbl_rec_by_lid(p_osmt, 0xffff, sm_key, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* SwitchInfo Record tests */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_sw_info_rec_by_lid(p_osmt, 0, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_sw_info_rec_by_lid(p_osmt, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* LFT Record tests */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_lft_rec_by_lid(p_osmt, 0, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_lft_rec_by_lid(p_osmt, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* MFT Record tests */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_mft_rec_by_lid(p_osmt, 0, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_mft_rec_by_lid(p_osmt, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Some LinkRecord tests */
+	/* FromLID */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_link_rec_by_lid(p_osmt, test_lid, 0, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* ToLID */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_link_rec_by_lid(p_osmt, 0, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* FromLID & ToLID */
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_get_link_rec_by_lid(p_osmt, test_lid, test_lid, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* NodeRecord test */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_get_node_rec_by_lid(p_osmt, 0xffff, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* SMInfoRecord tests */
+	memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_SET,
+					       &sm_info_rec_opt, &context);
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n");
+	}
+
+	memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE,
+					       &sm_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+	sm_info_rec_opt.lid = test_lid;	/* local LID */
+	memset(&context, 0, sizeof(context));
+	status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE,
+					       &sm_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (portguid != 0) {
+		memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+		sm_info_rec_opt.sm_guid = portguid;	/* local GUID */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_sminfo_record_request(p_osmt,
+						  IB_MAD_METHOD_GETTABLE,
+						  &sm_info_rec_opt, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	for (i = 1; i < 16; i++) {
+		memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+		sm_info_rec_opt.priority = i;
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_sminfo_record_request(p_osmt,
+						  IB_MAD_METHOD_GETTABLE,
+						  &sm_info_rec_opt, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	for (i = 1; i < 4; i++) {
+		memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt));
+		sm_info_rec_opt.sm_state = i;
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_sminfo_record_request(p_osmt,
+						  IB_MAD_METHOD_GETTABLE,
+						  &sm_info_rec_opt, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	/* InformInfoRecord tests */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a BAD - Set Unsubscribe request\n");
+	memset(&inform_info_opt, 0, sizeof(inform_info_opt));
+	memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_SET, &inform_info_rec_opt,
+				       &context);
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfoRecord "
+			"IS EXPECTED ERROR ^^^^\n");
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - Empty GetTable request\n");
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* InformInfo tests */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a BAD - Empty Get request "
+		"(should fail with NO_RECORDS)\n");
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_GET, &inform_info_opt,
+					    &context);
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfo "
+			"IS EXPECTED ERROR ^^^^\n");
+	}
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a BAD - Set Unsubscribe request\n");
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status == IB_SUCCESS) {
+		status = IB_ERROR;
+		goto Exit;
+	} else {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfo UnSubscribe "
+			"IS EXPECTED ERROR ^^^^\n");
+	}
+
+	/* Now subscribe */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a Good - Set Subscribe request\n");
+	inform_info_opt.subscribe = TRUE;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Now unsubscribe (QPN needs to be 1 to work) */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a Good - Set Unsubscribe request\n");
+	inform_info_opt.subscribe = FALSE;
+	inform_info_opt.qpn = 1;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Now subscribe again */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a Good - Set Subscribe request\n");
+	inform_info_opt.subscribe = TRUE;
+	inform_info_opt.qpn = 1;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Subscribe over existing subscription */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a Good - Set Subscribe (again) request\n");
+	inform_info_opt.qpn = 0;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* More InformInfoRecord tests */
+	/* RID lookup (with currently invalid enum) */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable by GID\n");
+	ib_gid_set_default(&inform_info_rec_opt.subscriber_gid,
+			   p_osmt->local_port.port_guid);
+	inform_info_rec_opt.subscriber_enum = 1;
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Enum lookup */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable (subscriber_enum == 0) request\n");
+	inform_info_rec_opt.subscriber_enum = 0;
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Get all InformInfoRecords */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable (ALL records) request\n");
+	memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Another subscription */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending another Good - Set Subscribe (again) request\n");
+	inform_info_opt.qpn = 0;
+	inform_info_opt.trap = 0x1234;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET, &inform_info_opt,
+					    &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Get all InformInfoRecords again */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable (ALL records) request\n");
+	memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Cleanup subscriptions before further testing */
+	/* Does order of deletion matter ? Test this !!! */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo "
+		"Sending a Good - Set (cleanup) request\n");
+	inform_info_opt.subscribe = FALSE;
+	inform_info_opt.qpn = 1;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET,
+					    &inform_info_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Get all InformInfoRecords again */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable (ALL records) request\n");
+	memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo"
+		"Sending a Good - Set (cleanup) request\n");
+	inform_info_opt.subscribe = FALSE;
+	inform_info_opt.qpn = 1;
+	inform_info_opt.trap = 0;
+	memset(&context, 0, sizeof(context));
+	status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO,
+					    IB_MAD_METHOD_SET,
+					    &inform_info_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	/* Get all InformInfoRecords a final time */
+	OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord "
+		"Sending a Good - GetTable (ALL records) request\n");
+	memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt));
+	memset(&context, 0, sizeof(context));
+	status =
+	    osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD,
+				       IB_MAD_METHOD_GETTABLE,
+				       &inform_info_rec_opt, &context);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (lmc != 0) {
+		test_lid = cl_ntoh16(p_osmt->local_port.lid + 1);
+
+		/* Another GUIDInfo Record test */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_guidinfo_rec_by_lid(p_osmt, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* Another PKeyTable Record test */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, sm_key,
+						   &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* Another SwitchInfo Record test */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_sw_info_rec_by_lid(p_osmt, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* Another LFT Record test */
+		memset(&context, 0, sizeof(context));
+		status = osmtest_get_lft_rec_by_lid(p_osmt, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* Another MFT Record test */
+		memset(&context, 0, sizeof(context));
+		status = osmtest_get_mft_rec_by_lid(p_osmt, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* More LinkRecord tests */
+		/* FromLID */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_link_rec_by_lid(p_osmt, test_lid, 0, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* ToLID */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_link_rec_by_lid(p_osmt, 0, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		/* Another NodeRecord test */
+		memset(&context, 0, sizeof(context));
+		status =
+		    osmtest_get_node_rec_by_lid(p_osmt, test_lid, &context);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+	/* PathRecords */
+	if (!p_osmt->opt.ignore_path_records) {
+		status = osmtest_validate_all_path_recs(p_osmt);
+		if (status != IB_SUCCESS)
+			goto Exit;
+
+		if (lmc != 0) {
+			memset(&context, 0, sizeof(context));
+			status =
+			    osmtest_get_path_rec_by_lid_pair(p_osmt, test_lid,
+							     test_lid,
+							     &context);
+			if (status != IB_SUCCESS)
+				goto Exit;
+
+			memset(&context, 0, sizeof(context));
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				EXPECTING_ERRORS_START "\n");
+			status =
+			    osmtest_get_path_rec_by_lid_pair(p_osmt, 0xffff,
+							     0xffff, &context);
+			if (status != IB_SUCCESS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+					"Got error %s\n",
+					ib_get_err_str(status));
+			}
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				EXPECTING_ERRORS_END "\n");
+
+			if (status == IB_SUCCESS) {
+				status = IB_ERROR;
+				goto Exit;
+			}
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				EXPECTING_ERRORS_START "\n");
+
+			status =
+			    osmtest_get_path_rec_by_lid_pair(p_osmt, test_lid,
+							     0xffff, &context);
+			if (status != IB_SUCCESS) {
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+					"Got error %s\n",
+					ib_get_err_str(status));
+			}
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+				EXPECTING_ERRORS_END "\n");
+
+			if (status == IB_SUCCESS) {
+				status = IB_ERROR;
+				goto Exit;
+			}
+		}
+	}
+#endif
+
+	status = osmtest_validate_single_port_recs(p_osmt);
+	if (status != IB_SUCCESS)
+		goto Exit;
+
+	if (!p_osmt->opt.ignore_path_records) {
+		status = osmtest_validate_single_path_recs(p_osmt);
+		if (status != IB_SUCCESS)
+			goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const osmtest_token_t *str_get_token(IN char *const p_str)
+{
+	const osmtest_token_t *p_tok;
+	uint32_t index = 0;
+
+	p_tok = &token_array[index];
+
+	while (p_tok->val != OSMTEST_TOKEN_UNKNOWN) {
+		if (strnicmp(p_str, p_tok->str, p_tok->str_size) == 0)
+			return (p_tok);
+
+		p_tok = &token_array[++index];
+	}
+
+	return (NULL);
+}
+
+/**********************************************************************
+   Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static boolean_t
+str_skip_white(IN char line[], IN OUT uint32_t * const p_offset)
+{
+	while (((line[*p_offset] == '\t') ||
+		(line[*p_offset] == ' ')) &&
+	       (line[*p_offset] != '\n') && (line[*p_offset] != '\0')) {
+		++*p_offset;
+	}
+
+	if ((line[*p_offset] == '\n') || (line[*p_offset] == '\0'))
+		return (FALSE);
+	else
+		return (TRUE);
+}
+
+/**********************************************************************
+   Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static void str_skip_token(IN char line[], IN OUT uint32_t * const p_offset)
+{
+	while ((line[*p_offset] != '\t') &&
+	       (line[*p_offset] != ' ') && (line[*p_offset] != '\0')) {
+		++*p_offset;
+	}
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_node(IN osmtest_t * const p_osmt,
+		   IN FILE * const fh, IN OUT uint32_t * const p_line_num)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint32_t offset;
+	char line[OSMTEST_MAX_LINE_LEN];
+	boolean_t done = FALSE;
+	node_t *p_node;
+	node_t *p_guid_node;
+	const osmtest_token_t *p_tok;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_node = node_new();
+	CL_ASSERT(p_node != NULL);
+
+	/*
+	 * Parse the inventory file and create the database.
+	 */
+	while (!done) {
+		if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) {
+			/*
+			 * End of file in the middle of a definition.
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0119: "
+				"Unexpected end of file\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		++*p_line_num;
+
+		/*
+		 * Skip whitespace
+		 */
+		offset = 0;
+		if (!str_skip_white(line, &offset))
+			continue;	/* whole line was whitespace */
+
+		p_tok = str_get_token(&line[offset]);
+		if (p_tok == NULL) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0120: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			continue;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+			"Found '%s' (line %u)\n", p_tok->str, *p_line_num);
+
+		str_skip_token(line, &offset);
+
+		switch (p_tok->val) {
+		case OSMTEST_TOKEN_COMMENT:
+			break;
+
+		case OSMTEST_TOKEN_LID:
+			p_node->comp.lid = 0xFFFF;
+			p_node->rec.lid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lid = 0x%X\n",
+				cl_ntoh16(p_node->rec.lid));
+			break;
+
+		case OSMTEST_TOKEN_BASE_VERSION:
+			p_node->comp.node_info.base_version = 0xFF;
+			p_node->rec.node_info.base_version =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"base_version = 0x%X\n",
+				p_node->rec.node_info.base_version);
+			break;
+
+		case OSMTEST_TOKEN_CLASS_VERSION:
+			p_node->comp.node_info.class_version = 0xFF;
+			p_node->rec.node_info.class_version =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"class_version = 0x%X\n",
+				p_node->rec.node_info.class_version);
+			break;
+
+		case OSMTEST_TOKEN_NODE_TYPE:
+			p_node->comp.node_info.node_type = 0xFF;
+			p_node->rec.node_info.node_type =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"node_type = 0x%X\n",
+				p_node->rec.node_info.node_type);
+			break;
+
+		case OSMTEST_TOKEN_NUM_PORTS:
+			p_node->comp.node_info.num_ports = 0xFF;
+			p_node->rec.node_info.num_ports =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"num_ports = 0x%X\n",
+				p_node->rec.node_info.num_ports);
+			break;
+
+		case OSMTEST_TOKEN_SYS_GUID:
+			p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL;
+			p_node->rec.node_info.sys_guid =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"sys_guid = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_node->rec.node_info.sys_guid));
+			break;
+
+		case OSMTEST_TOKEN_NODE_GUID:
+			p_node->comp.node_info.node_guid =
+			    0xFFFFFFFFFFFFFFFFULL;
+			p_node->rec.node_info.node_guid =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"node_guid = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_node->rec.node_info.node_guid));
+			break;
+
+		case OSMTEST_TOKEN_PORT_GUID:
+			p_node->comp.node_info.port_guid =
+			    0xFFFFFFFFFFFFFFFFULL;
+			p_node->rec.node_info.port_guid =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"port_guid = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_node->rec.node_info.port_guid));
+			break;
+
+		case OSMTEST_TOKEN_PARTITION_CAP:
+			p_node->comp.node_info.partition_cap = 0xFFFF;
+			p_node->rec.node_info.partition_cap =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"partition_cap = 0x%X\n",
+				cl_ntoh16(p_node->rec.node_info.partition_cap));
+			break;
+
+		case OSMTEST_TOKEN_DEVICE_ID:
+			p_node->comp.node_info.device_id = 0xFFFF;
+			p_node->rec.node_info.device_id = cl_hton16((uint16_t)
+								    strtoul
+								    (&line
+								     [offset],
+								     NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"device_id = 0x%X\n",
+				cl_ntoh16(p_node->rec.node_info.device_id));
+			break;
+
+		case OSMTEST_TOKEN_REVISION:
+			p_node->comp.node_info.revision = 0xFFFFFFFF;
+			p_node->rec.node_info.revision =
+			    cl_hton32(strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"revision = 0x%X\n",
+				cl_ntoh32(p_node->rec.node_info.revision));
+			break;
+
+		case OSMTEST_TOKEN_PORT_NUM:
+			p_node->comp.node_info.port_num_vendor_id |=
+			    IB_NODE_INFO_PORT_NUM_MASK;
+			p_node->rec.node_info.port_num_vendor_id |=
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"local_port_num = 0x%X\n",
+				ib_node_info_get_local_port_num
+				(&p_node->rec.node_info));
+			break;
+
+		case OSMTEST_TOKEN_VENDOR_ID:
+			p_node->comp.node_info.port_num_vendor_id |=
+			    IB_NODE_INFO_VEND_ID_MASK;
+			p_node->rec.node_info.port_num_vendor_id |=
+			    cl_hton32(strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vendor_id = 0x%X\n",
+				cl_ntoh32(ib_node_info_get_vendor_id
+					  (&p_node->rec.node_info)));
+			break;
+
+		case OSMTEST_TOKEN_END:
+			done = TRUE;
+			break;
+
+		default:
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0121: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+
+			break;
+		}
+	}
+
+	/*
+	 * Make sure the user specified enough information, then
+	 * add this object to the database.
+	 */
+	if (p_node->comp.lid == 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0122: "
+			"LID must be specified for defined nodes\n");
+		node_delete(p_node);
+		goto Exit;
+	}
+
+	cl_qmap_insert(&p_osmt->exp_subn.node_lid_tbl,
+		       p_node->rec.lid, &p_node->map_item);
+
+	p_guid_node = node_new();
+	CL_ASSERT(p_node != NULL);
+
+	*p_guid_node = *p_node;
+
+	cl_qmap_insert(&p_osmt->exp_subn.node_guid_tbl,
+		       p_guid_node->rec.node_info.node_guid,
+		       &p_guid_node->map_item);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_port(IN osmtest_t * const p_osmt,
+		   IN FILE * const fh, IN OUT uint32_t * const p_line_num)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint32_t offset;
+	char line[OSMTEST_MAX_LINE_LEN];
+	boolean_t done = FALSE;
+	port_t *p_port;
+	const osmtest_token_t *p_tok;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_port = port_new();
+	CL_ASSERT(p_port != NULL);
+
+	/*
+	 * Parse the inventory file and create the database.
+	 */
+	while (!done) {
+		if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) {
+			/*
+			 * End of file in the middle of a definition.
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0123: "
+				"Unexpected end of file\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		++*p_line_num;
+
+		/*
+		 * Skip whitespace
+		 */
+		offset = 0;
+		if (!str_skip_white(line, &offset))
+			continue;	/* whole line was whitespace */
+
+		p_tok = str_get_token(&line[offset]);
+		if (p_tok == NULL) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0124: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			continue;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+			"Found '%s' (line %u)\n", p_tok->str, *p_line_num);
+
+		str_skip_token(line, &offset);
+
+		switch (p_tok->val) {
+		case OSMTEST_TOKEN_COMMENT:
+			break;
+
+		case OSMTEST_TOKEN_LID:
+			p_port->comp.lid = 0xFFFF;
+			p_port->rec.lid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lid = 0x%X\n",
+				cl_ntoh16(p_port->rec.lid));
+			break;
+
+		case OSMTEST_TOKEN_PORT_NUM:
+			p_port->comp.port_num = 0xFF;
+			p_port->rec.port_num =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"port_num = 0x%u\n", p_port->rec.port_num);
+			break;
+
+		case OSMTEST_TOKEN_MKEY:
+			p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL;
+			p_port->rec.port_info.m_key =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"m_key = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_port->rec.port_info.m_key));
+			break;
+
+		case OSMTEST_TOKEN_SUBN_PREF:
+			p_port->comp.port_info.subnet_prefix =
+			    0xFFFFFFFFFFFFFFFFULL;
+			p_port->rec.port_info.subnet_prefix =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"subnet_prefix = 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_port->rec.port_info.subnet_prefix));
+			break;
+
+		case OSMTEST_TOKEN_BASE_LID:
+			p_port->comp.port_info.base_lid = 0xFFFF;
+			p_port->rec.port_info.base_lid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"base_lid = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.base_lid));
+			break;
+
+		case OSMTEST_TOKEN_SM_BASE_LID:
+			p_port->comp.port_info.master_sm_base_lid = 0xFFFF;
+			p_port->rec.port_info.master_sm_base_lid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"master_sm_base_lid = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.master_sm_base_lid));
+			break;
+
+		case OSMTEST_TOKEN_CAP_MASK:
+			p_port->comp.port_info.capability_mask = 0xFFFFFFFF;
+			p_port->rec.port_info.capability_mask =
+			    cl_hton32((uint32_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"capability_mask = 0x%X\n",
+				cl_ntoh32(p_port->rec.port_info.capability_mask));
+			break;
+
+		case OSMTEST_TOKEN_DIAG_CODE:
+			p_port->comp.port_info.diag_code = 0xFFFF;
+			p_port->rec.port_info.diag_code =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"diag_code = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.diag_code));
+			break;
+
+		case OSMTEST_TOKEN_MKEY_LEASE_PER:
+			p_port->comp.port_info.m_key_lease_period = 0xFFFF;
+			p_port->rec.port_info.m_key_lease_period =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"m_key_lease_period = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.m_key_lease_period));
+			break;
+
+		case OSMTEST_TOKEN_LOC_PORT_NUM:
+			p_port->comp.port_info.local_port_num = 0xFF;
+			p_port->rec.port_info.local_port_num =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"local_port_num = 0x%u\n",
+				p_port->rec.port_info.local_port_num);
+			break;
+
+		case OSMTEST_TOKEN_LINK_WID_EN:
+			p_port->comp.port_info.link_width_enabled = 0xFF;
+			p_port->rec.port_info.link_width_enabled =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"link_width_enabled = 0x%u\n",
+				p_port->rec.port_info.link_width_enabled);
+			break;
+
+		case OSMTEST_TOKEN_LINK_WID_SUP:
+			p_port->comp.port_info.link_width_supported = 0xFF;
+			p_port->rec.port_info.link_width_supported =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"link_width_supported = 0x%u\n",
+				p_port->rec.port_info.link_width_supported);
+			break;
+
+		case OSMTEST_TOKEN_LINK_WID_ACT:
+			p_port->comp.port_info.link_width_active = 0xFF;
+			p_port->rec.port_info.link_width_active =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"link_width_active = 0x%u\n",
+				p_port->rec.port_info.link_width_active);
+			break;
+
+		case OSMTEST_TOKEN_LINK_SPEED_SUP:
+			p_port->comp.port_info.state_info1 = 0xFF;
+			ib_port_info_set_link_speed_sup((uint8_t)
+							strtoul(&line[offset],
+								NULL, 0),
+							&p_port->rec.port_info);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"link_speed_supported = 0x%u\n",
+				ib_port_info_get_link_speed_sup(&p_port->rec.port_info));
+			break;
+
+		case OSMTEST_TOKEN_PORT_STATE:
+			str_skip_white(line, &offset);
+			p_port->comp.port_info.state_info1 = 0xFF;
+			ib_port_info_set_port_state(&p_port->rec.port_info,
+						    ib_get_port_state_from_str
+						    (&line[offset]));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"port_state = 0x%u\n",
+				ib_port_info_get_port_state(&p_port->rec.port_info));
+			break;
+
+		case OSMTEST_TOKEN_STATE_INFO2:
+			p_port->comp.port_info.state_info2 = 0xFF;
+			p_port->rec.port_info.state_info2 =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"state_info2 = 0x%u\n",
+				p_port->rec.port_info.state_info2);
+			break;
+
+		case OSMTEST_TOKEN_MKEY_PROT_BITS:
+			p_port->comp.port_info.mkey_lmc = 0xFF;
+			ib_port_info_set_mpb(&p_port->rec.port_info,
+					     (uint8_t) strtoul(&line[offset],
+							       NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "mpb = 0x%u\n",
+				ib_port_info_get_mpb(&p_port->rec.port_info));
+			break;
+
+		case OSMTEST_TOKEN_LMC:
+			p_port->comp.port_info.mkey_lmc = 0xFF;
+			ib_port_info_set_lmc(&p_port->rec.port_info,
+					     (uint8_t) strtoul(&line[offset],
+							       NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lmc = 0x%u\n",
+				ib_port_info_get_lmc(&p_port->rec.port_info));
+			break;
+
+		case OSMTEST_TOKEN_LINK_SPEED:
+			p_port->comp.port_info.link_speed = 0xFF;
+			p_port->rec.port_info.link_speed =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"link_speed = 0x%u\n",
+				p_port->rec.port_info.link_speed);
+			break;
+
+		case OSMTEST_TOKEN_MTU_SMSL:
+			p_port->comp.port_info.mtu_smsl = 0xFF;
+			p_port->rec.port_info.mtu_smsl =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"mtu_smsl = 0x%u\n",
+				p_port->rec.port_info.mtu_smsl);
+			break;
+
+		case OSMTEST_TOKEN_VL_CAP:
+			p_port->comp.port_info.vl_cap = 0xFF;
+			p_port->rec.port_info.vl_cap =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_cap = 0x%u\n",
+				p_port->rec.port_info.vl_cap);
+			break;
+
+		case OSMTEST_TOKEN_VL_HIGH_LIMIT:
+			p_port->comp.port_info.vl_high_limit = 0xFF;
+			p_port->rec.port_info.vl_high_limit =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vl_high_limit = 0x%u\n",
+				p_port->rec.port_info.vl_high_limit);
+			break;
+
+		case OSMTEST_TOKEN_VL_ARB_HIGH_CAP:
+			p_port->comp.port_info.vl_arb_high_cap = 0xFF;
+			p_port->rec.port_info.vl_arb_high_cap =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vl_arb_high_cap = 0x%u\n",
+				p_port->rec.port_info.vl_arb_high_cap);
+			break;
+
+		case OSMTEST_TOKEN_VL_ARB_LOW_CAP:
+			p_port->comp.port_info.vl_arb_low_cap = 0xFF;
+			p_port->rec.port_info.vl_arb_low_cap =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vl_arb_low_cap = 0x%u\n",
+				p_port->rec.port_info.vl_arb_low_cap);
+			break;
+
+		case OSMTEST_TOKEN_MTU_CAP:
+			p_port->comp.port_info.mtu_cap = 0xFF;
+			p_port->rec.port_info.mtu_cap =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "mtu_cap = 0x%u\n",
+				p_port->rec.port_info.mtu_cap);
+			break;
+
+		case OSMTEST_TOKEN_VL_STALL_LIFE:
+			p_port->comp.port_info.vl_stall_life = 0xFF;
+			p_port->rec.port_info.vl_stall_life =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vl_stall_life = 0x%u\n",
+				p_port->rec.port_info.vl_stall_life);
+			break;
+
+		case OSMTEST_TOKEN_VL_ENFORCE:
+			p_port->comp.port_info.vl_enforce = 0xFF;
+			p_port->rec.port_info.vl_enforce =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"vl_enforce = 0x%u\n",
+				p_port->rec.port_info.vl_enforce);
+			break;
+
+		case OSMTEST_TOKEN_MKEY_VIOL:
+			p_port->comp.port_info.m_key_violations = 0xFFFF;
+			p_port->rec.port_info.m_key_violations =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"m_key_violations = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.m_key_violations));
+			break;
+
+		case OSMTEST_TOKEN_PKEY_VIOL:
+			p_port->comp.port_info.p_key_violations = 0xFFFF;
+			p_port->rec.port_info.p_key_violations =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"p_key_violations = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.p_key_violations));
+			break;
+
+		case OSMTEST_TOKEN_QKEY_VIOL:
+			p_port->comp.port_info.q_key_violations = 0xFFFF;
+			p_port->rec.port_info.q_key_violations =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"q_key_violations = 0x%X\n",
+				cl_ntoh16(p_port->rec.port_info.q_key_violations));
+			break;
+
+		case OSMTEST_TOKEN_GUID_CAP:
+			p_port->comp.port_info.guid_cap = 0xFF;
+			p_port->rec.port_info.guid_cap =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"guid_cap = 0x%u\n",
+				p_port->rec.port_info.guid_cap);
+			break;
+
+		case OSMTEST_TOKEN_SUBN_TIMEOUT:
+			p_port->comp.port_info.subnet_timeout = 0x1F;
+			p_port->rec.port_info.subnet_timeout =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"subnet_timeout = 0x%u\n",
+				ib_port_info_get_timeout(&p_port->rec.port_info));
+			break;
+
+		case OSMTEST_TOKEN_RESP_TIME_VAL:
+			p_port->comp.port_info.resp_time_value = 0xFF;
+			p_port->rec.port_info.resp_time_value =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"resp_time_value = 0x%u\n",
+				p_port->rec.port_info.resp_time_value);
+			break;
+
+		case OSMTEST_TOKEN_ERR_THRESHOLD:
+			p_port->comp.port_info.error_threshold = 0xFF;
+			p_port->rec.port_info.error_threshold =
+			    (uint8_t) strtoul(&line[offset], NULL, 0);
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"error_threshold = 0x%u\n",
+				p_port->rec.port_info.error_threshold);
+			break;
+
+		case OSMTEST_TOKEN_END:
+			done = TRUE;
+			break;
+
+		default:
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0125: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			break;
+		}
+	}
+
+	/*
+	 * Make sure the user specified enough information, then
+	 * add this object to the database.
+	 */
+	if (p_port->comp.lid == 0) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0126: "
+			"LID must be specified for defined ports\n");
+		port_delete(p_port);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	cl_qmap_insert(&p_osmt->exp_subn.port_key_tbl,
+		       port_gen_id(p_port->rec.lid, p_port->rec.port_num),
+		       &p_port->map_item);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_path(IN osmtest_t * const p_osmt,
+		   IN FILE * const fh, IN OUT uint32_t * const p_line_num)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint32_t offset;
+	char line[OSMTEST_MAX_LINE_LEN];
+	boolean_t done = FALSE;
+	path_t *p_path;
+	const osmtest_token_t *p_tok;
+	boolean_t got_error = FALSE;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	p_path = path_new();
+	CL_ASSERT(p_path != NULL);
+
+	/*
+	 * Parse the inventory file and create the database.
+	 */
+	while (!done) {
+		if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) {
+			/*
+			 * End of file in the middle of a definition.
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
+				"Unexpected end of file\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		++*p_line_num;
+
+		/*
+		 * Skip whitespace
+		 */
+		offset = 0;
+		if (!str_skip_white(line, &offset))
+			continue;	/* whole line was whitespace */
+
+		p_tok = str_get_token(&line[offset]);
+		if (p_tok == NULL) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0128: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			got_error = TRUE;
+			continue;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+			"Found '%s' (line %u)\n", p_tok->str, *p_line_num);
+
+		str_skip_token(line, &offset);
+
+		switch (p_tok->val) {
+		case OSMTEST_TOKEN_COMMENT:
+			break;
+
+		case OSMTEST_TOKEN_DGID:
+			p_path->comp.dgid.unicast.prefix =
+			    0xFFFFFFFFFFFFFFFFULL;
+			p_path->comp.dgid.unicast.interface_id =
+			    0xFFFFFFFFFFFFFFFFULL;
+
+			str_skip_white(line, &offset);
+			p_path->rec.dgid.unicast.prefix =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			str_skip_token(line, &offset);
+			p_path->rec.dgid.unicast.interface_id =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"dgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_path->rec.dgid.unicast.prefix),
+				cl_ntoh64(p_path->rec.dgid.unicast.interface_id));
+			break;
+
+		case OSMTEST_TOKEN_SGID:
+			p_path->comp.sgid.unicast.prefix =
+			    0xFFFFFFFFFFFFFFFFULL;
+			p_path->comp.sgid.unicast.interface_id =
+			    0xFFFFFFFFFFFFFFFFULL;
+
+			str_skip_white(line, &offset);
+			p_path->rec.sgid.unicast.prefix =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+			str_skip_token(line, &offset);
+			p_path->rec.sgid.unicast.interface_id =
+			    cl_hton64(strtoull(&line[offset], NULL, 0));
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+				"sgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
+				cl_ntoh64(p_path->rec.sgid.unicast.prefix),
+				cl_ntoh64(p_path->rec.sgid.unicast.interface_id));
+			break;
+
+		case OSMTEST_TOKEN_DLID:
+			p_path->comp.dlid = 0xFFFF;
+			p_path->rec.dlid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "dlid = 0x%X\n",
+				cl_ntoh16(p_path->rec.dlid));
+			break;
+
+		case OSMTEST_TOKEN_SLID:
+			p_path->comp.slid = 0xFFFF;
+			p_path->rec.slid =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "slid = 0x%X\n",
+				cl_ntoh16(p_path->rec.slid));
+			break;
+
+		case OSMTEST_TOKEN_PKEY:
+			p_path->comp.pkey = 0xFFFF;
+			p_path->rec.pkey =
+			    cl_hton16((uint16_t)
+				      strtoul(&line[offset], NULL, 0));
+			OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "pkey = 0x%X\n",
+				cl_ntoh16(p_path->rec.pkey));
+			break;
+
+		case OSMTEST_TOKEN_END:
+			done = TRUE;
+			break;
+
+		default:
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0129: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			got_error = TRUE;
+			break;
+		}
+	}
+
+	if (got_error) {
+		status = IB_ERROR;
+		goto Exit;
+	}
+	/*
+	 * Make sure the user specified enough information, then
+	 * add this object to the database.
+	 */
+	if (osmtest_path_rec_kay_is_valid(p_osmt, p_path) == FALSE) {
+		path_delete(p_path);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	cl_qmap_insert(&p_osmt->exp_subn.path_tbl,
+		       osmtest_path_rec_key_get(&p_path->rec),
+		       &p_path->map_item);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_link(IN osmtest_t * const p_osmt,
+		   IN FILE * const fh, IN OUT uint32_t * const p_line_num)
+{
+	ib_api_status_t status = IB_SUCCESS;
+	uint32_t offset;
+	char line[OSMTEST_MAX_LINE_LEN];
+	boolean_t done = FALSE;
+	const osmtest_token_t *p_tok;
+	boolean_t got_error = FALSE;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Parse the inventory file and create the database.
+	 */
+	while (!done) {
+		if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) {
+			/*
+			 * End of file in the middle of a definition.
+			 */
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012A: "
+				"Unexpected end of file\n");
+			status = IB_ERROR;
+			goto Exit;
+		}
+
+		++*p_line_num;
+
+		/*
+		 * Skip whitespace
+		 */
+		offset = 0;
+		if (!str_skip_white(line, &offset))
+			continue;	/* whole line was whitespace */
+
+		p_tok = str_get_token(&line[offset]);
+		if (p_tok == NULL) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012B: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			got_error = TRUE;
+			continue;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+			"Found '%s' (line %u)\n", p_tok->str, *p_line_num);
+
+		str_skip_token(line, &offset);
+
+		switch (p_tok->val) {
+		case OSMTEST_TOKEN_FROMLID:
+		case OSMTEST_TOKEN_FROMPORTNUM:
+		case OSMTEST_TOKEN_TOPORTNUM:
+		case OSMTEST_TOKEN_TOLID:
+			/* For now */
+			break;
+
+		case OSMTEST_TOKEN_END:
+			done = TRUE;
+			break;
+
+		default:
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012C: "
+				"Ignoring line %u with unknown token: %s\n",
+				*p_line_num, &line[offset]);
+			got_error = TRUE;
+			break;
+		}
+	}
+
+	if (got_error)
+		status = IB_ERROR;
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t osmtest_create_db(IN osmtest_t * const p_osmt)
+{
+	FILE *fh;
+	ib_api_status_t status = IB_SUCCESS;
+	uint32_t offset;
+	char line[OSMTEST_MAX_LINE_LEN];
+	uint32_t line_num = 0;
+	const osmtest_token_t *p_tok;
+	boolean_t got_error = FALSE;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	fh = fopen(p_osmt->opt.file_name, "r");
+	if (fh == NULL) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0130: "
+			"Unable to open inventory file (%s)\n",
+			p_osmt->opt.file_name);
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+	/*
+	 * Parse the inventory file and create the database.
+	 */
+	while (fgets(line, OSMTEST_MAX_LINE_LEN, fh) != NULL) {
+		line_num++;
+
+		/*
+		 * Skip whitespace
+		 */
+		offset = 0;
+		if (!str_skip_white(line, &offset))
+			continue;	/* whole line was whitespace */
+
+		p_tok = str_get_token(&line[offset]);
+		if (p_tok == NULL) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0131: "
+				"Ignoring line %u: %s\n", line_num,
+				&line[offset]);
+			got_error = TRUE;
+			continue;
+		}
+
+		OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+			"Found '%s' (line %u)\n", p_tok->str, line_num);
+
+		switch (p_tok->val) {
+		case OSMTEST_TOKEN_COMMENT:
+			break;
+
+		case OSMTEST_TOKEN_DEFINE_NODE:
+			status = osmtest_parse_node(p_osmt, fh, &line_num);
+			break;
+
+		case OSMTEST_TOKEN_DEFINE_PORT:
+			status = osmtest_parse_port(p_osmt, fh, &line_num);
+			break;
+
+		case OSMTEST_TOKEN_DEFINE_PATH:
+			status = osmtest_parse_path(p_osmt, fh, &line_num);
+			break;
+
+		case OSMTEST_TOKEN_DEFINE_LINK:
+			status = osmtest_parse_link(p_osmt, fh, &line_num);
+			break;
+
+		default:
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0132: "
+				"Ignoring line %u: %s\n", line_num,
+				&line[offset]);
+			got_error = TRUE;
+			break;
+		}
+
+		if (got_error)
+			status = IB_ERROR;
+
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0133: "
+				"Bad status received during parsing (%s)\n",
+				ib_get_err_str(status));
+			fclose(fh);
+			goto Exit;
+		}
+	}
+
+	fclose(fh);
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+   Returns the index in the local port attribute array for the
+   user's selection.
+**********************************************************************/
+static uint32_t
+osmtest_get_user_port(IN osmtest_t * const p_osmt,
+		      IN const ib_port_attr_t p_attr_array[],
+		      IN uint32_t const num_ports)
+{
+	uint32_t i;
+	uint32_t choice = 0;
+	boolean_t done_flag = FALSE;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * User needs prompting for the local port GUID with which
+	 * to bind.
+	 */
+
+	while (done_flag == FALSE) {
+		printf("\nChoose a local port number with which to bind:\n\n");
+		for (i = 0; i < num_ports; i++) {
+			/*
+			 * Print the index + 1 since by convention, port numbers
+			 * start with 1 on host channel adapters.
+			 */
+
+			printf("\t%u: GUID = 0x%8" PRIx64
+			       ", lid = 0x%04X, state = %s\n", i + 1,
+			       cl_ntoh64(p_attr_array[i].port_guid),
+			       p_attr_array[i].lid,
+			       ib_get_port_state_str(p_attr_array[i].
+						     link_state));
+		}
+
+		printf("\nEnter choice (1-%u): ", i);
+		scanf("%u", &choice);
+		if (choice > num_ports)
+			printf("\nError: Lame choice!\n");
+		else
+			done_flag = TRUE;
+
+	}
+	printf("\n");
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (choice - 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_bind(IN osmtest_t * p_osmt,
+	     IN uint16_t max_lid, IN ib_net64_t guid OPTIONAL)
+{
+	uint32_t port_index;
+	ib_api_status_t status;
+	uint32_t num_ports = GUID_ARRAY_SIZE;
+	ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	/*
+	 * Call the transport layer for a list of local port
+	 * GUID values.
+	 */
+	status = osm_vendor_get_all_port_attr(p_osmt->p_vendor,
+					      attr_array, &num_ports);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0134: "
+			"Failure getting local port attributes (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	if (guid == 0) {
+		/*
+		 * User needs prompting for the local port GUID with which
+		 * to bind.
+		 */
+		port_index =
+		    osmtest_get_user_port(p_osmt, attr_array, num_ports);
+
+		if (num_ports == 0) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0135: "
+				"No local ports.  Unable to proceed\n");
+			goto Exit;
+		}
+		guid = attr_array[port_index].port_guid;
+	} else {
+		for (port_index = 0; port_index < num_ports; port_index++) {
+			if (attr_array[port_index].port_guid == guid)
+				break;
+		}
+
+		if (port_index == num_ports) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0136: "
+				"No local port with guid 0x%016" PRIx64 "\n",
+				cl_ntoh64(guid));
+			status = IB_NOT_FOUND;
+			goto Exit;
+		}
+	}
+
+	/*
+	 * Copy the port info for the selected port.
+	 */
+	memcpy(&p_osmt->local_port, &attr_array[port_index],
+	       sizeof(p_osmt->local_port));
+
+	/* bind to the SA */
+	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
+		"Using port with SM LID:0x%04X\n", p_osmt->local_port.sm_lid);
+	p_osmt->max_lid = max_lid;
+
+	p_osmt->h_bind =
+	    osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid);
+
+	if (p_osmt->h_bind == OSM_BIND_INVALID_HANDLE) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0137: "
+			"Unable to bind to SA\n");
+		status = IB_ERROR;
+		goto Exit;
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t osmtest_run(IN osmtest_t * const p_osmt)
+{
+	ib_api_status_t status = IB_SUCCESS;
+
+	OSM_LOG_ENTER(&p_osmt->log);
+
+	status = osmtest_validate_sa_class_port_info(p_osmt);
+	if (status != IB_SUCCESS) {
+		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0138: "
+			"Could not obtain SA ClassPortInfo (%s)\n",
+			ib_get_err_str(status));
+		goto Exit;
+	}
+
+	if (p_osmt->opt.flow == OSMT_FLOW_CREATE_INVENTORY) {
+		/*
+		 * Creating an inventory file with all nodes, ports and paths
+		 */
+		status = osmtest_create_inventory_file(p_osmt);
+		if (status != IB_SUCCESS) {
+			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0139: "
+				"Inventory file create failed (%s)\n",
+				ib_get_err_str(status));
+			goto Exit;
+		}
+	} else {
+		if (p_osmt->opt.flow == OSMT_FLOW_STRESS_SA) {
+			/*
+			 * Stress SA - flood the SA with queries
+			 */
+			switch (p_osmt->opt.stress) {
+			case 0:
+			case 1:	/* small response SA query stress */
+				status = osmtest_stress_small_rmpp(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0140: "
+						"Small RMPP stress test failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+				break;
+			case 2:	/* large response SA query stress */
+				status = osmtest_stress_large_rmpp(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0141: "
+						"Large RMPP stress test failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+				break;
+			case 3:	/* large response Path Record SA query stress */
+				status = osmtest_create_db(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0142: "
+						"Database creation failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+
+				status = osmtest_stress_large_rmpp_pr(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0143: "
+						"Large RMPP stress test failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+				break;
+			default:
+				OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+					"ERR 0144: "
+					"Unknown stress test value %u\n",
+					p_osmt->opt.stress);
+				break;
+			}
+		} else {
+
+			/*
+			 * Run normal validation tests.
+			 */
+			if (p_osmt->opt.flow == OSMT_FLOW_ALL ||
+			    p_osmt->opt.flow == OSMT_FLOW_VALIDATE_INVENTORY) {
+				/*
+				 * Only validate the given inventory file
+				 */
+				status = osmtest_create_db(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0145: "
+						"Database creation failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+
+				status = osmtest_validate_against_db(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0146: "
+						"SA validation database failure (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_ALL) {
+				status = osmtest_wrong_sm_key_ignored(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0147: "
+						"Try wrong SM_Key failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_ALL ||
+			    p_osmt->opt.flow == OSMT_FLOW_SERVICE_REGISTRATION)
+			{
+				/*
+				 * run service registration, deregistration, and lease test
+				 */
+				status = osmt_run_service_records_flow(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0148: "
+						"Service Flow failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_ALL ||
+			    p_osmt->opt.flow == OSMT_FLOW_EVENT_FORWARDING) {
+				/*
+				 * Run event forwarding test
+				 */
+#ifdef OSM_VENDOR_INTF_MTL
+				status = osmt_run_inform_info_flow(p_osmt);
+
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0149: "
+						"Inform Info Flow failed: (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+#else
+				OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+					"The event forwarding flow "
+					"is not implemented yet!\n");
+				status = IB_SUCCESS;
+				goto Exit;
+#endif
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_QOS) {
+				/*
+				 * QoS info: dump VLArb and SLtoVL tables.
+				 * Since it generates a huge file, we run it only
+				 * if explicitly required to
+				 */
+				status = osmtest_create_db(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 014A: "
+						"Database creation failed (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+
+				status =
+				    osmt_run_slvl_and_vlarb_records_flow
+				    (p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0150: "
+						"Failed to get SLtoVL and VL Arbitration Tables (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_TRAP) {
+				/*
+				 * Run trap 64/65 flow (this flow requires running of external tool)
+				 */
+#ifdef OSM_VENDOR_INTF_MTL
+				status = osmt_run_trap64_65_flow(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0151: "
+						"Trap 64/65 Flow failed: (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+#else
+				OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+					"The event forwarding flow "
+					"is not implemented yet!\n");
+				status = IB_SUCCESS;
+				goto Exit;
+#endif
+			}
+
+			if (p_osmt->opt.flow == OSMT_FLOW_ALL ||
+			    p_osmt->opt.flow == OSMT_FLOW_MULTICAST) {
+				/*
+				 * Multicast flow
+				 */
+				status = osmt_run_mcast_flow(p_osmt);
+				if (status != IB_SUCCESS) {
+					OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
+						"ERR 0152: "
+						"Multicast Flow failed: (%s)\n",
+						ib_get_err_str(status));
+					goto Exit;
+				}
+			}
+
+			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
+				"\n\n***************** ALL TESTS PASS *****************\n\n");
+
+		}
+	}
+
+Exit:
+	OSM_LOG_EXIT(&p_osmt->log);
+	return (status);
+}
diff --git a/scripts/opensm.init.in b/scripts/opensm.init.in
new file mode 100644
index 0000000..52293eb
--- /dev/null
+++ b/scripts/opensm.init.in
@@ -0,0 +1,133 @@
+#!/bin/bash
+#
+# opensm:		Manage OpenSM
+#
+# chkconfig: - 09 91
+# description:  Manage OpenSM
+#
+### BEGIN INIT INFO
+# Provides: opensm
+# Required-Start: $syslog
+# Default-Start: none
+# Default-Stop: 0 1 6
+# Description:  Manage OpenSM
+### END INIT INFO
+#
+# Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+# Copyright 2006 PathScale, Inc.  All Rights Reserved.
+#
+# This Software is licensed under one of the following licenses:
+#
+# 1) under the terms of the "Common Public License 1.0" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/cpl.php.
+#
+# 2) under the terms of the "The BSD License" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/bsd-license.php.
+#
+# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+#    copy of which is available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/gpl-license.php.
+#
+# Licensee has the right to choose one of the above licenses.
+#
+# Redistributions of source code must retain the above copyright
+# notice and one of the license notices.
+#
+# Redistributions in binary form must reproduce both the above copyright
+# notice, one of the license notices in the documentation
+# and/or other materials provided with the distribution.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+# Source function library.
+if [[ -s /etc/init.d/functions ]]; then
+    . /etc/init.d/functions
+    rc_status() { :; }
+    rc_exit() { exit $RETVAL; }
+fi
+if [[ -s /etc/rc.status ]]; then
+    . /etc/rc.status
+    failure() { rc_status -v; }
+    success() { rc_status -v; }
+fi
+
+CONFIG=@sysconfdir@/sysconfig/opensm
+if [[ -s $CONFIG ]]; then
+    . $CONFIG
+fi
+
+start () {
+    echo -n "Starting opensm: "
+    @sbindir@/opensm --daemon $OPTIONS > /dev/null
+    if [[ $RETVAL -eq 0 ]]; then
+        touch /var/lock/subsys/opensm
+        success
+    else
+        failure
+    fi
+    echo
+}
+
+stop () {
+    echo -n "Shutting down opensm: "
+    killproc opensm
+    if [[ $RETVAL -eq 0 ]]; then
+        rm -f /var/lock/subsys/opensm
+        success
+    else
+        failure
+    fi
+    echo
+}
+
+Xstatus () {
+	pid="`pidof opensm`"
+	ret=$?
+	if [ $ret -eq 0 ] ; then
+		echo "OpenSM is running... pid=$pid"
+	else
+		echo "OpenSM is not running."
+	fi
+}
+
+restart() {
+    stop
+    start
+}
+
+# See how we were called.
+case "$1" in
+    start)
+	start
+	;;
+    stop)
+	stop
+	;;
+    status)
+        Xstatus
+	;;
+    restart | force-reload | reload)
+	restart
+	;;
+    try-restart | condrestart)
+	[ -e /var/lock/subsys/opensm ] && restart
+	;;
+    resweep)
+	killall -HUP opensm
+        RETVAL=$?
+	;;
+    rotatelog)
+	killall -USR1 opensm
+        RETVAL=$?
+	;;
+    *)
+	echo $"Usage: $0 {start|stop|status|restart|reload|condrestart|resweep|rotatelog}"
+	RETVAL=1
+	;;
+esac
+
+_rc_status_all=$RETVAL
+rc_exit
diff --git a/scripts/opensm.logrotate b/scripts/opensm.logrotate
new file mode 100644
index 0000000..e16e227
--- /dev/null
+++ b/scripts/opensm.logrotate
@@ -0,0 +1,7 @@
+/var/log/opensm.log {
+    missingok
+    notifempty
+    copytruncate
+    weekly
+    compress
+}
diff --git a/scripts/opensm.sysconfig b/scripts/opensm.sysconfig
new file mode 100644
index 0000000..2cc02e6
--- /dev/null
+++ b/scripts/opensm.sysconfig
@@ -0,0 +1,2 @@
+# It will be used for sldd.sh
+OSM_HOSTS=""
diff --git a/scripts/redhat-opensm.init.in b/scripts/redhat-opensm.init.in
new file mode 100755
index 0000000..9c22275
--- /dev/null
+++ b/scripts/redhat-opensm.init.in
@@ -0,0 +1,292 @@
+#!/bin/bash
+#
+# Bring up/down opensm
+#
+# chkconfig: - 15 85
+# description: Activates/Deactivates InfiniBand Subnet Manager
+#
+### BEGIN INIT INFO
+# Provides:       opensm
+### END INIT INFO
+#
+# Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+# Copyright (c) 2006 Mellanox Technologies. All rights reserved.
+#
+# This Software is licensed under one of the following licenses:
+#
+# 1) under the terms of the "Common Public License 1.0" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/cpl.php.
+#
+# 2) under the terms of the "The BSD License" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/bsd-license.php.
+#
+# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+#    copy of which is available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/gpl-license.php.
+#
+# Licensee has the right to choose one of the above licenses.
+#
+# Redistributions of source code must retain the above copyright
+# notice and one of the license notices.
+#
+# Redistributions in binary form must reproduce both the above copyright
+# notice, one of the license notices in the documentation
+# and/or other materials provided with the distribution.
+#
+#
+#  $Id: openib-1.0-opensm.init,v 1.5 2006/08/02 18:18:23 dledford Exp $
+#
+# processname: @sbindir@/opensm
+# config: @sysconfdir@/sysconfig/opensm
+# pidfile: /var/run/opensm.pid
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+. /etc/rc.d/init.d/functions
+
+CONFIG=@sysconfdir@/sysconfig/opensm
+if [ -f $CONFIG ]; then
+    . $CONFIG
+fi
+
+prog=@sbindir@/opensm
+bin=${prog##*/}
+
+# Handover daemon for updating guid2lid cache file
+sldd_prog=@sbindir@/sldd.sh
+sldd_bin=${sldd_prog##*/}
+sldd_pid_file=/var/run/sldd.pid
+
+ACTION=$1
+
+# Setting OpenSM start parameters
+PID_FILE=/var/run/${bin}.pid
+touch $PID_FILE
+
+if [[ -n "${OSM_HOSTS}" && $(echo -n ${OSM_HOSTS} | wc -w | tr -d '[:space:]') -gt 1  ]]; then
+    HONORE_GUID2LID="--honor_guid2lid"
+fi
+
+#########################################################################
+
+start_sldd()
+{
+    if [ -f $sldd_pid_file ]; then
+            local line p
+            read line < $sldd_pid_file
+            for p in $line ; do
+                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p"
+            done
+    fi
+
+    if [ -z "$sldd_pid" ]; then
+        sldd_pid=`pidof -x $sldd_bin`
+    fi
+
+    if [ -n "${sldd_pid:-}" ] ; then
+	kill -9 ${sldd_pid} > /dev/null 2>&1
+    fi
+
+    $sldd_prog > /dev/null 2>&1 &
+    sldd_pid=$!
+
+    echo ${sldd_pid} > $sldd_pid_file
+    # Sleep is needed in order to update local gid2lid cache file before running opensm
+    sleep 3
+}
+
+stop_sldd()
+{
+    if [ -f $sldd_pid_file ]; then
+            local line p
+            read line < $sldd_pid_file
+            for p in $line ; do
+                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p"
+            done
+    fi
+
+    if [ -z "$sldd_pid" ]; then
+        sldd_pid=`pidof -x $sldd_bin`
+    fi
+
+    if [ -n "${sldd_pid:-}" ] ; then
+        kill -15 ${sldd_pid} > /dev/null 2>&1
+    fi
+
+}
+
+start()
+{
+    local OSM_PID=
+
+    pid=""
+
+    if [ -f $PID_FILE ]; then
+            local line p
+            read line < $PID_FILE
+            for p in $line ; do
+                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p"
+            done
+    fi
+
+    if [ -z "$pid" ]; then
+        pid=`pidof -o $$ -o $PPID -o %PPID -x $bin`
+    fi
+
+    if [ -n "${pid:-}" ] ; then
+        echo $"${bin} (pid $pid) is already running..."
+    else
+
+	if [ -n "${HONORE_GUID2LID}" ]; then
+		# Run sldd daemod
+		start_sldd
+	fi
+
+        # Start opensm
+	echo -n "Starting IB Subnet Manager"
+        $prog --daemon ${HONORE_GUID2LID} ${OPTIONS} > /dev/null
+        cnt=0; alive=0
+        while [ $cnt -lt 6 -a $alive -ne 1 ]; do
+		echo -n ".";
+		sleep 1
+		alive=0
+                OSM_PID=`pidof $prog`
+                if [ "$OSM_PID" != "" ]; then
+                        alive=1
+                fi
+		let cnt++;
+	done
+
+        echo $OSM_PID > $PID_FILE
+        checkpid $OSM_PID
+        RC=$?
+        [ $RC -eq 0 ] && echo_success || echo_failure
+        [ $RC -eq 0 ] && touch /var/lock/subsys/opensm
+	echo
+
+    fi
+return $RC
+}
+
+stop()
+{
+    local pid=
+    local pid1=
+    local pid2=
+
+    # Stop sldd daemon
+    stop_sldd
+
+    if [ -f $PID_FILE ]; then
+            local line p
+            read line < $PID_FILE
+            for p in $line ; do
+                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid1="$pid1 $p"
+            done
+    fi
+
+    pid2=`pidof -o $$ -o $PPID -o %PPID -x $bin`
+
+    pid=`echo "$pid1 $pid2" | sed -e 's/\ /\n/g' | sort -n | uniq | sed -e 's/\n/\ /g'`
+
+    if [ -n "${pid:-}" ] ; then
+        # Kill opensm
+	echo -n "Stopping IB Subnet Manager."
+        kill -15 $pid > /dev/null 2>&1
+		cnt=0; alive=1
+        while [ $cnt -lt 6 -a $alive -ne 0 ]; do
+		echo -n ".";
+		alive=0
+		for p in $pid; do
+			if checkpid $p ; then alive=1; echo -n "-"; fi
+		done
+		let cnt++;
+		sleep $alive
+	done
+
+        for p in $pid
+        do
+            while checkpid $p ; do
+                kill -KILL $p > /dev/null 2>&1
+                echo -n "+"
+                sleep 1
+            done
+        done
+        checkpid $pid
+        RC=$?
+        [ $RC -eq 0 ] && echo_failure || echo_success
+	echo
+        RC=$((! $RC))
+    else
+	echo -n "Stopping IB Subnet Manager."
+        echo_failure
+	echo
+        RC=1
+    fi
+
+    # Remove pid file if any.
+    rm -f $PID_FILE
+    rm -f /var/lock/subsys/opensm
+    return $RC
+}
+
+status()
+{
+    local pid
+
+    # First try "pidof"
+    pid=`pidof -o $$ -o $PPID -o %PPID -x ${bin}`
+    if [ -n "$pid" ]; then
+            echo $"${bin} (pid $pid) is running..."
+            return 0
+    fi
+
+     # Next try "/var/run/opensm.pid" files
+     if [ -f $PID_FILE ] ; then
+             read pid < $PID_FILE
+             if [ -n "$pid" ]; then
+                     echo $"${bin} dead but pid file $PID_FILE exists"
+                     return 1
+             fi
+     fi
+     echo $"${bin} is stopped"
+     return 3
+}
+
+
+
+case $ACTION in
+	start)
+                start
+		;;
+	stop)
+		stop
+		;;
+	restart)
+		stop
+                start
+		;;
+	status)
+		status
+		;;
+	condrestart)
+		pid=`pidof -o $$ -o $PPID -o %PPID -x $bin`
+		if [ -n "$pid" ]; then
+			stop
+			sleep 1
+			start
+		fi
+		;;
+	*)
+		echo
+		echo "Usage: `basename $0` {start|stop|restart|status}"
+		echo
+		exit 1
+		;;
+esac
+
+RC=$?
+exit $RC
diff --git a/scripts/sldd.sh.in b/scripts/sldd.sh.in
new file mode 100755
index 0000000..f7635fe
--- /dev/null
+++ b/scripts/sldd.sh.in
@@ -0,0 +1,246 @@
+#!/bin/bash
+#
+# Copyright (c) 2008 Voltaire, Inc. All rights reserved.
+# Copyright (c) 2006 Mellanox Technologies. All rights reserved.
+#
+# This Software is licensed under one of the following licenses:
+#
+# 1) under the terms of the "Common Public License 1.0" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/cpl.php.
+#
+# 2) under the terms of the "The BSD License" a copy of which is
+#    available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/bsd-license.php.
+#
+# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+#    copy of which is available from the Open Source Initiative, see
+#    http://www.opensource.org/licenses/gpl-license.php.
+#
+# Licensee has the right to choose one of the above licenses.
+#
+# Redistributions of source code must retain the above copyright
+# notice and one of the license notices.
+#
+# Redistributions in binary form must reproduce both the above copyright
+# notice, one of the license notices in the documentation
+# and/or other materials provided with the distribution.
+#
+#
+
+# OpenSM found to have the following problem
+# when handover is performed:
+# If some of the cluster nodes are rebooted during the handover they loose their LID assignment.
+# The reason for it is that the standby SM does not obey its own Guid to LID table
+# and simply uses the discovered LIDs. If some nodes are not available for it
+# their previous LID assignment is lost forever.
+
+# The idea is to use an external daemon that will distribute
+# the semi-static LID assignment table from the master SM to all standby SMs.
+# A standby SM, becoming a master . needs to obey the copied semi static LID assignment table.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+CONFIG=@sysconfdir@/sysconfig/opensm
+if [ -f $CONFIG ]; then
+	. $CONFIG
+fi
+
+SLDD_DEBUG=${SLDD_DEBUG:-0}
+
+CACHE_FILE=${CACHE_FILE:-/var/cache/opensm/guid2lid}
+CACHE_DIR=$(dirname ${CACHE_FILE})
+tmp_cache=${CACHE_FILE}.tmp
+
+PING='ping -w 1 -c 1'
+
+RCP=${RCP:-/usr/bin/scp}
+RSH=${RSH:-/usr/bin/ssh}
+IFCONFIG=${IFCONFIG:-'/sbin/ifconfig -a'}
+
+declare -i SLDD_DEBUG
+RESCAN_TIME=${RESCAN_TIME:-60}
+
+if [ -z "${OSM_HOSTS}" ]; then
+	[ $SLDD_DEBUG -eq 1 ] &&
+	echo "No OpenSM servers (OSM_HOSTS) configured for the IB subnet."
+	exit 0
+fi
+
+
+declare -a arr_OSM_HOSTS
+arr_OSM_HOSTS=(${OSM_HOSTS})
+
+num_of_osm_hosts=${#arr_OSM_HOSTS[@]}
+
+if [ ${num_of_osm_hosts} -eq 1 ]; then
+	[ $SLDD_DEBUG -eq 1 ] &&
+	echo "One OpenSM server configured in the IB subnet." &&
+	echo "Nothing to be done for SLDD"
+
+	exit 0
+fi
+
+trap 'trap_handler' 15
+
+trap_handler()
+{
+	logger -i "SLDD: Exiting."
+	exit 0
+}
+
+is_alive()
+{
+	$PING $1 > /dev/null 2>&1
+	return $?
+}
+
+is_local()
+{
+	$IFCONFIG | grep -w "$1" > /dev/null 2>&1
+	return $?
+}
+
+update_remote_cache()
+{
+	/bin/rm -f ${CACHE_FILE}.upd
+	/bin/cp -a ${CACHE_FILE} ${CACHE_FILE}.upd
+
+	[ $SLDD_DEBUG -eq 1 ] &&
+	echo "Updating remote cache file"
+
+	for host in ${OSM_HOSTS}
+	do
+		# Skip local host update
+		if [ "${host}" == "${local_host}" ]; then
+			continue
+		fi
+
+		if is_alive $host; then
+			stat=$($RSH $host "/bin/mkdir -p ${CACHE_DIR} > /dev/null 2>&1; /bin/rm -f ${CACHE_FILE}.${local_host} > /dev/null 2>&1; echo \$?" | tr -d '[:space:]')
+			if [ "X${stat}" == "X0" ]; then
+				[ $SLDD_DEBUG -eq 1 ] &&
+				echo "Updating $host"
+				logger -i "SLDD: updating $host with ${CACHE_FILE}"
+				$RCP ${CACHE_FILE}.upd ${host}:${CACHE_FILE}.${local_host}
+				/bin/cp ${CACHE_FILE}.upd ${CACHE_FILE}.${host}
+			else
+				[ $SLDD_DEBUG -eq 1 ] &&
+				echo "$RSH to $host failed."
+				logger -i "SLDD: Failed to update $host with ${CACHE_FILE}. $RSH without password should be enabled"
+				exit 5
+			fi
+		else
+			[ $SLDD_DEBUG -eq 1 ] &&
+			echo "$host is down."
+			continue
+		fi
+	done
+}
+
+get_latest_remote_cache()
+{
+	# Find most updated remote cache file (the suffix should be like ip address: *.*.*.*)
+	echo -n "$(/bin/ls -1t ${CACHE_FILE}.*.* 2> /dev/null | head -1)"
+}
+
+get_largest_remote_cache()
+{
+	# Find largest (size) remote cache file (the suffix should be like ip address: *.*.*.*)
+	echo -n "$(/bin/ls -1S ${CACHE_FILE}.*.* 2> /dev/null | head -1)"
+}
+
+swap_cache_files()
+{
+	/bin/rm -f ${CACHE_FILE}.old
+	/bin/mv ${CACHE_FILE} ${CACHE_FILE}.old
+	/bin/cp ${largest_remote_cache} ${CACHE_FILE}
+	touch ${CACHE_FILE}.tmp
+}
+
+# Find local host in the osm hosts list
+local_host=""
+for host in ${OSM_HOSTS}
+do
+	if is_local $host; then
+		local_host=${host}
+	fi
+done
+
+# Get cache file info
+declare -i new_size=0
+declare -i last_size=0
+declare -i largest_remote_cache_size=0
+
+if [ -e ${CACHE_FILE} ]; then
+	last_size=$(du -b ${CACHE_FILE} | awk '{print$1}' | tr -d '[:space:]')
+else
+	touch ${CACHE_FILE} ${CACHE_FILE}.tmp
+fi
+
+# if [ ${last_size} -gt 0 ]; then
+# 	# First time update
+# 	update_remote_cache
+# fi
+
+while true
+do
+	if [ -s "${CACHE_FILE}" ]; then
+		new_size=$(du -b ${CACHE_FILE} | awk '{print$1}' | tr -d '[:space:]')
+		# Check if local cache file grew from its last version or the time stamp changed
+		if [ ${new_size} -gt ${last_size} ]
+		   [ "$(/bin/ls -1t ${CACHE_FILE} ${CACHE_FILE}.tmp 2> /dev/null | head -1)"  != "${CACHE_FILE}.tmp" ]; then
+			largest_remote_cache=$(get_largest_remote_cache)
+			if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then
+				largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]')
+			else
+				largest_remote_cache_size=0
+			fi
+
+			# Check if local cache file larger than remote chache file
+			if [ ${new_size} -gt ${largest_remote_cache_size} ]; then
+				[ $SLDD_DEBUG -eq 1 ] &&
+				echo "Local cache file larger then remote. Update remote cache files"
+				last_size=${new_size}
+				update_remote_cache
+				continue
+			fi
+		fi
+
+		largest_remote_cache=$(get_largest_remote_cache)
+		if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then
+			largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]')
+		else
+			largest_remote_cache_size=0
+		fi
+
+		# Update local cache file from remote
+		if [ ${largest_remote_cache_size} -gt ${new_size} ]; then
+			[ $SLDD_DEBUG -eq 1 ] &&
+			echo "Local cache file shorter then remote. Use ${largest_remote_cache}"
+			logger -i "SLDD: updating local cache file with ${largest_remote_cache}"
+			swap_cache_files
+			last_size=${largest_remote_cache_size}
+		fi
+
+	else # The local cache file is empty
+		[ $SLDD_DEBUG -eq 1 ] &&
+		echo "${CACHE_FILE} is empty"
+
+		largest_remote_cache=$(get_largest_remote_cache)
+		if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then
+			# Copy it to the current cache
+			[ $SLDD_DEBUG -eq 1 ] &&
+			echo "Local cache file is empty. Use ${largest_remote_cache}"
+			logger -i "SLDD: updating local cache file with ${largest_remote_cache}"
+			swap_cache_files
+		fi
+
+	fi
+
+	[ $SLDD_DEBUG -eq 1 ] &&
+	echo "Sleeping ${RESCAN_TIME} seconds."
+	sleep ${RESCAN_TIME}
+
+done

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ofed/opensm.git



More information about the Pkg-ofed-commits mailing list