]> git.openfabrics.org - ~shefty/libibcm.git/commitdiff
r2209: Initial check-in of libibcm
authorLibor Michalek <libor@topspin.com>
Sat, 23 Apr 2005 00:34:20 +0000 (00:34 +0000)
committerLibor Michalek <libor@topspin.com>
Sat, 23 Apr 2005 00:34:20 +0000 (00:34 +0000)
Signed-off-by: Libor Michalek <libor@topspin.com>
16 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.in [new file with mode: 0644]
examples/simple.c [new file with mode: 0644]
include/infiniband/cm.h [new file with mode: 0644]
include/infiniband/cm_abi.h [new file with mode: 0644]
include/infiniband/sa.h [new file with mode: 0644]
libibcm.spec.in [new file with mode: 0644]
src/cm.c [new file with mode: 0644]
src/libibcm.map [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..c79db95
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Libor Michalek         <libor@topspin.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..ee1a79f
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,378 @@
+This software is available to you under a choice of one of two
+licenses.  You may choose to be licensed under the terms of the the
+OpenIB.org BSD license or the GNU General Public License (GPL) Version
+2, both included below.
+
+Copyright (c) 2004 Topspin Communications.  All rights reserved.
+
+==================================================================
+
+                      OpenIB.org BSD license
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following
+    disclaimer in the documentation and/or other materials provided
+    with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+==================================================================
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..47a9c57
--- /dev/null
@@ -0,0 +1,34 @@
+# $Id$
+INCLUDES = -I$(srcdir)/include
+
+AM_CFLAGS = -g -Wall -D_GNU_SOURCE
+
+ibcmlibdir = $(libdir)/infiniband
+
+ibcmlib_LTLIBRARIES = src/ibcm.la
+
+src_ibcm_la_CFLAGS = -g -Wall -D_GNU_SOURCE
+
+if HAVE_LD_VERSION_SCRIPT
+    ibcm_version_script = -Wl,--version-script=$(srcdir)/src/libibcm.map
+else
+    ibcm_version_script =
+endif
+
+src_ibcm_la_SOURCES = src/cm.c
+src_ibcm_la_LDFLAGS = -avoid-version -module $(ucm_version_script)
+
+libibcmincludedir = $(includedir)/infiniband
+
+libibcminclude_HEADERS = include/infiniband/cm_abi.h \
+                        include/infiniband/cm.h \
+                        include/infiniband/sa.h
+
+EXTRA_DIST = include/infiniband/cm_abi.h \
+            include/infiniband/cm.h \
+            include/infiniband/sa.h \
+            src/libibcm.map \
+            libibverbs.spec.in
+
+dist-hook: libibcm.spec
+       cp libibcm.spec $(distdir)
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..fd47839
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+set -x
+aclocal -I config
+libtoolize --force --copy
+autoheader
+automake --foreign --add-missing --copy
+autoconf
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..2eb4bee
--- /dev/null
@@ -0,0 +1,36 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.57)
+AC_INIT(libibcm, 0.9.0, openib-general@openib.org)
+AC_CONFIG_SRCDIR([src/cm.c])
+AC_CONFIG_AUX_DIR(config)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(libibcm, 0.9.0)
+AC_DISABLE_STATIC
+AM_PROG_LIBTOOL
+
+dnl Checks for programs
+AC_PROG_CC
+
+dnl Checks for libraries
+
+dnl Checks for header files.
+AC_CHECK_HEADER(infiniband/verbs.h, [],
+    AC_MSG_ERROR([<infiniband/verbs.h> not found.  Is libibverbs installed?]))
+AC_HEADER_STDC
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_CHECK_SIZEOF(long)
+
+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")
+
+AC_CONFIG_FILES([Makefile libibcm.spec])
+AC_OUTPUT
diff --git a/examples/simple.c b/examples/simple.c
new file mode 100644 (file)
index 0000000..65fd99d
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glob.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdint.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#include <infiniband/sa.h>
+#include <infiniband/cm.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+static inline uint64_t cpu_to_be64(uint64_t x) { return bswap_64(x); }
+#elif __BYTE_ORDER == __BIG_ENDIAN
+static inline uint64_t cpu_to_be64(uint64_t x) { return x; }
+#endif
+
+#define TEST_SID 0x0000000ff0000000ULL
+
+static int connect(uint32_t cm_id)
+{
+       struct ib_cm_req_param param;
+       struct ib_sa_path_rec sa;
+       union ibv_gid *dst;
+       union ibv_gid *src;
+       int result;
+
+       param.qp_type       = IBV_QPT_RC;
+       param.qp_num        = 0xff00;
+       param.starting_psn  = 0x7000;
+        param.service_id    = TEST_SID;
+
+
+        param.primary_path     = &sa;
+       param.alternate_path   = NULL;
+       param.private_data     = NULL;
+        param.private_data_len = 0;
+
+        param.peer_to_peer               = 0;
+        param.responder_resources        = 4;
+        param.initiator_depth            = 4;
+        param.remote_cm_response_timeout = 20;
+        param.flow_control               = 1;
+        param.local_cm_response_timeout  = 20;
+        param.retry_count                = 2;
+        param.rnr_retry_count            = 7;
+        param.max_cm_retries             = 3;
+        param.srq                        = 0;
+
+       memset(&sa, 0, sizeof(sa));
+
+       src = (union ibv_gid *)&sa.sgid;
+       dst = (union ibv_gid *)&sa.dgid;
+
+        sa.dlid = htons(0x1f9);
+        sa.slid = htons(0x3e1);
+
+        sa.dlid = 0xf901;
+        sa.slid = 0xe103;
+
+       sa.reversible = 0x1000000;
+
+       sa.pkey = 0xffff;
+       sa.mtu  = IBV_MTU_1024;
+
+       sa.mtu_selector  = 2;
+       sa.rate_selector = 2;
+       sa.rate          = 3;
+       sa.packet_life_time_selector = 2;
+       sa.packet_life_time          = 2;
+
+       src->global.subnet_prefix = cpu_to_be64(0xfe80000000000000ULL);
+       dst->global.subnet_prefix = cpu_to_be64(0xfe80000000000000ULL);
+       src->global.interface_id  = cpu_to_be64(0x0002c90200002179ULL);
+       dst->global.interface_id  = cpu_to_be64(0x0005ad000001296cULL);
+
+       return ib_cm_send_req(cm_id, &param);
+}
+
+#if 0
+int ib_ucm_event_get(int cm_id, int *event, int *state)
+{
+       struct ib_ucm_cmd_hdr *hdr;
+       struct ib_ucm_event_get *cmd;
+       struct ib_ucm_event_resp resp;
+       void *msg;
+       int result;
+       int size;
+       
+       size = sizeof(*hdr) + sizeof(*cmd);
+       msg = alloca(size);
+       if (!msg)
+               return -ENOMEM;
+       
+       hdr = msg;
+       cmd = msg + sizeof(*hdr);
+
+       hdr->cmd = IB_USER_CM_CMD_EVENT;
+       hdr->in  = sizeof(*cmd);
+       hdr->out = sizeof(resp);
+
+       cmd->response = (unsigned long)&resp;
+       cmd->data     = (unsigned long)NULL;
+       cmd->info     = (unsigned long)NULL;
+       cmd->data_len = 0;
+       cmd->info_len = 0;
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       *event = resp.event;
+       *state = resp.state;
+
+       return 0;
+}
+
+#endif
+
+int main(int argc, char **argv)
+{
+       struct ib_cm_event *event;
+       struct ib_cm_rep_param rep;
+       int cm_id;
+       int result;
+
+       int param_c = 0;
+       int status = 0;
+       int mode;
+       /*
+        * read command line.
+        */
+       if (2 != argc ||
+           0 > (mode = atoi(argv[++param_c]))) {
+
+               fprintf(stderr, "usage: %s <mode>\n", argv[0]);
+
+               fprintf(stderr, "  mode - [client:1|server:0]\n");
+               exit(1);
+       }
+
+       result = ib_cm_create_id(&cm_id);
+       if (result < 0) {
+               printf("Error creating CM ID <%d:%d>\n", result, errno);
+               goto done;
+       }
+
+       if (mode) {
+               result = connect(cm_id);
+               if (result) {
+                       printf("Error <%d:%d> sending REQ <%d>\n", 
+                              result, errno, cm_id);
+                       goto done;
+               }
+       }
+       else {
+               result = ib_cm_listen(cm_id, TEST_SID, 0);
+               if (result) {
+                       printf("Error <%d:%d> listneing <%d>\n", 
+                              result, errno, cm_id);
+                       goto done;
+               }
+       }
+
+       while (!status) {
+
+               result = ib_cm_event_get(&event);
+               if (result) {
+                       printf("Error <%d:%d> getting event\n", 
+                              result, errno);
+                       goto done;
+               }
+
+               printf("CM ID <%d> Event <%d> State <%d>\n", 
+                      event->cm_id, event->event, event->state);
+
+               switch (event->state) {
+               case IB_CM_REQ_RCVD:
+
+                       result = ib_cm_destroy_id(cm_id);
+                       if (result < 0) {
+                               printf("Error destroying listen ID <%d:%d>\n",
+                                      result, errno);
+                               goto done;
+                       }
+                       
+                       cm_id = event->cm_id;
+
+                       rep.qp_num       = event->param.req_rcvd.remote_qpn;
+                       rep.starting_psn = event->param.req_rcvd.starting_psn;
+
+                       rep.private_data        = NULL;
+                       rep.private_data_len    = 0;
+
+                       rep.responder_resources = 4;
+                       rep.initiator_depth     = 4;
+                       rep.target_ack_delay    = 14;
+                       rep.failover_accepted   = 0;
+                       rep.flow_control        = 1;
+                       rep.rnr_retry_count     = 7;
+                       rep.srq                 = 0;
+
+                       result = ib_cm_send_rep(cm_id, &rep);
+                       if (result < 0) {
+                               printf("Error <%d:%d> sending REP\n",
+                                      result, errno);
+                               goto done;
+                       }
+               
+                       break;
+               case IB_CM_REP_RCVD:
+
+                       result = ib_cm_send_rtu(cm_id, NULL, 0);
+                       if (result < 0) {
+                               printf("Error <%d:%d> sending RTU\n",
+                                      result, errno);
+                               goto done;
+                       }
+
+                       break;
+               case IB_CM_ESTABLISHED:
+
+                       result = ib_cm_send_dreq(cm_id, NULL, 0);
+                       if (result < 0) {
+                               printf("Error <%d:%d> sending DREQ\n",
+                                      result, errno);
+                               goto done;
+                       }
+
+                       break;
+               case IB_CM_DREQ_RCVD:
+
+                       result = ib_cm_send_drep(cm_id, NULL, 0);
+                       if (result < 0) {
+                               printf("Error <%d:%d> sending DREP\n",
+                                      result, errno);
+                               goto done;
+                       }
+
+                       break;
+               case IB_CM_TIMEWAIT:
+                       break;
+               case IB_CM_IDLE:
+                       status = 1;
+                       break;
+               default:
+                       status = EINVAL;
+                       printf("Unhandled state <%d:%d>\n", 
+                              event->state, event->event);
+                       break;
+               }
+
+               result = ib_cm_event_put(event);
+               if (result) {
+                       printf("Error <%d:%d> freeing event\n", 
+                              result, errno);
+                       goto done;
+               }
+       }
+
+
+       result = ib_cm_destroy_id(cm_id);
+       if (result < 0) {
+               printf("Error destroying CM ID <%d:%d>\n", result, errno);
+               goto done;
+       }
+
+done:
+       return 0;
+}
+
diff --git a/include/infiniband/cm.h b/include/infiniband/cm.h
new file mode 100644 (file)
index 0000000..9c0a6db
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
+ * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+#if !defined(CM_H)
+#define CM_H
+
+#include <infiniband/verbs.h>
+#include <infiniband/sa.h>
+
+enum ib_cm_state {
+       IB_CM_IDLE,
+       IB_CM_LISTEN,
+       IB_CM_REQ_SENT,
+       IB_CM_REQ_RCVD,
+       IB_CM_MRA_REQ_SENT,
+       IB_CM_MRA_REQ_RCVD,
+       IB_CM_REP_SENT,
+       IB_CM_REP_RCVD,
+       IB_CM_MRA_REP_SENT,
+       IB_CM_MRA_REP_RCVD,
+       IB_CM_ESTABLISHED,
+       IB_CM_DREQ_SENT,
+       IB_CM_DREQ_RCVD,
+       IB_CM_TIMEWAIT,
+       IB_CM_SIDR_REQ_SENT,
+       IB_CM_SIDR_REQ_RCVD
+};
+
+enum ib_cm_lap_state {
+       IB_CM_LAP_IDLE,
+       IB_CM_LAP_SENT,
+       IB_CM_LAP_RCVD,
+       IB_CM_MRA_LAP_SENT,
+       IB_CM_MRA_LAP_RCVD,
+};
+
+enum ib_cm_event_type {
+       IB_CM_REQ_ERROR,
+       IB_CM_REQ_RECEIVED,
+       IB_CM_REP_ERROR,
+       IB_CM_REP_RECEIVED,
+       IB_CM_RTU_RECEIVED,
+       IB_CM_USER_ESTABLISHED,
+       IB_CM_DREQ_ERROR,
+       IB_CM_DREQ_RECEIVED,
+       IB_CM_DREP_RECEIVED,
+       IB_CM_TIMEWAIT_EXIT,
+       IB_CM_MRA_RECEIVED,
+       IB_CM_REJ_RECEIVED,
+       IB_CM_LAP_ERROR,
+       IB_CM_LAP_RECEIVED,
+       IB_CM_APR_RECEIVED,
+       IB_CM_SIDR_REQ_ERROR,
+       IB_CM_SIDR_REQ_RECEIVED,
+       IB_CM_SIDR_REP_RECEIVED
+};
+
+enum ib_cm_data_size {
+       IB_CM_REQ_PRIVATE_DATA_SIZE      = 92,
+       IB_CM_MRA_PRIVATE_DATA_SIZE      = 222,
+       IB_CM_REJ_PRIVATE_DATA_SIZE      = 148,
+       IB_CM_REP_PRIVATE_DATA_SIZE      = 196,
+       IB_CM_RTU_PRIVATE_DATA_SIZE      = 224,
+       IB_CM_DREQ_PRIVATE_DATA_SIZE     = 220,
+       IB_CM_DREP_PRIVATE_DATA_SIZE     = 224,
+       IB_CM_REJ_ARI_LENGTH             = 72,
+       IB_CM_LAP_PRIVATE_DATA_SIZE      = 168,
+       IB_CM_APR_PRIVATE_DATA_SIZE      = 148,
+       IB_CM_APR_INFO_LENGTH            = 72,
+       IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
+       IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
+       IB_CM_SIDR_REP_INFO_LENGTH       = 72
+};
+
+struct ib_cm_req_event_param {
+       uint32_t                listen_id;
+
+       struct ib_sa_path_rec   *primary_path;
+       struct ib_sa_path_rec   *alternate_path;
+
+       uint64_t                remote_ca_guid;
+       uint32_t                remote_qkey;
+       uint32_t                remote_qpn;
+       enum ibv_qp_type        qp_type;
+
+       uint32_t                starting_psn;
+       uint8_t                 responder_resources;
+       uint8_t                 initiator_depth;
+       unsigned int            local_cm_response_timeout:5;
+       unsigned int            flow_control:1;
+       unsigned int            remote_cm_response_timeout:5;
+       unsigned int            retry_count:3;
+       unsigned int            rnr_retry_count:3;
+       unsigned int            srq:1;
+};
+
+struct ib_cm_rep_event_param {
+       uint64_t                remote_ca_guid;
+       uint32_t                remote_qkey;
+       uint32_t                remote_qpn;
+       uint32_t                starting_psn;
+       uint8_t                 responder_resources;
+       uint8_t                 initiator_depth;
+       unsigned int            target_ack_delay:5;
+       unsigned int            failover_accepted:2;
+       unsigned int            flow_control:1;
+       unsigned int            rnr_retry_count:3;
+       unsigned int            srq:1;
+};
+
+enum ib_cm_rej_reason {
+       IB_CM_REJ_NO_QP                         = 1,
+       IB_CM_REJ_NO_EEC                        = 2,
+       IB_CM_REJ_NO_RESOURCES                  = 3,
+       IB_CM_REJ_TIMEOUT                       = 4,
+       IB_CM_REJ_UNSUPPORTED                   = 5,
+       IB_CM_REJ_INVALID_COMM_ID               = 6,
+       IB_CM_REJ_INVALID_COMM_INSTANCE         = 7,
+       IB_CM_REJ_INVALID_SERVICE_ID            = 8,
+       IB_CM_REJ_INVALID_TRANSPORT_TYPE        = 9,
+       IB_CM_REJ_STALE_CONN                    = 10,
+       IB_CM_REJ_RDC_NOT_EXIST                 = 11,
+       IB_CM_REJ_INVALID_GID                   = 12,
+       IB_CM_REJ_INVALID_LID                   = 13,
+       IB_CM_REJ_INVALID_SL                    = 14,
+       IB_CM_REJ_INVALID_TRAFFIC_CLASS         = 15,
+       IB_CM_REJ_INVALID_HOP_LIMIT             = 16,
+       IB_CM_REJ_INVALID_PACKET_RATE           = 17,
+       IB_CM_REJ_INVALID_ALT_GID               = 18,
+       IB_CM_REJ_INVALID_ALT_LID               = 19,
+       IB_CM_REJ_INVALID_ALT_SL                = 20,
+       IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS     = 21,
+       IB_CM_REJ_INVALID_ALT_HOP_LIMIT         = 22,
+       IB_CM_REJ_INVALID_ALT_PACKET_RATE       = 23,
+       IB_CM_REJ_PORT_REDIRECT                 = 24,
+       IB_CM_REJ_INVALID_MTU                   = 26,
+       IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES   = 27,
+       IB_CM_REJ_CONSUMER_DEFINED              = 28,
+       IB_CM_REJ_INVALID_RNR_RETRY             = 29,
+       IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID       = 30,
+       IB_CM_REJ_INVALID_CLASS_VERSION         = 31,
+       IB_CM_REJ_INVALID_FLOW_LABEL            = 32,
+       IB_CM_REJ_INVALID_ALT_FLOW_LABEL        = 33
+};
+
+struct ib_cm_rej_event_param {
+       enum ib_cm_rej_reason   reason;
+       void                    *ari;
+       uint8_t                 ari_length;
+};
+
+struct ib_cm_mra_event_param {
+       uint8_t service_timeout;
+};
+
+struct ib_cm_lap_event_param {
+       struct ib_sa_path_rec   *alternate_path;
+};
+
+enum ib_cm_apr_status {
+       IB_CM_APR_SUCCESS,
+       IB_CM_APR_INVALID_COMM_ID,
+       IB_CM_APR_UNSUPPORTED,
+       IB_CM_APR_REJECT,
+       IB_CM_APR_REDIRECT,
+       IB_CM_APR_IS_CURRENT,
+       IB_CM_APR_INVALID_QPN_EECN,
+       IB_CM_APR_INVALID_LID,
+       IB_CM_APR_INVALID_GID,
+       IB_CM_APR_INVALID_FLOW_LABEL,
+       IB_CM_APR_INVALID_TCLASS,
+       IB_CM_APR_INVALID_HOP_LIMIT,
+       IB_CM_APR_INVALID_PACKET_RATE,
+       IB_CM_APR_INVALID_SL
+};
+
+struct ib_cm_apr_event_param {
+       enum ib_cm_apr_status   ap_status;
+       void                    *apr_info;
+       uint8_t                 info_len;
+};
+
+struct ib_cm_sidr_req_event_param {
+       uint32_t          listen_id;
+       struct ib_device *device;
+       uint8_t           port;
+       uint16_t          pkey;
+};
+
+enum ib_cm_sidr_status {
+       IB_SIDR_SUCCESS,
+       IB_SIDR_UNSUPPORTED,
+       IB_SIDR_REJECT,
+       IB_SIDR_NO_QP,
+       IB_SIDR_REDIRECT,
+       IB_SIDR_UNSUPPORTED_VERSION
+};
+
+struct ib_cm_sidr_rep_event_param {
+       enum ib_cm_sidr_status  status;
+       uint32_t                qkey;
+       uint32_t                qpn;
+       void                    *info;
+       uint8_t                 info_len;
+
+};
+
+struct ib_cm_event {
+       uint32_t              cm_id;
+       enum ib_cm_event_type event;
+       enum ib_cm_state      state;
+       union {
+               struct ib_cm_req_event_param    req_rcvd;
+               struct ib_cm_rep_event_param    rep_rcvd;
+               /* No data for RTU received events. */
+               struct ib_cm_rej_event_param    rej_rcvd;
+               struct ib_cm_mra_event_param    mra_rcvd;
+               struct ib_cm_lap_event_param    lap_rcvd;
+               struct ib_cm_apr_event_param    apr_rcvd;
+               /* No data for DREQ/DREP received events. */
+               struct ib_cm_sidr_req_event_param sidr_req_rcvd;
+               struct ib_cm_sidr_rep_event_param sidr_rep_rcvd;
+               enum ibv_wc_status              send_status;
+       } param;
+
+       void                    *private_data;
+};
+
+/**
+ * ib_cm_event_get - Retrieves the next pending communications event,
+ *   if no event is pending waits for an event.
+ * @event: Allocated information about the next communication event.
+ *    Event should be freed using ib_cm_event_put()
+ *
+ * IB_CM_REQ_RECEIVED and IB_CM_SIDR_REQ_RECEIVED communication events 
+ * generated as a result of listen requests result in the allocation of a 
+ * new @cm_id. 
+ * Clients are responsible for destroying the new @cm_id.  For peer-to-peer
+ * IB_CM_REQ_RECEIVED and all other events, the returned @cm_id corresponds
+ * to a user's existing communication identifier.
+ */
+int ib_cm_event_get(struct ib_cm_event **event);
+
+/**
+ * ib_cm_event_put - Free a communications event.
+ * @event: Event to be released.
+ *
+ * All events which are allocated by ib_cm_event_get() must be released,
+ * there should be a one-to-one correspondence between successful gets
+ * and puts.
+ */
+int ib_cm_event_put(struct ib_cm_event *event);
+
+/**
+ * ib_cm_get_fd - Returns the file descriptor which the CM uses to
+ *   submit requests and retrieve events.
+ *
+ * The primary use of the file descriptor is to test for CM readiness
+ * events. When the CM becomes ready to READ there is a pending event
+ * ready, and a subsequent call to ib_cm_event_get will not block.
+ * Note: The user should not read or writ directly to the CM file
+ *       descriptor, it will likely result in an error or unexpected
+ *       results.
+ */
+int ib_cm_get_fd(void);
+
+/**
+ * ib_cm_create_id - Allocate a communication identifier.
+ *
+ * Communication identifiers are used to track connection states, service
+ * ID resolution requests, and listen requests.
+ */
+int ib_cm_create_id(uint32_t *cm_id);
+
+/**
+ * ib_cm_destroy_id - Destroy a connection identifier.
+ * @cm_id: Connection identifier to destroy.
+ */
+int ib_cm_destroy_id(uint32_t cm_id);
+
+struct ib_cm_attr_param {
+       uint64_t                service_id;
+       uint64_t                service_mask;
+       enum ib_cm_state        state;
+       enum ib_cm_lap_state    lap_state;
+       uint32_t                local_id;
+       uint32_t                remote_id;
+};
+/**
+ * ib_cm_attr_id - Get connection identifier attributes.
+ * @cm_id: Connection identifier to retrieve attributes.
+ * @param: Destination of retreived parameters.
+ *
+ * Not all parameters are valid during all connection states.
+ */
+int ib_cm_attr_id(uint32_t cm_id, 
+                 struct ib_cm_attr_param *param);
+
+/**
+ * ib_cm_listen - Initiates listening on the specified service ID for
+ *   connection and service ID resolution requests.
+ * @cm_id: Connection identifier associated with the listen request.
+ * @service_id: Service identifier matched against incoming connection
+ *   and service ID resolution requests.  The service ID should be specified
+ *   network-byte order.
+ * @service_mask: Mask applied to service ID used to listen across a
+ *   range of service IDs.  If set to 0, the service ID is matched
+ *   exactly.
+ */
+int ib_cm_listen(uint32_t cm_id,
+                uint64_t service_id,
+                uint64_t service_mask);
+
+struct ib_cm_req_param {
+       struct ib_sa_path_rec   *primary_path;
+       struct ib_sa_path_rec   *alternate_path;
+       uint64_t                service_id;
+       uint32_t                qp_num;
+       enum ibv_qp_type        qp_type;
+       uint32_t                starting_psn;
+       void                    *private_data;
+       uint8_t                 private_data_len;
+       uint8_t                 peer_to_peer;
+       uint8_t                 responder_resources;
+       uint8_t                 initiator_depth;
+       uint8_t                 remote_cm_response_timeout;
+       uint8_t                 flow_control;
+       uint8_t                 local_cm_response_timeout;
+       uint8_t                 retry_count;
+       uint8_t                 rnr_retry_count;
+       uint8_t                 max_cm_retries;
+       uint8_t                 srq;
+};
+
+/**
+ * ib_cm_send_req - Sends a connection request to the remote node.
+ * @cm_id: Connection identifier that will be associated with the
+ *   connection request.
+ * @param: Connection request information needed to establish the
+ *   connection.
+ */
+int ib_cm_send_req(uint32_t cm_id,
+                  struct ib_cm_req_param *param);
+
+struct ib_cm_rep_param {
+       uint32_t        qp_num;
+       uint32_t        starting_psn;
+       void            *private_data;
+       uint8_t         private_data_len;
+       uint8_t         responder_resources;
+       uint8_t         initiator_depth;
+       uint8_t         target_ack_delay;
+       uint8_t         failover_accepted;
+       uint8_t         flow_control;
+       uint8_t         rnr_retry_count;
+       uint8_t         srq;
+};
+
+/**
+ * ib_cm_send_rep - Sends a connection reply in response to a connection
+ *   request.
+ * @cm_id: Connection identifier that will be associated with the
+ *   connection request.
+ * @param: Connection reply information needed to establish the
+ *   connection.
+ */
+int ib_cm_send_rep(uint32_t cm_id,
+                  struct ib_cm_rep_param *param);
+
+/**
+ * ib_cm_send_rtu - Sends a connection ready to use message in response
+ *   to a connection reply message.
+ * @cm_id: Connection identifier associated with the connection request.
+ * @private_data: Optional user-defined private data sent with the
+ *   ready to use message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_rtu(uint32_t cm_id,
+                  void *private_data,
+                  uint8_t private_data_len);
+
+/**
+ * ib_cm_send_dreq - Sends a disconnection request for an existing
+ *   connection.
+ * @cm_id: Connection identifier associated with the connection being
+ *   released.
+ * @private_data: Optional user-defined private data sent with the
+ *   disconnection request message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_dreq(uint32_t cm_id,
+                   void *private_data,
+                   uint8_t private_data_len);
+
+/**
+ * ib_cm_send_drep - Sends a disconnection reply to a disconnection request.
+ * @cm_id: Connection identifier associated with the connection being
+ *   released.
+ * @private_data: Optional user-defined private data sent with the
+ *   disconnection reply message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_drep(uint32_t cm_id,
+                   void *private_data,
+                   uint8_t private_data_len);
+
+/**
+ * ib_cm_establish - Forces a connection state to established.
+ * @cm_id: Connection identifier to transition to established.
+ *
+ * This routine should be invoked by users who receive messages on a
+ * connected QP before an RTU has been received.
+ */
+int ib_cm_establish(uint32_t cm_id);
+
+/**
+ * ib_cm_send_rej - Sends a connection rejection message to the
+ *   remote node.
+ * @cm_id: Connection identifier associated with the connection being
+ *   rejected.
+ * @reason: Reason for the connection request rejection.
+ * @ari: Optional additional rejection information.
+ * @ari_length: Size of the additional rejection information, in bytes.
+ * @private_data: Optional user-defined private data sent with the
+ *   rejection message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_rej(uint32_t cm_id,
+                  enum ib_cm_rej_reason reason,
+                  void *ari,
+                  uint8_t ari_length,
+                  void *private_data,
+                  uint8_t private_data_len);
+
+/**
+ * ib_cm_send_mra - Sends a message receipt acknowledgement to a connection
+ *   message.
+ * @cm_id: Connection identifier associated with the connection message.
+ * @service_timeout: The maximum time required for the sender to reply to
+ *   to the connection message.
+ * @private_data: Optional user-defined private data sent with the
+ *   message receipt acknowledgement.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_mra(uint32_t cm_id,
+                  uint8_t service_timeout,
+                  void *private_data,
+                  uint8_t private_data_len);
+
+/**
+ * ib_cm_send_lap - Sends a load alternate path request.
+ * @cm_id: Connection identifier associated with the load alternate path
+ *   message.
+ * @alternate_path: A path record that identifies the alternate path to
+ *   load.
+ * @private_data: Optional user-defined private data sent with the
+ *   load alternate path message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_lap(uint32_t cm_id,
+                  struct ib_sa_path_rec *alternate_path,
+                  void *private_data,
+                  uint8_t private_data_len);
+
+/**
+ * ib_cm_send_apr - Sends an alternate path response message in response to
+ *   a load alternate path request.
+ * @cm_id: Connection identifier associated with the alternate path response.
+ * @status: Reply status sent with the alternate path response.
+ * @info: Optional additional information sent with the alternate path
+ *   response.
+ * @info_length: Size of the additional information, in bytes.
+ * @private_data: Optional user-defined private data sent with the
+ *   alternate path response message.
+ * @private_data_len: Size of the private data buffer, in bytes.
+ */
+int ib_cm_send_apr(uint32_t cm_id,
+                  enum ib_cm_apr_status status,
+                  void *info,
+                  uint8_t info_length,
+                  void *private_data,
+                  uint8_t private_data_len);
+
+struct ib_cm_sidr_req_param {
+       struct ib_sa_path_rec   *path;
+       uint64_t                service_id;
+       int                     timeout_ms;
+       void                    *private_data;
+       uint8_t                 private_data_len;
+       uint8_t                 max_cm_retries;
+       uint16_t                pkey;
+};
+
+/**
+ * ib_cm_send_sidr_req - Sends a service ID resolution request to the
+ *   remote node.
+ * @cm_id: Communication identifier that will be associated with the
+ *   service ID resolution request.
+ * @param: Service ID resolution request information.
+ */
+int ib_cm_send_sidr_req(uint32_t cm_id,
+                       struct ib_cm_sidr_req_param *param);
+
+struct ib_cm_sidr_rep_param {
+       uint32_t                qp_num;
+       uint32_t                qkey;
+       enum ib_cm_sidr_status  status;
+       void                    *info;
+       uint8_t                 info_length;
+       void                    *private_data;
+       uint8_t                 private_data_len;
+};
+
+/**
+ * ib_cm_send_sidr_rep - Sends a service ID resolution request to the
+ *   remote node.
+ * @cm_id: Communication identifier associated with the received service ID
+ *   resolution request.
+ * @param: Service ID resolution reply information.
+ */
+int ib_cm_send_sidr_rep(uint32_t cm_id,
+                       struct ib_cm_sidr_rep_param *param);
+
+#endif /* CM_H */
diff --git a/include/infiniband/cm_abi.h b/include/infiniband/cm_abi.h
new file mode 100644 (file)
index 0000000..34ccff6
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#ifndef CM_ABI_H
+#define CM_ABI_H
+
+#include <linux/types.h>
+/*
+ * This file must be kept in sync with the kernel's version of
+ * drivers/infiniband/include/ib_user_cm.h
+ */
+
+#define IB_USER_CM_ABI_VERSION 1
+
+enum {
+       IB_USER_CM_CMD_CREATE_ID,
+       IB_USER_CM_CMD_DESTROY_ID,
+       IB_USER_CM_CMD_ATTR_ID,
+
+       IB_USER_CM_CMD_LISTEN,
+       IB_USER_CM_CMD_ESTABLISH,
+       
+       IB_USER_CM_CMD_SEND_REQ,
+       IB_USER_CM_CMD_SEND_REP,
+       IB_USER_CM_CMD_SEND_RTU,
+       IB_USER_CM_CMD_SEND_DREQ,
+       IB_USER_CM_CMD_SEND_DREP,
+       IB_USER_CM_CMD_SEND_REJ,
+       IB_USER_CM_CMD_SEND_MRA,
+       IB_USER_CM_CMD_SEND_LAP,
+       IB_USER_CM_CMD_SEND_APR,
+       IB_USER_CM_CMD_SEND_SIDR_REQ,
+       IB_USER_CM_CMD_SEND_SIDR_REP,
+
+       IB_USER_CM_CMD_EVENT,
+};
+/*
+ * command ABI structures.
+ */
+struct cm_abi_cmd_hdr {
+       __u32 cmd;
+       __u16 in;
+       __u16 out;
+};
+
+struct cm_abi_create_id {
+       __u64 response;
+};
+
+struct cm_abi_create_id_resp {
+       __u32 id;
+};
+
+struct cm_abi_destroy_id {
+       __u32 id;
+};
+
+struct cm_abi_attr_id {
+       __u64 response;
+       __u32 id;
+};
+
+struct cm_abi_attr_id_resp {
+       __u64 service_id;
+       __u64 service_mask;
+       __u32 state;
+       __u32 lap_state;
+       __u32 local_id;
+       __u32 remote_id;
+};
+
+struct cm_abi_listen {
+       __u64 service_id;
+       __u64 service_mask;
+       __u32 id;
+};
+
+struct cm_abi_establish {
+       __u32 id;
+};
+
+struct cm_abi_private_data {
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  reserved[3];
+};
+
+struct cm_abi_path_rec {
+       __u8  dgid[16];
+       __u8  sgid[16];
+       __u16 dlid;
+       __u16 slid;
+       __u32 raw_traffic;
+       __u32 flow_label;
+       __u32 reversible;
+       __u32 mtu;
+       __u16 pkey;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  numb_path;
+       __u8  sl;
+       __u8  mtu_selector;
+       __u8  rate_selector;
+       __u8  rate;
+       __u8  packet_life_time_selector;
+       __u8  packet_life_time;
+       __u8  preference;
+};
+
+struct cm_abi_req {
+       __u32 id;
+       __u32 qpn;
+       __u32 qp_type;
+       __u32 psn;
+       __u64 sid;
+       __u64 data;
+       __u64 primary_path;
+       __u64 alternate_path;
+       __u8  len;
+       __u8  peer_to_peer;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  remote_cm_response_timeout;
+       __u8  flow_control;
+       __u8  local_cm_response_timeout;
+       __u8  retry_count;
+       __u8  rnr_retry_count;
+       __u8  max_cm_retries;
+       __u8  srq;
+       __u8  reserved[1];
+};
+
+struct cm_abi_rep {
+       __u64 data;
+       __u32 id;
+       __u32 qpn;
+       __u32 psn;
+       __u8  len;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  target_ack_delay;
+       __u8  failover_accepted;
+       __u8  flow_control;
+       __u8  rnr_retry_count;
+       __u8  srq;
+};
+
+struct cm_abi_info {
+       __u32 id;
+       __u32 status;
+       __u64 info;
+       __u64 data;
+       __u8  info_len;
+       __u8  data_len;
+       __u8  reserved[2];
+};
+
+struct cm_abi_mra {
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  timeout;
+       __u8  reserved[2];
+};
+
+struct cm_abi_lap {
+       __u64 path;
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  reserved[3];
+};
+
+struct cm_abi_sidr_req {
+       __u32 id;
+       __u32 timeout;
+       __u64 sid;
+       __u64 data;
+       __u64 path;
+       __u16 pkey;
+       __u8  len;
+       __u8  max_cm_retries;
+};
+
+struct cm_abi_sidr_rep {
+       __u32 id;
+       __u32 qpn;
+       __u32 qkey;
+       __u32 status;
+       __u64 info;
+       __u64 data;
+       __u8  info_len;
+       __u8  data_len;
+       __u8  reserved[2];
+};
+/*
+ * event notification ABI structures.
+ */
+struct cm_abi_event_get {
+       __u64 response;
+       __u64 data;
+       __u64 info;
+       __u8  data_len;
+       __u8  info_len;
+       __u8  reserved[2];
+};
+
+struct cm_abi_req_event_resp {
+       __u32                  listen_id;
+       /* device */
+       /* port */
+       struct cm_abi_path_rec primary_path;
+       struct cm_abi_path_rec alternate_path;
+       __u64                  remote_ca_guid;
+       __u32                  remote_qkey;
+       __u32                  remote_qpn;
+       __u32                  qp_type;
+       __u32                  starting_psn;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  local_cm_response_timeout;
+       __u8  flow_control;
+       __u8  remote_cm_response_timeout;
+       __u8  retry_count;
+       __u8  rnr_retry_count;
+       __u8  srq;
+};
+
+struct cm_abi_rep_event_resp {
+       __u64 remote_ca_guid;
+       __u32 remote_qkey;
+       __u32 remote_qpn;
+       __u32 starting_psn;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  target_ack_delay;
+       __u8  failover_accepted;
+       __u8  flow_control;
+       __u8  rnr_retry_count;
+       __u8  srq;
+       __u8  reserved[1];
+};
+
+struct cm_abi_rej_event_resp {
+       __u32 reason;
+       /* ari in cm_abi_event_get info field. */
+};
+
+struct cm_abi_mra_event_resp {
+       __u8  timeout;
+       __u8  reserved[3];
+};
+
+struct cm_abi_lap_event_resp {
+       struct cm_abi_path_rec path;
+};
+
+struct cm_abi_apr_event_resp {
+       __u32 status;
+       /* apr info in cm_abi_event_get info field. */
+};
+
+struct cm_abi_sidr_req_event_resp {
+       __u32 listen_id;
+       /* device */
+       /* port */
+       __u16 pkey;
+       __u8  reserved[2];
+};
+
+struct cm_abi_sidr_rep_event_resp {
+       __u32 status;
+       __u32 qkey;
+       __u32 qpn;
+       /* info in cm_abi_event_get info field. */
+};
+
+#define CM_ABI_PRES_DATA      0x01
+#define CM_ABI_PRES_INFO      0x02
+#define CM_ABI_PRES_PRIMARY   0x04
+#define CM_ABI_PRES_ALTERNATE 0x08
+
+struct cm_abi_event_resp {
+       __u32 id;
+       __u32 state;
+       __u32 event;
+       __u32 present;
+       union {
+               struct cm_abi_req_event_resp req_resp;
+               struct cm_abi_rep_event_resp rep_resp;
+               struct cm_abi_rej_event_resp rej_resp;
+               struct cm_abi_mra_event_resp mra_resp;
+               struct cm_abi_lap_event_resp lap_resp;
+               struct cm_abi_apr_event_resp apr_resp;
+
+               struct cm_abi_sidr_req_event_resp sidr_req_resp;
+               struct cm_abi_sidr_rep_event_resp sidr_rep_resp;
+
+               __u32                             send_status;
+       } u;
+};
+
+#endif /* CM_ABI_H */
diff --git a/include/infiniband/sa.h b/include/infiniband/sa.h
new file mode 100644 (file)
index 0000000..a5f960e
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#ifndef IB_SA_H
+#define IB_SA_H
+
+#include <infiniband/verbs.h>
+
+enum ib_sa_rate {
+       IB_SA_RATE_2_5_GBPS = 2,
+       IB_SA_RATE_5_GBPS   = 5,
+       IB_SA_RATE_10_GBPS  = 3,
+       IB_SA_RATE_20_GBPS  = 6,
+       IB_SA_RATE_30_GBPS  = 4,
+       IB_SA_RATE_40_GBPS  = 7,
+       IB_SA_RATE_60_GBPS  = 8,
+       IB_SA_RATE_80_GBPS  = 9,
+       IB_SA_RATE_120_GBPS = 10
+};
+
+static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
+{
+       switch (rate) {
+       case IB_SA_RATE_2_5_GBPS: return  1;
+       case IB_SA_RATE_5_GBPS:   return  2;
+       case IB_SA_RATE_10_GBPS:  return  4;
+       case IB_SA_RATE_20_GBPS:  return  8;
+       case IB_SA_RATE_30_GBPS:  return 12;
+       case IB_SA_RATE_40_GBPS:  return 16;
+       case IB_SA_RATE_60_GBPS:  return 24;
+       case IB_SA_RATE_80_GBPS:  return 32;
+       case IB_SA_RATE_120_GBPS: return 48;
+       default:                  return -1;
+       }
+}
+
+struct ib_sa_path_rec {
+       /* reserved */
+       /* reserved */
+       union ibv_gid dgid;
+       union ibv_gid sgid;
+       uint16_t      dlid;
+       uint16_t      slid;
+       int           raw_traffic;
+       /* reserved */
+       uint32_t      flow_label;
+       uint8_t       hop_limit;
+       uint8_t       traffic_class;
+       int           reversible;
+       uint8_t       numb_path;
+       uint16_t      pkey;
+       /* reserved */
+       uint8_t       sl;
+       uint8_t       mtu_selector;
+       enum ibv_mtu  mtu;
+       uint8_t       rate_selector;
+       uint8_t       rate;
+       uint8_t       packet_life_time_selector;
+       uint8_t       packet_life_time;
+       uint8_t       preference;
+};
+
+#endif /* IB_SA_H */
diff --git a/libibcm.spec.in b/libibcm.spec.in
new file mode 100644 (file)
index 0000000..8601053
--- /dev/null
@@ -0,0 +1,40 @@
+# $Id: $
+
+%define prefix /usr
+%define ver      @VERSION@
+%define  RELEASE 1
+%define  rel     %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
+
+Summary: Userspace InfiniBand Connection Manager.
+Name: libibcm
+Version: %ver
+Release: %rel
+Copyright: Dual GPL/BSD
+Group: System Environment/Libraries
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+Source: http://openib.org/downloads/%{name}-%{version}.tar.gz
+Url: http://openib.org/
+
+%description
+Along with the OpenIB kernel drivers, libibcm provides a userspace
+InfiniBand Connection Managment API.
+
+%prep
+%setup -q
+
+%build
+%configure
+make
+
+%install
+make DESTDIR=${RPM_BUILD_ROOT} install
+# remove unpackaged files from the buildroot
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%{_libdir}/libibcm*.so.*
+%doc AUTHORS COPYING ChangeLog NEWS README
diff --git a/src/cm.c b/src/cm.c
new file mode 100644 (file)
index 0000000..6f756fd
--- /dev/null
+++ b/src/cm.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glob.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdint.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include <infiniband/cm.h>
+#include <infiniband/cm_abi.h>
+
+#define IB_UCM_DEV_PATH "/dev/infiniband/ucm"
+#define PFX "libucm: "
+
+#define CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, type, size) \
+do {                                        \
+       struct cm_abi_cmd_hdr *hdr;         \
+                                            \
+       size = sizeof(*hdr) + sizeof(*cmd); \
+       msg = alloca(size);                 \
+       if (!msg)                           \
+               return -ENOMEM;             \
+       hdr = msg;                          \
+       cmd = msg + sizeof(*hdr);           \
+       hdr->cmd = type;                    \
+       hdr->in  = sizeof(*cmd);            \
+       hdr->out = sizeof(*resp);           \
+       memset(cmd, 0, sizeof(*cmd));       \
+       resp = alloca(sizeof(*resp));       \
+       if (!resp)                          \
+               return -ENOMEM;             \
+       cmd->response = (unsigned long)resp;\
+} while (0)
+
+#define CM_CREATE_MSG_CMD(msg, cmd, type, size) \
+do {                                        \
+       struct cm_abi_cmd_hdr *hdr;         \
+                                            \
+       size = sizeof(*hdr) + sizeof(*cmd); \
+       msg = alloca(size);                 \
+       if (!msg)                           \
+               return -ENOMEM;             \
+       hdr = msg;                          \
+       cmd = msg + sizeof(*hdr);           \
+       hdr->cmd = type;                    \
+       hdr->in  = sizeof(*cmd);            \
+       hdr->out = 0;                       \
+       memset(cmd, 0, sizeof(*cmd));       \
+} while (0)
+
+static int fd;
+
+static void __attribute__((constructor)) ib_cm_init(void)
+{
+       fd = open(IB_UCM_DEV_PATH, O_RDWR);
+        if (fd < 0)
+               fprintf(stderr, PFX
+                       "Error <%d:%d> couldn't open IB cm device <%s>\n",
+                       fd, errno, IB_UCM_DEV_PATH);
+
+}
+
+static void cm_param_path_get(struct cm_abi_path_rec *abi,
+                             struct ib_sa_path_rec *sa)
+{
+       memcpy(abi->dgid, sa->dgid.raw, sizeof(union ibv_gid));
+       memcpy(abi->sgid, sa->sgid.raw, sizeof(union ibv_gid));
+
+       abi->dlid = sa->dlid;
+       abi->slid = sa->slid;
+
+       abi->raw_traffic  = sa->raw_traffic;
+       abi->flow_label   = sa->flow_label;
+       abi->reversible   = sa->reversible;
+       abi->mtu          = sa->mtu;
+       abi->pkey         = sa->pkey;
+
+       abi->hop_limit                 = sa->hop_limit;
+       abi->traffic_class             = sa->traffic_class;
+       abi->numb_path                 = sa->numb_path;
+       abi->sl                        = sa->sl;
+       abi->mtu_selector              = sa->mtu_selector;
+       abi->rate_selector             = sa->rate_selector;
+       abi->rate                      = sa->rate;
+       abi->packet_life_time_selector = sa->packet_life_time_selector;
+       abi->packet_life_time          = sa->packet_life_time;
+       abi->preference                = sa->preference;
+}
+
+int ib_cm_create_id(uint32_t *cm_id)
+{
+       struct cm_abi_create_id_resp *resp;
+       struct cm_abi_create_id *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!cm_id)
+               return -EINVAL;
+
+        CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_CREATE_ID, size);
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       *cm_id = resp->id;
+       return 0;
+}
+
+int ib_cm_destroy_id(uint32_t cm_id)
+{
+       struct cm_abi_destroy_id *cmd;
+       void *msg;
+       int result;
+       int size;
+       
+        CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_DESTROY_ID, size);
+
+       cmd->id = cm_id;
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_attr_id(uint32_t cm_id, struct ib_cm_attr_param *param)
+{
+       struct cm_abi_attr_id_resp *resp;
+       struct cm_abi_attr_id *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!param)
+               return -EINVAL;
+
+        CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_ATTR_ID, size);
+
+       cmd->id = cm_id;
+
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       param->service_id   = resp->service_id;
+       param->service_mask = resp->service_mask;
+       param->state        = resp->state;
+       param->lap_state    = resp->lap_state;
+       param->local_id     = resp->local_id;
+       param->remote_id    = resp->remote_id;
+
+       return 0;
+}
+
+int ib_cm_listen(uint32_t cm_id,
+                uint64_t service_id,
+                uint64_t service_mask)
+{
+       struct cm_abi_listen *cmd;
+       void *msg;
+       int result;
+       int size;
+       
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_LISTEN, size);
+
+       cmd->id           = cm_id;
+       cmd->service_id   = service_id;
+       cmd->service_mask = service_mask;
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_req(uint32_t cm_id, struct ib_cm_req_param *param)
+{
+       struct cm_abi_path_rec *p_path;
+       struct cm_abi_path_rec *a_path;
+       struct cm_abi_req *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!param)
+               return -EINVAL;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REQ, size);
+
+       cmd->id      = cm_id;
+       cmd->qpn     = param->qp_num;
+       cmd->qp_type = param->qp_type;
+       cmd->psn     = param->starting_psn;
+        cmd->sid     = param->service_id;
+
+        cmd->peer_to_peer               = param->peer_to_peer;
+        cmd->responder_resources        = param->responder_resources;
+        cmd->initiator_depth            = param->initiator_depth;
+        cmd->remote_cm_response_timeout = param->remote_cm_response_timeout;
+        cmd->flow_control               = param->flow_control;
+        cmd->local_cm_response_timeout  = param->local_cm_response_timeout;
+        cmd->retry_count                = param->retry_count;
+        cmd->rnr_retry_count            = param->rnr_retry_count;
+        cmd->max_cm_retries             = param->max_cm_retries;
+        cmd->srq                        = param->srq;
+
+       if (param->primary_path) {
+
+               p_path = alloca(sizeof(*p_path));
+               if (!p_path)
+                       return -ENOMEM;
+
+               cm_param_path_get(p_path, param->primary_path);
+               cmd->primary_path = (unsigned long)p_path;
+       }
+               
+       if (param->alternate_path) {
+
+               a_path = alloca(sizeof(*a_path));
+               if (!a_path)
+                       return -ENOMEM;
+
+               cm_param_path_get(a_path, param->alternate_path);
+               cmd->alternate_path = (unsigned long)a_path;
+       }
+
+       if (param->private_data && param->private_data_len) {
+
+               cmd->data = (unsigned long)param->private_data;
+               cmd->len  = param->private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_rep(uint32_t cm_id, struct ib_cm_rep_param *param)
+{
+       struct cm_abi_rep *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!param)
+               return -EINVAL;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REP, size);
+
+       cmd->id  = cm_id;
+       cmd->qpn = param->qp_num;
+       cmd->psn = param->starting_psn;
+
+        cmd->responder_resources = param->responder_resources;
+        cmd->initiator_depth     = param->initiator_depth;
+       cmd->target_ack_delay    = param->target_ack_delay;
+       cmd->failover_accepted   = param->failover_accepted;
+        cmd->flow_control        = param->flow_control;
+        cmd->rnr_retry_count     = param->rnr_retry_count;
+        cmd->srq                 = param->srq;
+
+       if (param->private_data && param->private_data_len) {
+
+               cmd->data = (unsigned long)param->private_data;
+               cmd->len  = param->private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+static inline int cm_send_private_data(uint32_t cm_id,
+                                      uint32_t type,
+                                      void *private_data,
+                                      uint8_t private_data_len)
+{
+       struct cm_abi_private_data *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       CM_CREATE_MSG_CMD(msg, cmd, type, size);
+
+       cmd->id  = cm_id;
+
+       if (private_data && private_data_len) {
+
+               cmd->data = (unsigned long)private_data;
+               cmd->len  = private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_rtu(uint32_t cm_id,
+                  void *private_data,
+                  uint8_t private_data_len)
+{
+       return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_RTU,
+                                   private_data, private_data_len);
+}
+
+int ib_cm_send_dreq(uint32_t cm_id,
+                   void *private_data,
+                   uint8_t private_data_len)
+{
+       return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREQ,
+                                   private_data, private_data_len);
+}
+
+int ib_cm_send_drep(uint32_t cm_id,
+                   void *private_data,
+                   uint8_t private_data_len)
+{
+       return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREP,
+                                   private_data, private_data_len);
+}
+
+int ib_cm_establish(uint32_t cm_id)
+{
+       struct cm_abi_establish *cmd;
+       void *msg;
+       int result;
+       int size;
+       
+        CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_ESTABLISH, size);
+
+       cmd->id = cm_id;
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+static inline int cm_send_status(uint32_t cm_id,
+                                uint32_t type,
+                                int status,
+                                void *info,
+                                uint8_t info_length,
+                                void *private_data,
+                                uint8_t private_data_len)
+{
+       struct cm_abi_info *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       CM_CREATE_MSG_CMD(msg, cmd, type, size);
+
+       cmd->id     = cm_id;
+       cmd->status = status;
+
+       if (private_data && private_data_len) {
+
+               cmd->data     = (unsigned long)private_data;
+               cmd->data_len = private_data_len;
+       }
+
+       if (info && info_length) {
+
+               cmd->info     = (unsigned long)info;
+               cmd->info_len = info_length;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_rej(uint32_t cm_id,
+                  enum ib_cm_rej_reason reason,
+                  void *ari,
+                  uint8_t ari_length,
+                  void *private_data,
+                  uint8_t private_data_len)
+{
+       return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_REJ, reason, 
+                             ari, ari_length,
+                             private_data, private_data_len);
+}
+
+int ib_cm_send_apr(uint32_t cm_id,
+                  enum ib_cm_apr_status status,
+                  void *info,
+                  uint8_t info_length,
+                  void *private_data,
+                  uint8_t private_data_len)
+{
+       return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_APR, status, 
+                             info, info_length,
+                             private_data, private_data_len);
+}
+
+int ib_cm_send_mra(uint32_t cm_id,
+                  uint8_t service_timeout,
+                  void *private_data,
+                  uint8_t private_data_len)
+{
+       struct cm_abi_mra *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_MRA, size);
+
+       cmd->id      = cm_id;
+       cmd->timeout = service_timeout;
+
+       if (private_data && private_data_len) {
+
+               cmd->data = (unsigned long)private_data;
+               cmd->len  = private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_lap(uint32_t cm_id,
+                  struct ib_sa_path_rec *alternate_path,
+                  void *private_data,
+                  uint8_t private_data_len)
+{
+       struct cm_abi_path_rec *abi_path;
+       struct cm_abi_lap *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_LAP, size);
+
+       cmd->id = cm_id;
+
+       if (alternate_path) {
+
+               abi_path = alloca(sizeof(*abi_path));
+               if (!abi_path)
+                       return -ENOMEM;
+
+               cm_param_path_get(abi_path, alternate_path);
+               cmd->path = (unsigned long)abi_path;
+       }
+
+       if (private_data && private_data_len) {
+
+               cmd->data = (unsigned long)private_data;
+               cmd->len  = private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_sidr_req(uint32_t cm_id, struct ib_cm_sidr_req_param *param)
+{
+       struct cm_abi_path_rec *abi_path;
+       struct cm_abi_sidr_req *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!param)
+               return -EINVAL;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REQ, size);
+
+       cmd->id             = cm_id;
+       cmd->sid            = param->service_id;
+       cmd->timeout        = param->timeout_ms;
+       cmd->pkey           = param->pkey;
+       cmd->max_cm_retries = param->max_cm_retries;
+
+       if (param->path) {
+
+               abi_path = alloca(sizeof(*abi_path));
+               if (!abi_path)
+                       return -ENOMEM;
+
+               cm_param_path_get(abi_path, param->path);
+               cmd->path = (unsigned long)abi_path;
+       }
+
+       if (param->private_data && param->private_data_len) {
+
+               cmd->data = (unsigned long)param->private_data;
+               cmd->len  = param->private_data_len;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+int ib_cm_send_sidr_rep(uint32_t cm_id, struct ib_cm_sidr_rep_param *param)
+{
+       struct cm_abi_sidr_rep *cmd;
+       void *msg;
+       int result;
+       int size;
+
+       if (!param)
+               return -EINVAL;
+
+       CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REP, size);
+
+       cmd->id     = cm_id;
+       cmd->qpn    = param->qp_num;
+       cmd->qkey   = param->qkey;
+       cmd->status = param->status;
+
+       if (param->private_data && param->private_data_len) {
+
+               cmd->data     = (unsigned long)param->private_data;
+               cmd->data_len = param->private_data_len;
+       }
+
+       if (param->info && param->info_length) {
+
+               cmd->info     = (unsigned long)param->info;
+               cmd->info_len = param->info_length;
+       }
+
+       result = write(fd, msg, size);
+       if (result != size)
+               return (result > 0) ? -ENODATA : result;
+
+       return 0;
+}
+
+/*
+ * event processing
+ */
+static void cm_event_path_get(struct ib_sa_path_rec  *upath,
+                             struct cm_abi_path_rec *kpath)
+{
+       if (!kpath || !upath)
+               return;
+
+       memcpy(upath->dgid.raw, kpath->dgid, sizeof(union ibv_gid));
+       memcpy(upath->sgid.raw, kpath->sgid, sizeof(union ibv_gid));
+       
+       upath->dlid             = kpath->dlid;
+       upath->slid             = kpath->slid;
+       upath->raw_traffic      = kpath->raw_traffic;
+       upath->flow_label       = kpath->flow_label;
+       upath->hop_limit        = kpath->hop_limit;
+       upath->traffic_class    = kpath->traffic_class;
+       upath->reversible       = kpath->reversible;
+       upath->numb_path        = kpath->numb_path;
+       upath->pkey             = kpath->pkey;
+       upath->sl               = kpath->sl;
+       upath->mtu_selector     = kpath->mtu_selector;
+       upath->mtu              = kpath->mtu;
+       upath->rate_selector    = kpath->rate_selector;
+       upath->rate             = kpath->rate;
+       upath->packet_life_time = kpath->packet_life_time;
+       upath->preference       = kpath->preference;
+
+       upath->packet_life_time_selector = 
+               kpath->packet_life_time_selector;
+}
+
+static void cm_event_req_get(struct ib_cm_req_event_param *ureq,
+                            struct cm_abi_req_event_resp *kreq)
+{
+       ureq->listen_id                  = kreq->listen_id;
+
+       ureq->remote_ca_guid             = kreq->remote_ca_guid;
+       ureq->remote_qkey                = kreq->remote_qkey;
+       ureq->remote_qpn                 = kreq->remote_qpn;
+       ureq->qp_type                    = kreq->qp_type;
+       ureq->starting_psn               = kreq->starting_psn;
+       ureq->responder_resources        = kreq->responder_resources;
+       ureq->initiator_depth            = kreq->initiator_depth;
+       ureq->local_cm_response_timeout  = kreq->local_cm_response_timeout;
+       ureq->flow_control               = kreq->flow_control;
+       ureq->remote_cm_response_timeout = kreq->remote_cm_response_timeout;
+       ureq->retry_count                = kreq->retry_count;
+       ureq->rnr_retry_count            = kreq->rnr_retry_count;
+       ureq->srq                        = kreq->srq;
+
+       cm_event_path_get(ureq->primary_path, &kreq->primary_path);
+       cm_event_path_get(ureq->alternate_path, &kreq->alternate_path);
+}
+
+static void cm_event_rep_get(struct ib_cm_rep_event_param *urep,
+                            struct cm_abi_rep_event_resp *krep)
+{
+       urep->remote_ca_guid      = krep->remote_ca_guid;
+       urep->remote_qkey         = krep->remote_qkey;
+       urep->remote_qpn          = krep->remote_qpn;
+       urep->starting_psn        = krep->starting_psn;
+       urep->responder_resources = krep->responder_resources;
+       urep->initiator_depth     = krep->initiator_depth;
+       urep->target_ack_delay    = krep->target_ack_delay;
+       urep->failover_accepted   = krep->failover_accepted;
+       urep->flow_control        = krep->flow_control;
+       urep->rnr_retry_count     = krep->rnr_retry_count;
+       urep->srq                 = krep->srq;
+}
+static void cm_event_rej_get(struct ib_cm_rej_event_param *urej,
+                            struct cm_abi_rej_event_resp *krej)
+{
+       urej->reason = krej->reason;
+}
+
+static void cm_event_mra_get(struct ib_cm_mra_event_param *umra,
+                            struct cm_abi_mra_event_resp *kmra)
+{
+       umra->service_timeout = kmra->timeout;
+}
+
+static void cm_event_lap_get(struct ib_cm_lap_event_param *ulap,
+                            struct cm_abi_lap_event_resp *klap)
+{
+       cm_event_path_get(ulap->alternate_path, &klap->path);
+}
+
+static void cm_event_apr_get(struct ib_cm_apr_event_param *uapr,
+                            struct cm_abi_apr_event_resp *kapr)
+{
+       uapr->ap_status = kapr->status;
+}
+
+static void cm_event_sidr_req_get(struct ib_cm_sidr_req_event_param *ureq,
+                                 struct cm_abi_sidr_req_event_resp *kreq)
+{
+       ureq->listen_id = kreq->listen_id;
+       ureq->pkey      = kreq->pkey;
+}
+
+static void cm_event_sidr_rep_get(struct ib_cm_sidr_rep_event_param *urep,
+                                 struct cm_abi_sidr_rep_event_resp *krep)
+{
+       urep->status = krep->status;
+       urep->qkey   = krep->qkey;
+       urep->qpn    = krep->qpn;
+};
+
+int ib_cm_event_get(struct ib_cm_event **event)
+{
+       struct cm_abi_cmd_hdr *hdr;
+       struct cm_abi_event_get *cmd;
+       struct cm_abi_event_resp *resp;
+       struct ib_cm_event *evt = NULL;
+       struct ib_sa_path_rec *path_a = NULL;
+       struct ib_sa_path_rec *path_b = NULL;
+       void *data = NULL;
+       void *info = NULL;
+       void *msg;
+       int result = 0;
+       int size;
+       
+       if (!event)
+               return -EINVAL;
+
+       size = sizeof(*hdr) + sizeof(*cmd);
+       msg = alloca(size);
+       if (!msg)
+               return -ENOMEM;
+       
+       hdr = msg;
+       cmd = msg + sizeof(*hdr);
+
+       hdr->cmd = IB_USER_CM_CMD_EVENT;
+       hdr->in  = sizeof(*cmd);
+       hdr->out = sizeof(*resp);
+
+       resp = alloca(sizeof(*resp));
+       if (!resp)
+               return -ENOMEM;
+       
+       cmd->response = (unsigned long)resp;
+       cmd->data_len = (uint8_t)(~0U);
+       cmd->info_len = (uint8_t)(~0U);
+
+       data = malloc(cmd->data_len);
+       if (!data) {
+               result = -ENOMEM;
+               goto done;
+       }
+
+       info = malloc(cmd->info_len);
+       if (!info) {
+               result = -ENOMEM;
+               goto done;
+       }
+
+       cmd->data = (unsigned long)data;
+       cmd->info = (unsigned long)info;
+
+       result = write(fd, msg, size);
+       if (result != size) {
+               result = (result > 0) ? -ENODATA : result;
+               goto done;
+       }
+       /*
+        * decode event.
+        */
+       evt = malloc(sizeof(*evt));
+       if (!evt) {
+               result = -ENOMEM;
+               goto done;
+       }
+       
+       memset(evt, 0, sizeof(*evt));
+
+       evt->cm_id = resp->id;
+       evt->event = resp->event;
+       evt->state = resp->state;
+
+       if (resp->present & CM_ABI_PRES_PRIMARY) {
+
+               path_a = malloc(sizeof(*path_a));
+               if (!path_a) {
+                       result = -ENOMEM;
+                       goto done;
+               }
+       }
+
+       if (resp->present & CM_ABI_PRES_ALTERNATE) {
+
+               path_b = malloc(sizeof(*path_b));
+               if (!path_b) {
+                       result = -ENOMEM;
+                       goto done;
+               }
+       }
+       
+       if (resp->present & CM_ABI_PRES_DATA) {
+
+               evt->private_data = data;
+               data = NULL;
+       }
+
+       switch (evt->event) {
+       case IB_CM_REQ_RECEIVED:
+
+               evt->param.req_rcvd.primary_path   = path_a;
+               evt->param.req_rcvd.alternate_path = path_b;
+               path_a = NULL;
+               path_b = NULL;
+
+               cm_event_req_get(&evt->param.req_rcvd, &resp->u.req_resp);
+               break;
+       case IB_CM_REP_RECEIVED:
+
+               cm_event_rep_get(&evt->param.rep_rcvd, &resp->u.rep_resp);
+               break;
+       case IB_CM_MRA_RECEIVED:
+
+               cm_event_mra_get(&evt->param.mra_rcvd, &resp->u.mra_resp);
+               break;
+       case IB_CM_REJ_RECEIVED:
+
+               cm_event_rej_get(&evt->param.rej_rcvd, &resp->u.rej_resp);
+
+               evt->param.rej_rcvd.ari = info;
+               info = NULL;
+
+               break;
+       case IB_CM_LAP_RECEIVED:
+
+               evt->param.lap_rcvd.alternate_path = path_b;
+               path_b = NULL;
+
+               cm_event_lap_get(&evt->param.lap_rcvd, &resp->u.lap_resp);
+               break;
+       case IB_CM_APR_RECEIVED:
+
+               cm_event_apr_get(&evt->param.apr_rcvd, &resp->u.apr_resp);
+
+               evt->param.apr_rcvd.apr_info = info;
+               info = NULL;
+
+               break;
+       case IB_CM_SIDR_REQ_RECEIVED:
+
+               cm_event_sidr_req_get(&evt->param.sidr_req_rcvd,
+                                     &resp->u.sidr_req_resp);
+               break;
+       case IB_CM_SIDR_REP_RECEIVED:
+
+               cm_event_sidr_rep_get(&evt->param.sidr_rep_rcvd,
+                                     &resp->u.sidr_rep_resp);
+               
+               evt->param.sidr_rep_rcvd.info = info;
+               info = NULL;
+
+               break;
+       default:
+
+               evt->param.send_status = resp->u.send_status;
+               break;
+       }
+
+       *event = evt;
+       evt    = NULL;
+       result = 0;
+done:
+       if (data)
+               free(data);
+       if (info)
+               free(info);
+       if (path_a)
+               free(path_a);
+       if (path_b)
+               free(path_b);
+       if (evt)
+               free(evt);
+
+       return result;
+}
+
+int ib_cm_event_put(struct ib_cm_event *event)
+{
+       if (!event)
+               return -EINVAL;
+
+       if (event->private_data)
+               free(event->private_data);
+
+       switch (event->event) {
+       case IB_CM_REQ_RECEIVED:
+
+               if (event->param.req_rcvd.primary_path)
+                       free(event->param.req_rcvd.primary_path);
+
+               if (event->param.req_rcvd.alternate_path)
+                       free(event->param.req_rcvd.alternate_path);
+               break;
+       case IB_CM_REJ_RECEIVED:
+
+               if (event->param.rej_rcvd.ari)
+                       free(event->param.rej_rcvd.ari);
+               break;
+       case IB_CM_LAP_RECEIVED:
+
+               if (event->param.lap_rcvd.alternate_path)
+                       free(event->param.lap_rcvd.alternate_path);
+               break;
+       case IB_CM_APR_RECEIVED:
+
+               if (event->param.apr_rcvd.apr_info)
+                       free(event->param.apr_rcvd.apr_info);
+               break;
+       case IB_CM_SIDR_REP_RECEIVED:
+
+               if (event->param.sidr_rep_rcvd.info)
+                       free(event->param.sidr_rep_rcvd.info);
+       default:
+               break;
+       }
+
+       free(event);
+       return 0;
+}
+
+int ib_cm_get_fd(void)
+{
+       return fd;
+}
+
+int ib_cm_event_get_timed(int timeout_ms, struct ib_cm_event **event)
+{
+       struct pollfd ufds;
+       int result;
+
+       ufds.fd      = ib_cm_get_fd();
+       ufds.events  = POLLIN;
+       ufds.revents = 0;
+
+       *event = NULL;
+
+       result = poll(&ufds, 1, timeout_ms);
+       if (!result)
+               return -ETIMEDOUT;
+
+       return ib_cm_event_get(event);
+}
diff --git a/src/libibcm.map b/src/libibcm.map
new file mode 100644 (file)
index 0000000..613475c
--- /dev/null
@@ -0,0 +1,24 @@
+IBCM_1.0 {
+       global:
+
+               ib_cm_event_get;
+               ib_cm_event_put;
+               ib_cm_get_fd;
+               ib_cm_create_id;
+               ib_cm_destroy_id;
+               ib_cm_attr_id;
+               ib_cm_listen;
+               ib_cm_send_req;
+               ib_cm_send_rep;
+               ib_cm_send_rtu;
+               ib_cm_send_dreq;
+               ib_cm_send_drep;
+               ib_cm_establish;
+               ib_cm_send_rej;
+               ib_cm_send_mra;
+               ib_cm_send_lap;
+               ib_cm_send_apr;
+               ib_cm_send_sidr_req;
+               ib_cm_send_sidr_rep;
+       local: *;
+};