--- /dev/null
+Libor Michalek <libor@topspin.com>
--- /dev/null
+This 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.
--- /dev/null
+# $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)
--- /dev/null
+#! /bin/sh
+
+set -x
+aclocal -I config
+libtoolize --force --copy
+autoheader
+automake --foreign --add-missing --copy
+autoconf
--- /dev/null
+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
--- /dev/null
+/*
+ * 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, ¶m);
+}
+
+#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;
+}
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+# $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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+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: *;
+};