components/open-fabrics/libibverbs/patches/005-libibverbs-xrc.patch
changeset 7865 22ec3267b2a3
equal deleted inserted replaced
7864:f11e8d81786a 7865:22ec3267b2a3
       
     1 #This patch was developed both in-house and from outside. We plan to submit it
       
     2 #upstream, but do not yet have a target date for doing so
       
     3 #
       
     4 # HG changeset patch
       
     5 # Parent  f8684a1d3f02b9cc10a686daa8659805384ba51a
       
     6 25759055 OFUV (Userland) support for XRC APIs
       
     7 
       
     8 diff -r f8684a1d3f02 Makefile.am
       
     9 --- a/Makefile.am	Mon Nov 21 11:48:20 2016 -0800
       
    10 +++ b/Makefile.am	Mon Mar 20 14:32:42 2017 -0700
       
    11 @@ -45,7 +45,8 @@
       
    12  
       
    13  libibverbsinclude_HEADERS = include/infiniband/arch.h include/infiniband/driver.h \
       
    14      include/infiniband/kern-abi.h include/infiniband/opcode.h include/infiniband/verbs.h \
       
    15 -    include/infiniband/sa-kern-abi.h include/infiniband/sa.h include/infiniband/marshall.h
       
    16 +    include/infiniband/sa-kern-abi.h include/infiniband/sa.h include/infiniband/marshall.h \
       
    17 +    include/infiniband/ofa_verbs.h
       
    18  
       
    19  man_MANS = man/ibv_asyncwatch.1 man/ibv_devices.1 man/ibv_devinfo.1	\
       
    20      man/ibv_shpd_pingpong.1			\
       
    21 @@ -64,7 +65,8 @@
       
    22      man/ibv_query_srq.3 man/ibv_rate_to_mult.3 man/ibv_reg_mr.3		\
       
    23      man/ibv_req_notify_cq.3 man/ibv_resize_cq.3 man/ibv_rate_to_mbps.3  \
       
    24      man/ibv_create_qp_ex.3 man/ibv_create_srq_ex.3 man/ibv_open_xrcd.3  \
       
    25 -    man/ibv_get_srq_num.3 man/ibv_open_qp.3
       
    26 +    man/ibv_get_srq_num.3 man/ibv_open_qp.3 man/ibv_create_xsrq.3       \
       
    27 +    man/ibv_xsrq_pingpong.1
       
    28  
       
    29  DEBIAN = debian/changelog debian/compat debian/control debian/copyright \
       
    30      debian/ibverbs-utils.install debian/libibverbs1.install \
       
    31 diff -r f8684a1d3f02 Makefile.in
       
    32 --- a/Makefile.in	Mon Nov 21 11:48:20 2016 -0800
       
    33 +++ b/Makefile.in	Mon Mar 20 14:32:42 2017 -0700
       
    34 @@ -476,7 +476,8 @@
       
    35  libibverbsincludedir = $(includedir)/infiniband
       
    36  libibverbsinclude_HEADERS = include/infiniband/arch.h include/infiniband/driver.h \
       
    37      include/infiniband/kern-abi.h include/infiniband/opcode.h include/infiniband/verbs.h \
       
    38 -    include/infiniband/sa-kern-abi.h include/infiniband/sa.h include/infiniband/marshall.h include/infiniband/ofa_solaris.h
       
    39 +    include/infiniband/sa-kern-abi.h include/infiniband/sa.h include/infiniband/marshall.h \
       
    40 +    include/infiniband/ofa_solaris.h include/infiniband/ofa_verbs.h
       
    41  
       
    42  man_MANS = man/ibv_asyncwatch.1 man/ibv_devices.1 man/ibv_devinfo.1	\
       
    43      man/ibv_shpd_pingpong.1			\
       
    44 @@ -495,7 +496,8 @@
       
    45      man/ibv_query_srq.3 man/ibv_rate_to_mult.3 man/ibv_reg_mr.3		\
       
    46      man/ibv_req_notify_cq.3 man/ibv_resize_cq.3 man/ibv_rate_to_mbps.3  \
       
    47      man/ibv_create_qp_ex.3 man/ibv_create_srq_ex.3 man/ibv_open_xrcd.3  \
       
    48 -    man/ibv_get_srq_num.3 man/ibv_open_qp.3
       
    49 +    man/ibv_get_srq_num.3 man/ibv_open_qp.3 man/ibv_create_xsrq.3       \
       
    50 +    man/ibv_xsrq_pingpong.1
       
    51  
       
    52  DEBIAN = debian/changelog debian/compat debian/control debian/copyright \
       
    53      debian/ibverbs-utils.install debian/libibverbs1.install \
       
    54 diff -r f8684a1d3f02 include/infiniband/ofa_verbs.h
       
    55 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
    56 +++ b/include/infiniband/ofa_verbs.h	Mon Mar 20 14:32:42 2017 -0700
       
    57 @@ -0,0 +1,140 @@
       
    58 +/*
       
    59 + * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
       
    60 + * Copyright (c) 2004, 2011-2012 Intel Corporation.  All rights reserved.
       
    61 + * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
       
    62 + * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
       
    63 + *
       
    64 + * This software is available to you under a choice of one of two
       
    65 + * licenses.  You may choose to be licensed under the terms of the GNU
       
    66 + * General Public License (GPL) Version 2, available from the file
       
    67 + * COPYING in the main directory of this source tree, or the
       
    68 + * OpenIB.org BSD license below:
       
    69 + *
       
    70 + *     Redistribution and use in source and binary forms, with or
       
    71 + *     without modification, are permitted provided that the following
       
    72 + *     conditions are met:
       
    73 + *
       
    74 + *	- Redistributions of source code must retain the above
       
    75 + *	  copyright notice, this list of conditions and the following
       
    76 + *	  disclaimer.
       
    77 + *
       
    78 + *	- Redistributions in binary form must reproduce the above
       
    79 + *	  copyright notice, this list of conditions and the following
       
    80 + *	  disclaimer in the documentation and/or other materials
       
    81 + *	  provided with the distribution.
       
    82 + *
       
    83 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    84 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    85 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
       
    86 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
       
    87 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
       
    88 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
    89 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       
    90 + * SOFTWARE.
       
    91 + */
       
    92 +
       
    93 +#ifndef INFINIBAND_OFA_VERBS_H
       
    94 +#define INFINIBAND_OFA_VERBS_H
       
    95 +
       
    96 +struct ibv_srq_init_attr;
       
    97 +struct ibv_cq;
       
    98 +struct ibv_pd;
       
    99 +struct ibv_qp_init_attr;
       
   100 +struct ibv_qp_attr;
       
   101 +
       
   102 +
       
   103 +#ifdef __GNUC__
       
   104 +#define DEPRECATED  __attribute__((deprecated))
       
   105 +#else
       
   106 +#define DEPRECATED
       
   107 +#endif
       
   108 +
       
   109 +/* XRC compatability layer */
       
   110 +#define LEGACY_XRC_SRQ_HANDLE 0xffffffff
       
   111 +
       
   112 +struct ibv_xrc_domain {
       
   113 +	struct ibv_context     *context;
       
   114 +	uint32_t		handle;
       
   115 +};
       
   116 +
       
   117 +struct ibv_srq_legacy {
       
   118 +	struct ibv_context     *context;
       
   119 +	void		       *srq_context;
       
   120 +	struct ibv_pd	       *pd;
       
   121 +	uint32_t		handle;
       
   122 +
       
   123 +	uint32_t		events_completed;
       
   124 +
       
   125 +	uint32_t		xrc_srq_num_bin_compat;
       
   126 +	struct ibv_xrc_domain  *xrc_domain_bin_compat;
       
   127 +	struct ibv_cq	       *xrc_cq_bin_compat;
       
   128 +
       
   129 +	pthread_mutex_t		mutex;
       
   130 +	pthread_cond_t		cond;
       
   131 +
       
   132 +	void		       *ibv_srq;
       
   133 +	/*
       
   134 +	 * Below fields are for legacy source compatibility. They reside
       
   135 +	 * on the same offset as of those fields in struct ibv_srq.
       
   136 +	 */
       
   137 +	uint32_t		xrc_srq_num;
       
   138 +	struct ibv_xrc_domain  *xrc_domain;
       
   139 +	struct ibv_cq	       *xrc_cq;
       
   140 +};
       
   141 +
       
   142 +/**
       
   143 + * ibv_open_xrc_domain - open an XRC domain
       
   144 + * Returns a reference to an XRC domain.
       
   145 + *
       
   146 + * @context: Device context
       
   147 + * @fd: descriptor for inode associated with the domain
       
   148 + *     If fd == -1, no inode is associated with the domain; in this ca= se,
       
   149 + *     the only legal value for oflag is O_CREAT
       
   150 + *
       
   151 + * @oflag: oflag values are constructed by OR-ing flags from the following list
       
   152 + *
       
   153 + * O_CREAT
       
   154 + *     If a domain belonging to device named by context is already associated
       
   155 + *     with the inode, this flag has no effect, except as noted under O_EXCL
       
   156 + *     below. Otherwise, a new XRC domain is created and is associated with
       
   157 + *     inode specified by fd.
       
   158 + *
       
   159 + * O_EXCL
       
   160 + *     If O_EXCL and O_CREAT are set, open will fail if a domain associated with
       
   161 + *     the inode exists. The check for the existence of the domain and creation
       
   162 + *     of the domain if it does not exist is atomic with respect to other
       
   163 + *     processes executing open with fd naming the same inode.
       
   164 + */
       
   165 +struct ibv_xrc_domain *ibv_open_xrc_domain(struct ibv_context *context,
       
   166 +					   int fd, int oflag) DEPRECATED;
       
   167 +
       
   168 +/**
       
   169 + * ibv_create_xrc_srq - Creates a SRQ associated with the specified protection
       
   170 + *   domain and xrc domain.
       
   171 + * @pd: The protection domain associated with the SRQ.
       
   172 + * @xrc_domain: The XRC domain associated with the SRQ.
       
   173 + * @xrc_cq: CQ to report completions for XRC packets on.
       
   174 + *
       
   175 + * @srq_init_attr: A list of initial attributes required to create the SRQ.
       
   176 + *
       
   177 + * srq_attr->max_wr and srq_attr->max_sge are read the determine the
       
   178 + * requested size of the SRQ, and set to the actual values allocated
       
   179 + * on return.  If ibv_create_srq() succeeds, then max_wr and max_sge
       
   180 + * will always be at least as large as the requested values.
       
   181 + */
       
   182 +struct ibv_srq *ibv_create_xrc_srq(struct ibv_pd *pd,
       
   183 +				   struct ibv_xrc_domain *xrc_domain,
       
   184 +				   struct ibv_cq *xrc_cq,
       
   185 +				   struct ibv_srq_init_attr *srq_init_attr) DEPRECATED;
       
   186 +
       
   187 +/**
       
   188 + * ibv_close_xrc_domain - close an XRC domain
       
   189 + * If this is the last reference, destroys the domain.
       
   190 + *
       
   191 + * @d: reference to XRC domain to close
       
   192 + *
       
   193 + * close is implicitly performed at process exit.
       
   194 + */
       
   195 +int ibv_close_xrc_domain(struct ibv_xrc_domain *d) DEPRECATED;
       
   196 +
       
   197 +#endif
       
   198 diff -r f8684a1d3f02 include/infiniband/verbs.h
       
   199 --- a/include/infiniband/verbs.h	Mon Nov 21 11:48:20 2016 -0800
       
   200 +++ b/include/infiniband/verbs.h	Mon Mar 20 14:32:42 2017 -0700
       
   201 @@ -42,6 +42,7 @@
       
   202  #include <errno.h>
       
   203  #if defined(__SVR4) && defined(__sun)
       
   204  #include <infiniband/ofa_solaris.h>
       
   205 +#include <infiniband/ofa_verbs.h>
       
   206  #endif
       
   207  
       
   208  #ifdef __cplusplus
       
   209 @@ -252,6 +253,8 @@
       
   210  		struct ibv_srq *srq;
       
   211  		int		port_num;
       
   212  		union ibv_gid	gid;
       
   213 +		/* For source compatibility with legacy API */
       
   214 +		uint32_t	xrc_qp_num;
       
   215  	} element;
       
   216  	enum ibv_event_type	event_type;
       
   217  };
       
   218 @@ -507,6 +510,7 @@
       
   219  	IBV_QPT_RC = 2,
       
   220  	IBV_QPT_UC,
       
   221  	IBV_QPT_UD,
       
   222 +	IBV_QPT_XRC, /* XRC legacy compatible type */
       
   223  	IBV_QPT_RAW_PACKET = 8,
       
   224  	IBV_QPT_XRC_SEND = 9,
       
   225  	IBV_QPT_XRC_RECV
       
   226 @@ -536,6 +540,8 @@
       
   227  	struct ibv_qp_cap	cap;
       
   228  	enum ibv_qp_type	qp_type;
       
   229  	int			sq_sig_all;
       
   230 +	/* Below is needed for legacy compatibility */
       
   231 +	struct ibv_xrc_domain  *xrc_domain;
       
   232  };
       
   233  
       
   234  enum ibv_qp_init_attr_mask {
       
   235 @@ -692,10 +698,14 @@
       
   236  		} ud;
       
   237  	} wr;
       
   238  	union {
       
   239 -		struct {
       
   240 -			uint32_t    remote_srqn;
       
   241 -		} xrc;
       
   242 -	} qp_type;
       
   243 +		union {
       
   244 +		      struct {
       
   245 +			      uint32_t	  remote_srqn;
       
   246 +		      } xrc;
       
   247 +		} qp_type;
       
   248 +
       
   249 +		uint32_t		xrc_remote_srq_num;
       
   250 +	};
       
   251  };
       
   252  
       
   253  struct ibv_recv_wr {
       
   254 @@ -723,6 +733,25 @@
       
   255  	pthread_mutex_t		mutex;
       
   256  	pthread_cond_t		cond;
       
   257  	uint32_t		events_completed;
       
   258 +
       
   259 +       /* 
       
   260 +	* Below is for source compatibility with legacy XRC APIs.
       
   261 +	* Padding is based on ibv_srq_legacy.
       
   262 +	*/
       
   263 +	uint32_t		xrc_srq_num_bin_compat_padding;
       
   264 +	struct ibv_xrc_domain  *xrc_domain_bin_compat_padding;
       
   265 +	struct ibv_cq	       *xrc_cq_bin_compat_padding;
       
   266 +	void		       *ibv_srq_padding;
       
   267 +
       
   268 +	/* legacy fields */
       
   269 +	uint32_t		xrc_srq_num;
       
   270 +	struct ibv_xrc_domain  *xrc_domain;
       
   271 +	struct ibv_cq	       *xrc_cq;
       
   272 +};
       
   273 +
       
   274 +/* XRC source compat layer */
       
   275 +enum ibv_event_flags {
       
   276 +       IBV_XRC_QP_EVENT_FLAG = 0x80000000,
       
   277  };
       
   278  
       
   279  struct ibv_qp {
       
   280 @@ -996,6 +1025,8 @@
       
   281  
       
   282  struct verbs_context {
       
   283  	/*  "grows up" - new fields go here */
       
   284 +	void * (*drv_get_legacy_xrc) (struct ibv_srq *ibv_srq);
       
   285 +	void (*drv_set_legacy_xrc) (struct ibv_srq *ibv_srq, void *legacy_xrc);
       
   286  	int (*drv_ibv_destroy_flow) (struct ibv_flow *flow);
       
   287  	int (*lib_ibv_destroy_flow) (struct ibv_flow *flow);
       
   288  	struct ibv_flow * (*drv_ibv_create_flow) (struct ibv_qp *qp,
       
   289 diff -r f8684a1d3f02 man/ibv_create_qp_ex.3
       
   290 --- a/man/ibv_create_qp_ex.3	Mon Nov 21 11:48:20 2016 -0800
       
   291 +++ b/man/ibv_create_qp_ex.3	Mon Mar 20 14:32:42 2017 -0700
       
   292 @@ -28,7 +28,7 @@
       
   293  struct ibv_cq          *recv_cq;        /* CQ to be associated with the Receive Queue (RQ) */
       
   294  struct ibv_srq         *srq;            /* SRQ handle if QP is to be associated with an SRQ, otherwise NULL */
       
   295  struct ibv_qp_cap       cap;            /* QP capabilities */
       
   296 -enum ibv_qp_type        qp_type;        /* QP Transport Service Type: IBV_QPT_RC, IBV_QPT_UC, IBV_QPT_UD or IBV_QPT_RAW_PACKET */
       
   297 +enum ibv_qp_type        qp_type;        /* QP Transport Service Type: IBV_QPT_RC, IBV_QPT_XRC_SEND, IBV_QPT_XRC_RECV, IBV_QPT_UC, IBV_QPT_UD or IBV_QPT_RAW_PACKET */
       
   298  int                     sq_sig_all;     /* If set, each Work Request (WR) submitted to the SQ generates a completion entry */
       
   299  uint32_t                comp_mask;	/* Identifies valid fields */
       
   300  struct ibv_pd          *pd;		/* PD to be associated with the QP */
       
   301 diff -r f8684a1d3f02 man/ibv_create_xsrq.3
       
   302 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
   303 +++ b/man/ibv_create_xsrq.3	Mon Mar 20 14:32:42 2017 -0700
       
   304 @@ -0,0 +1,87 @@
       
   305 +.\" -*- nroff -*-
       
   306 +.\"
       
   307 +.TH IBV_CREATE_XSRQ 3 2011-06-17 libibverbs "Libibverbs Programmer's Manual"
       
   308 +.SH "NAME"
       
   309 +ibv_create_xsrq, ibv_destroy_srq \- create or destroy a shared receive queue (SRQ)
       
   310 +.SH "SYNOPSIS"
       
   311 +.nf
       
   312 +.B #include 
       
   313 +.sp
       
   314 +.BI "struct ibv_srq *ibv_create_xsrq(struct ibv_pd " "*pd" ", struct "
       
   315 +.BI "                                ibv_srq_init_attr " "*srq_init_attr"
       
   316 +);
       
   317 +.sp
       
   318 +.BI "int ibv_destroy_srq(struct ibv_srq " "*srq" );
       
   319 +.fi
       
   320 +.SH "DESCRIPTION"
       
   321 +.B ibv_create_xsrq()
       
   322 +creates a shared receive queue (SRQ) associated with the protection domain
       
   323 +.I pd\fR.
       
   324 +The argument
       
   325 +.I srq_init_attr
       
   326 +is an ibv_srq_init_attr struct, as defined in .
       
   327 +.PP
       
   328 +.nf
       
   329 +struct ibv_srq_init_attr {
       
   330 +.in +8
       
   331 +void                   *srq_context;    /* Associated context of the SRQ
       
   332 +*/
       
   333 +struct ibv_srq_attr     attr;           /* SRQ attributes */
       
   334 +enum ibv_srq_type       srq_type;       /* Specifies type of SRQ to create
       
   335 +*/
       
   336 +union {
       
   337 +.in +8
       
   338 +struct {
       
   339 +.in +8
       
   340 +struct ibv_xrcd *xrcd;   /* XRC domain associated with an XRC SRQ */
       
   341 +struct ibv_cq   *cq;     /* completion queue for an XRC SRQ*/
       
   342 +.in -8
       
   343 +} xrc;   /* Extended attributes for IBV_SRQT_XRC type SRQs */
       
   344 +.in -8
       
   345 +} ext;
       
   346 +.in -8
       
   347 +};
       
   348 +.sp
       
   349 +.nf
       
   350 +struct ibv_srq_attr {
       
   351 +.in +8
       
   352 +uint32_t                max_wr;         /* Requested max number of
       
   353 +outstanding work requests (WRs) in the SRQ */
       
   354 +uint32_t                max_sge;        /* Requested max number of scatter
       
   355 +elements per WR */
       
   356 +uint32_t                srq_limit;      /* The limit value of the SRQ
       
   357 +(ignored for ibv_create_srq) */
       
   358 +.in -8
       
   359 +};
       
   360 +.fi
       
   361 +.PP
       
   362 +The function
       
   363 +.B ibv_create_xsrq()
       
   364 +will update the
       
   365 +.I srq_init_attr
       
   366 +struct with the original values of the SRQ that was created; the
       
   367 +values of max_wr and max_sge will be greater than or equal to the
       
   368 +values requested.
       
   369 +.PP
       
   370 +.B ibv_destroy_srq()
       
   371 +destroys the SRQ
       
   372 +.I srq\fR.
       
   373 +.SH "RETURN VALUE"
       
   374 +.B ibv_create_xsrq()
       
   375 +returns a pointer to the created SRQ, or NULL if the request fails.
       
   376 +.PP
       
   377 +.B ibv_destroy_srq()
       
   378 +returns 0 on success, or the value of errno on failure (which indicates
       
   379 +the failure reason).
       
   380 +.SH "NOTES"
       
   381 +.B ibv_destroy_srq()
       
   382 +fails if any queue pair is still associated with this SRQ.
       
   383 +.SH "SEE ALSO"
       
   384 +.BR ibv_alloc_pd (3),
       
   385 +.BR ibv_create_cq (3),
       
   386 +.BR ibv_open_xrcd (3),
       
   387 +.BR ibv_modify_srq (3),
       
   388 +.BR ibv_query_srq (3)
       
   389 +.SH "AUTHORS"
       
   390 +.TP
       
   391 +Sean Hefty
       
   392 diff -r f8684a1d3f02 man/ibv_xsrq_pingpong.1
       
   393 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
       
   394 +++ b/man/ibv_xsrq_pingpong.1	Mon Mar 20 14:32:42 2017 -0700
       
   395 @@ -0,0 +1,71 @@
       
   396 +.TH IBV_XSRQ_PINGPONG 1 "May 24, 2016" "libibverbs" "USER COMMANDS"
       
   397 +
       
   398 +.SH NAME
       
   399 +ibv_xsrq_pingpong \- simple InfiniBand shared receive queue test
       
   400 +
       
   401 +.SH SYNOPSIS
       
   402 +.B ibv_xsrq_pingpong
       
   403 +[\-p port] [\-d device] [\-i ib port] [\-s size] [\-m mtu] [\-c clients]
       
   404 +[\-n num_tests] [\-l sl] [\-e] \fBHOSTNAME\fR
       
   405 +
       
   406 +.B ibv_xsrq_pingpong
       
   407 +[\-p port] [\-d device] [\-i ib port] [\-s size] [\-m mtu] [\-c clients]
       
   408 +[\-n num_tests] [\-l sl] [\-e]
       
   409 +
       
   410 +.SH DESCRIPTION
       
   411 +.PP
       
   412 +Run a simple ping-pong test over InfiniBand via the extended reliable
       
   413 +connected (XRC) transport service, using a shared receive queue (SRQ).
       
   414 +
       
   415 +.SH OPTIONS
       
   416 +
       
   417 +.PP
       
   418 +.TP
       
   419 +\fB\-p\fR, \fB\-\-port\fR=\fIPORT\fR
       
   420 +use TCP port \fIPORT\fR for initial synchronization (default 18515)
       
   421 +.TP
       
   422 +\fB\-d\fR, \fB\-\-ib\-dev\fR=\fIDEVICE\fR
       
   423 +use IB device \fIDEVICE\fR (default first device found)
       
   424 +.TP
       
   425 +\fB\-i\fR, \fB\-\-ib\-port\fR=\fIPORT\fR
       
   426 +use IB port \fIPORT\fR (default port 1)
       
   427 +.TP
       
   428 +\fB\-s\fR, \fB\-\-size\fR=\fISIZE\fR
       
   429 +ping-pong messages of size \fISIZE\fR (default 4096)
       
   430 +.TP
       
   431 +\fB\-m\fR, \fB\-\-mtu\fR=\fIMTU\fR
       
   432 +use path mtu of size \fIMTU\fR (default 2048)
       
   433 +.TP
       
   434 +\fB\-c\fR, \fB\-\-clients\fR=\fICLIENTS\fR
       
   435 +number of clients \fICLIENTS\fR (on server only, default 1)
       
   436 +.TP
       
   437 +\fB\-n\fR, \fB\-\-num\-tests\fR=\fINUM_TESTS\fR
       
   438 +perform \fINUM_TESTS\fR tests per client (default 5)
       
   439 +.TP
       
   440 +\fB\-l\fR, \fB\-\-sl\fR=\fISL\fR
       
   441 +use \fISL\fR as the service level value (default 0)
       
   442 +.TP
       
   443 +\fB\-e\fR, \fB\-\-events\fR
       
   444 +sleep while waiting for work completion events (default is to poll for
       
   445 +completions)
       
   446 +
       
   447 +.SH SEE ALSO
       
   448 +.BR ibv_rc_pingpong (1),
       
   449 +.BR ibv_uc_pingpong (1),
       
   450 +.BR ibv_ud_pingpong (1)
       
   451 +.BR ibv_srq_pingpong (1)
       
   452 +
       
   453 +.SH AUTHORS
       
   454 +.TP
       
   455 +Roland Dreier
       
   456 +.RI < [email protected] >
       
   457 +.TP
       
   458 +Jarod Wilson
       
   459 +.RI < [email protected] >
       
   460 +
       
   461 +.SH BUGS
       
   462 +The network synchronization between client and server instances is
       
   463 +weak, and does not prevent incompatible options from being used on the
       
   464 +two instances.  The method used for retrieving work completions is not
       
   465 +strictly correct, and race conditions may cause failures on some
       
   466 +systems.
       
   467 diff -r f8684a1d3f02 src/cmd.c
       
   468 --- a/src/cmd.c	Mon Nov 21 11:48:20 2016 -0800
       
   469 +++ b/src/cmd.c	Mon Mar 20 14:32:42 2017 -0700
       
   470 @@ -815,6 +815,7 @@
       
   471  	cmd->user_handle     = (uintptr_t) qp;
       
   472  
       
   473  	if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) {
       
   474 +	        /* XRC receive side */
       
   475  		vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
       
   476  		cmd->pd_handle	= vxrcd->handle;
       
   477  	} else {
       
   478 @@ -824,7 +825,9 @@
       
   479  		cmd->pd_handle	= attr_ex->pd->handle;
       
   480  		cmd->send_cq_handle = attr_ex->send_cq->handle;
       
   481  
       
   482 -		if (attr_ex->qp_type != IBV_QPT_XRC_SEND) {
       
   483 +		/* XRC sender doesn't have a receive cq */
       
   484 +		if (attr_ex->qp_type != IBV_QPT_XRC_SEND &&
       
   485 +			attr_ex->qp_type != IBV_QPT_XRC) {
       
   486  			cmd->recv_cq_handle = attr_ex->recv_cq->handle;
       
   487  			cmd->srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0;
       
   488  		}
       
   489 @@ -847,7 +850,8 @@
       
   490  #else
       
   491  	cmd->sq_sig_all	     = attr_ex->sq_sig_all;
       
   492  #endif
       
   493 -	cmd->qp_type         = attr_ex->qp_type;
       
   494 +	cmd->qp_type	     = (attr_ex->qp_type == IBV_QPT_XRC) ?
       
   495 +				IBV_QPT_XRC_SEND : attr_ex->qp_type;
       
   496  	cmd->is_srq	     = !!attr_ex->srq;
       
   497  	cmd->reserved	     = 0;
       
   498  
       
   499 @@ -1215,6 +1219,9 @@
       
   500  			tmp->wr.ud.remote_qpn  = i->wr.ud.remote_qpn;
       
   501  			tmp->wr.ud.remote_qkey = i->wr.ud.remote_qkey;
       
   502  		} else {
       
   503 +			if (ibqp->qp_type == IBV_QPT_XRC_SEND)
       
   504 +				tmp->qp_type.xrc.remote_srqn =
       
   505 +					i->qp_type.xrc.remote_srqn;
       
   506  			switch (i->opcode) {
       
   507  			case IBV_WR_RDMA_WRITE:
       
   508  			case IBV_WR_RDMA_WRITE_WITH_IMM:
       
   509 diff -r f8684a1d3f02 src/device.c
       
   510 --- a/src/device.c	Mon Nov 21 11:48:20 2016 -0800
       
   511 +++ b/src/device.c	Mon Mar 20 14:32:42 2017 -0700
       
   512 @@ -261,6 +261,9 @@
       
   513  			  struct ibv_async_event *event)
       
   514  {
       
   515  	struct ibv_kern_async_event ev;
       
   516 +	struct verbs_context *vctx;
       
   517 +	struct ibv_srq_legacy *ibv_srq_legacy = NULL;
       
   518 +	struct ibv_qp *qp;
       
   519  
       
   520  	if (read(context->async_fd, &ev, sizeof ev) != sizeof ev)
       
   521  		return -1;
       
   522 @@ -281,11 +284,24 @@
       
   523  	case IBV_EVENT_PATH_MIG_ERR:
       
   524  	case IBV_EVENT_QP_LAST_WQE_REACHED:
       
   525  		event->element.qp = (void *) (uintptr_t) ev.element;
       
   526 +		qp = ibv_find_xrc_qp(event->element.qp->qp_num);
       
   527 +		if (qp) {
       
   528 +			/* This is an XRC receive QP created by the legacy API */
       
   529 +			event->event_type |= IBV_XRC_QP_EVENT_FLAG;
       
   530 +			event->element.qp = NULL;
       
   531 +			event->element.xrc_qp_num = qp->qp_num;
       
   532 +		}		
       
   533  		break;
       
   534  
       
   535  	case IBV_EVENT_SRQ_ERR:
       
   536  	case IBV_EVENT_SRQ_LIMIT_REACHED:
       
   537 -		event->element.srq = (void *) (uintptr_t) ev.element;
       
   538 +		vctx = verbs_get_ctx_op(context, drv_get_legacy_xrc);
       
   539 +		if (vctx)
       
   540 +			ibv_srq_legacy =
       
   541 +			  vctx->drv_get_legacy_xrc((void *) (uintptr_t) ev.element);
       
   542 +
       
   543 +		event->element.srq = (ibv_srq_legacy) ? (void *)ibv_srq_legacy :
       
   544 +			(void *) (uintptr_t) ev.element;
       
   545  		break;
       
   546  	case IBV_EVENT_GID_AVAIL:
       
   547  	case IBV_EVENT_GID_UNAVAIL:
       
   548 @@ -310,6 +326,12 @@
       
   549  
       
   550  void __ibv_ack_async_event(struct ibv_async_event *event)
       
   551  {
       
   552 +	int is_legacy_xrc = 0;
       
   553 +	if (event->event_type & IBV_XRC_QP_EVENT_FLAG) {
       
   554 +		event->event_type ^= IBV_XRC_QP_EVENT_FLAG;
       
   555 +		is_legacy_xrc = 1;
       
   556 +	}
       
   557 +
       
   558  	switch (event->event_type) {
       
   559  	case IBV_EVENT_CQ_ERR:
       
   560  	{
       
   561 @@ -334,6 +356,16 @@
       
   562  	{
       
   563  		struct ibv_qp *qp = event->element.qp;
       
   564  
       
   565 +		if (is_legacy_xrc) {
       
   566 +			qp = ibv_find_xrc_qp(event->element.xrc_qp_num);
       
   567 +			if (!qp || qp->qp_num != event->element.xrc_qp_num) {
       
   568 +				fprintf(stderr, PFX "Warning: ibv_ack_async_event, "
       
   569 +					"XRC qpn=%u wasn't found\n",
       
   570 +					event->element.xrc_qp_num);
       
   571 +				return;
       
   572 +			}
       
   573 +		}
       
   574 +
       
   575  		pthread_mutex_lock(&qp->mutex);
       
   576  		++qp->events_completed;
       
   577  		pthread_cond_signal(&qp->cond);
       
   578 @@ -347,6 +379,12 @@
       
   579  	{
       
   580  		struct ibv_srq *srq = event->element.srq;
       
   581  
       
   582 +		if (srq->handle == LEGACY_XRC_SRQ_HANDLE) {
       
   583 +		       struct ibv_srq_legacy *ibv_srq_legacy =
       
   584 +				       (struct ibv_srq_legacy *) srq;
       
   585 +		       srq = ibv_srq_legacy->ibv_srq;
       
   586 +		}
       
   587 +
       
   588  		pthread_mutex_lock(&srq->mutex);
       
   589  		++srq->events_completed;
       
   590  		pthread_cond_signal(&srq->cond);
       
   591 diff -r f8684a1d3f02 src/ibverbs.h
       
   592 --- a/src/ibverbs.h	Mon Nov 21 11:48:20 2016 -0800
       
   593 +++ b/src/ibverbs.h	Mon Mar 20 14:32:42 2017 -0700
       
   594 @@ -85,6 +85,7 @@
       
   595  extern HIDDEN int abi_ver;
       
   596  
       
   597  HIDDEN int ibverbs_init(struct ibv_device ***list);
       
   598 +HIDDEN struct ibv_qp *ibv_find_xrc_qp(uint32_t qpn);
       
   599  
       
   600  #define IBV_INIT_CMD(cmd, size, opcode)					\
       
   601  	do {								\
       
   602 diff -r f8684a1d3f02 src/libibverbs.map
       
   603 --- a/src/libibverbs.map	Mon Nov 21 11:48:20 2016 -0800
       
   604 +++ b/src/libibverbs.map	Mon Mar 20 14:32:42 2017 -0700
       
   605 @@ -124,4 +124,7 @@
       
   606  		ibv_cmd_create_qp_ex;
       
   607  		ibv_cmd_open_qp;
       
   608  
       
   609 +		ibv_open_xrc_domain;
       
   610 +		ibv_create_xrc_srq;
       
   611 +		ibv_close_xrc_domain;
       
   612  } IBVERBS_1.0;
       
   613 diff -r f8684a1d3f02 src/verbs.c
       
   614 --- a/src/verbs.c	Mon Nov 21 11:48:20 2016 -0800
       
   615 +++ b/src/verbs.c	Mon Mar 20 14:32:42 2017 -0700
       
   616 @@ -41,6 +41,7 @@
       
   617  #include <stdlib.h>
       
   618  #include <errno.h>
       
   619  #include <string.h>
       
   620 +#include <search.h>
       
   621  #if defined(__SVR4) && defined(__sun)
       
   622  #include <fcntl.h>
       
   623  #include <sys/stat.h>
       
   624 @@ -854,3 +855,208 @@
       
   625  	return qp->context->ops.detach_mcast(qp, gid, lid);
       
   626  }
       
   627  default_symver(__ibv_detach_mcast, ibv_detach_mcast);
       
   628 +
       
   629 +
       
   630 +/* XRC compatibility layer */
       
   631 +struct ibv_xrc_domain *ibv_open_xrc_domain(struct ibv_context *context,
       
   632 +					   int fd, int oflag)
       
   633 +{
       
   634 +
       
   635 +	struct ibv_xrcd *ibv_xrcd;
       
   636 +	struct ibv_xrcd_init_attr xrcd_init_attr;
       
   637 +
       
   638 +	memset(&xrcd_init_attr, 0, sizeof(xrcd_init_attr));
       
   639 +
       
   640 +	xrcd_init_attr.fd = fd;
       
   641 +	xrcd_init_attr.oflags = oflag;
       
   642 +
       
   643 +	xrcd_init_attr.comp_mask = IBV_XRCD_INIT_ATTR_FD |
       
   644 +					IBV_XRCD_INIT_ATTR_OFLAGS;
       
   645 +
       
   646 +	ibv_xrcd = ibv_open_xrcd(context, &xrcd_init_attr);
       
   647 +	if (!ibv_xrcd)
       
   648 +		return NULL;
       
   649 +
       
   650 +	return (struct ibv_xrc_domain *)ibv_xrcd;
       
   651 +
       
   652 +}
       
   653 +
       
   654 +
       
   655 +struct ibv_srq *ibv_create_xrc_srq(struct ibv_pd *pd,
       
   656 +				   struct ibv_xrc_domain *xrc_domain,
       
   657 +				   struct ibv_cq *xrc_cq,
       
   658 +				   struct ibv_srq_init_attr *srq_init_attr)
       
   659 +{
       
   660 +
       
   661 +	struct ibv_srq_init_attr_ex ibv_srq_init_attr_ex;
       
   662 +	struct ibv_srq_legacy *ibv_srq_legacy;
       
   663 +	struct ibv_srq *ibv_srq;
       
   664 +	uint32_t		xrc_srq_num;
       
   665 +	struct verbs_context *vctx;
       
   666 +
       
   667 +	vctx = verbs_get_ctx_op(pd->context, drv_set_legacy_xrc);
       
   668 +	if (!vctx) {
       
   669 +		errno = ENOSYS;
       
   670 +		return NULL;
       
   671 +	}
       
   672 +	memset(&ibv_srq_init_attr_ex, 0, sizeof ibv_srq_init_attr_ex);
       
   673 +
       
   674 +	ibv_srq_init_attr_ex.xrcd = (struct ibv_xrcd *)xrc_domain;
       
   675 +	ibv_srq_init_attr_ex.comp_mask = IBV_SRQ_INIT_ATTR_XRCD |
       
   676 +				IBV_SRQ_INIT_ATTR_TYPE |
       
   677 +				IBV_SRQ_INIT_ATTR_CQ | IBV_SRQ_INIT_ATTR_PD;
       
   678 +
       
   679 +	ibv_srq_init_attr_ex.cq = xrc_cq;
       
   680 +	ibv_srq_init_attr_ex.pd = pd;
       
   681 +	ibv_srq_init_attr_ex.srq_type = IBV_SRQT_XRC;
       
   682 +
       
   683 +	ibv_srq_init_attr_ex.attr.max_sge = srq_init_attr->attr.max_sge;
       
   684 +	ibv_srq_init_attr_ex.attr.max_wr = srq_init_attr->attr.max_wr;
       
   685 +	ibv_srq_init_attr_ex.attr.srq_limit = srq_init_attr->attr.srq_limit;
       
   686 +	ibv_srq_init_attr_ex.srq_context = srq_init_attr->srq_context;
       
   687 +
       
   688 +	ibv_srq = ibv_create_srq_ex(pd->context, &ibv_srq_init_attr_ex);
       
   689 +	if (!ibv_srq)
       
   690 +		return NULL;
       
   691 +
       
   692 +	if (ibv_srq->handle == LEGACY_XRC_SRQ_HANDLE) {
       
   693 +
       
   694 +		struct ibv_srq *ibv_srq_tmp = ibv_srq;
       
   695 +		int ret;
       
   696 +
       
   697 +		ibv_srq = ibv_create_srq_ex(pd->context, &ibv_srq_init_attr_ex);
       
   698 +
       
   699 +		ret = ibv_destroy_srq(ibv_srq_tmp);
       
   700 +		if (ret) {
       
   701 +			fprintf(stderr, PFX "ibv_create_xrc_srq, "
       
   702 +				"fail to destroy intermediate srq\n");
       
   703 +			return NULL;
       
   704 +		}
       
   705 +
       
   706 +		if (!ibv_srq)
       
   707 +			return NULL;
       
   708 +
       
   709 +		if (ibv_srq->handle == LEGACY_XRC_SRQ_HANDLE) {
       
   710 +			ret = ibv_destroy_srq(ibv_srq);
       
   711 +			if (ret)
       
   712 +				fprintf(stderr, PFX "ibv_create_xrc_srq, "
       
   713 +					"fail to destroy intermediate srq\n");
       
   714 +			errno = EAGAIN;
       
   715 +			return NULL;
       
   716 +		}
       
   717 +	}
       
   718 +
       
   719 +	ibv_srq_legacy = calloc(1, sizeof(*ibv_srq_legacy));
       
   720 +	if (!ibv_srq_legacy) {
       
   721 +		errno = ENOMEM;
       
   722 +		goto err;
       
   723 +	}
       
   724 +
       
   725 +	if (ibv_get_srq_num(ibv_srq, &xrc_srq_num))
       
   726 +		goto err_free;
       
   727 +
       
   728 +	ibv_srq_legacy->ibv_srq = ibv_srq;
       
   729 +	ibv_srq_legacy->xrc_srq_num = xrc_srq_num;
       
   730 +
       
   731 +	/* Setting the bin compat fields */
       
   732 +	ibv_srq_legacy->xrc_srq_num_bin_compat = xrc_srq_num;
       
   733 +	ibv_srq_legacy->xrc_domain_bin_compat = xrc_domain;
       
   734 +	ibv_srq_legacy->xrc_cq_bin_compat = xrc_cq;
       
   735 +	ibv_srq_legacy->context          = pd->context;
       
   736 +	ibv_srq_legacy->srq_context      = srq_init_attr->srq_context;
       
   737 +	ibv_srq_legacy->pd		 = pd;
       
   738 +	/*
       
   739 +	 * Set an indication that this is a legacy structure. For legacy structures,
       
   740 +	 * we should use the internal ibv_srq.
       
   741 +	 */
       
   742 +	ibv_srq_legacy->handle		 = LEGACY_XRC_SRQ_HANDLE;
       
   743 +	ibv_srq_legacy->xrc_domain	 = xrc_domain;
       
   744 +	ibv_srq_legacy->xrc_cq		 = xrc_cq;
       
   745 +	ibv_srq_legacy->events_completed = 0;
       
   746 +
       
   747 +	srq_init_attr->attr.max_wr = ibv_srq_init_attr_ex.attr.max_wr;
       
   748 +	srq_init_attr->attr.max_sge = ibv_srq_init_attr_ex.attr.max_sge;
       
   749 +
       
   750 +	vctx->drv_set_legacy_xrc(ibv_srq, ibv_srq_legacy);
       
   751 +	return (struct ibv_srq *)(ibv_srq_legacy);
       
   752 +
       
   753 +err_free:
       
   754 +	free(ibv_srq_legacy);
       
   755 +err:
       
   756 +	ibv_destroy_srq(ibv_srq);
       
   757 +	return NULL;
       
   758 +
       
   759 +}
       
   760 +
       
   761 +static pthread_mutex_t xrc_tree_mutex = PTHREAD_MUTEX_INITIALIZER;
       
   762 +static void *ibv_xrc_qp_tree;
       
   763 +
       
   764 +static int xrc_qp_compare(const void *a, const void *b)
       
   765 +{
       
   766 +
       
   767 +	if ((*(uint32_t *) a) < (*(uint32_t *) b))
       
   768 +	       return -1;
       
   769 +	else if ((*(uint32_t *) a) > (*(uint32_t *) b))
       
   770 +	       return 1;
       
   771 +	else
       
   772 +	       return 0;
       
   773 +
       
   774 +}
       
   775 +
       
   776 +struct ibv_qp *ibv_find_xrc_qp(uint32_t qpn)
       
   777 +{
       
   778 +	uint32_t **qpn_ptr;
       
   779 +	struct ibv_qp *ibv_qp = NULL;
       
   780 +
       
   781 +	pthread_mutex_lock(&xrc_tree_mutex);
       
   782 +	qpn_ptr = tfind(&qpn, &ibv_xrc_qp_tree, xrc_qp_compare);
       
   783 +	if (!qpn_ptr)
       
   784 +		goto end;
       
   785 +
       
   786 +	ibv_qp = container_of(*qpn_ptr, struct ibv_qp, qp_num);
       
   787 +
       
   788 +end:
       
   789 +	pthread_mutex_unlock(&xrc_tree_mutex);
       
   790 +	return ibv_qp;
       
   791 +}
       
   792 +
       
   793 +static int ibv_clear_xrc_qp(uint32_t qpn)
       
   794 +{
       
   795 +	uint32_t **qpn_ptr;
       
   796 +	int ret = 0;
       
   797 +
       
   798 +	pthread_mutex_lock(&xrc_tree_mutex);
       
   799 +	qpn_ptr = tdelete(&qpn, &ibv_xrc_qp_tree, xrc_qp_compare);
       
   800 +	if (!qpn_ptr)
       
   801 +		ret = EINVAL;
       
   802 +
       
   803 +	pthread_mutex_unlock(&xrc_tree_mutex);
       
   804 +	return ret;
       
   805 +}
       
   806 +
       
   807 +static int ibv_store_xrc_qp(struct ibv_qp *qp)
       
   808 +{
       
   809 +	uint32_t **qpn_ptr;
       
   810 +	int ret = 0;
       
   811 +
       
   812 +	if (ibv_find_xrc_qp(qp->qp_num)) {
       
   813 +		fprintf(stderr, PFX "ibv_store_xrc_qp failed, qpn=%u is already stored\n",
       
   814 +				qp->qp_num);
       
   815 +		return EEXIST;
       
   816 +	}
       
   817 +
       
   818 +	pthread_mutex_lock(&xrc_tree_mutex);
       
   819 +	qpn_ptr = tsearch(&qp->qp_num, &ibv_xrc_qp_tree, xrc_qp_compare);
       
   820 +	if (!qpn_ptr)
       
   821 +		ret = EINVAL;
       
   822 +
       
   823 +	pthread_mutex_unlock(&xrc_tree_mutex);
       
   824 +	return ret;
       
   825 +
       
   826 +}
       
   827 +
       
   828 +int ibv_close_xrc_domain(struct ibv_xrc_domain *d)
       
   829 +{
       
   830 +	struct ibv_xrcd *ibv_xrcd = (struct ibv_xrcd *)d;
       
   831 +	return ibv_close_xrcd(ibv_xrcd);
       
   832 +}