[Pkg-ofed-commits] [perftest] 02/06: Imported Upstream version 3.0+0.16.gb2f2e82

Mehdi Dogguy mehdi at moszumanska.debian.org
Thu Dec 31 19:05:25 UTC 2015


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

mehdi pushed a commit to branch master
in repository perftest.

commit 97f67597a308460b1dc59b9a5517d4e431bd2a33
Author: Mehdi Dogguy <mehdi at debian.org>
Date:   Thu Dec 31 10:47:08 2015 +0100

    Imported Upstream version 3.0+0.16.gb2f2e82
---
 .gitignore                   |  18 +++
 perftest.spec                |   4 +-
 src/get_clock.c              |  23 +--
 src/perftest_communication.c |  98 +++++++------
 src/perftest_parameters.c    | 120 ++++++++++++---
 src/perftest_parameters.h    |   6 +
 src/perftest_resources.c     | 343 ++++++++++++++++++++++++++++++-------------
 src/perftest_resources.h     |  38 ++++-
 src/raw_ethernet_resources.c |  19 ++-
 src/raw_ethernet_resources.h |   2 +-
 src/raw_ethernet_send_bw.c   |   9 +-
 src/raw_ethernet_send_lat.c  |   8 +-
 src/send_lat.c               |  57 ++-----
 13 files changed, 505 insertions(+), 240 deletions(-)

diff --git a/.gitignore b/.gitignore
index 41d3288..b3f5ecf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,21 @@ stamp-h1
 
 #Ctags
 tags
+
+#Programs
+ib_atomic_bw
+ib_atomic_lat
+ib_read_bw
+ib_read_lat
+ib_send_bw
+ib_send_lat
+ib_write_bw
+ib_write_lat
+raw_ethernet_bw
+raw_ethernet_lat
+
+#Debian Stuff
+debian/compat
+debian/*.log
+debian/files
+debian/perftest
diff --git a/perftest.spec b/perftest.spec
index ada14d5..a087377 100644
--- a/perftest.spec
+++ b/perftest.spec
@@ -1,10 +1,10 @@
 Name:           perftest
 Summary:        IB Performance tests
 Version: 3.0
-Release: 0.9.g214990b
+Release: 0.16.gb2f2e82
 License:        BSD 3-Clause, GPL v2 or later
 Group:          Productivity/Networking/Diagnostic
-Source: http://www.openfabrics.org/downloads/perftest-3.0-0.9.g214990b.tar.gz
+Source: http://www.openfabrics.org/downloads/perftest-3.0-0.16.gb2f2e82.tar.gz
 Url:            http://www.openfabrics.org
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  libibverbs-devel librdmacm-devel libibumad-devel
diff --git a/src/get_clock.c b/src/get_clock.c
index 5a09b9f..9b0c23e 100755
--- a/src/get_clock.c
+++ b/src/get_clock.c
@@ -134,7 +134,7 @@ static double sample_get_cpu_mhz(void)
 }
 
 #ifndef __s390x__
-static double proc_get_cpu_mhz(int no_cpu_freq_fail)
+static double proc_get_cpu_mhz(int no_cpu_freq_warn)
 {
 	FILE* f;
 	char buf[256];
@@ -185,13 +185,9 @@ static double proc_get_cpu_mhz(int no_cpu_freq_fail)
 		delta = mhz > m ? mhz - m : m - mhz;
 		if ((delta / mhz > 0.02) && (print_flag ==0)) {
 			print_flag = 1;
-			fprintf(stderr, "Conflicting CPU frequency values"
-					" detected: %lf != %lf\n", mhz, m);
-			if (no_cpu_freq_fail) {
-				fprintf(stderr, "Test integrity may be harmed !\n");
-			} else {
-				fclose(f);
-				return 0.0;
+			if (!no_cpu_freq_warn) {
+				fprintf(stderr, "Conflicting CPU frequency values"
+						" detected: %lf != %lf. CPU Frequency is not max.\n", mhz, m);
 			}
 			continue;
 		}
@@ -202,14 +198,14 @@ static double proc_get_cpu_mhz(int no_cpu_freq_fail)
 }
 #endif
 
-double get_cpu_mhz(int no_cpu_freq_fail)
+double get_cpu_mhz(int no_cpu_freq_warn)
 {
 	#ifdef __s390x__
 	return sample_get_cpu_mgz();
 	#else
 	double sample, proc, delta;
 	sample = sample_get_cpu_mhz();
-	proc = proc_get_cpu_mhz(no_cpu_freq_fail);
+	proc = proc_get_cpu_mhz(no_cpu_freq_warn);
 	#ifdef __aarch64__
 	if (proc < 1)
 		proc = sample;
@@ -219,13 +215,6 @@ double get_cpu_mhz(int no_cpu_freq_fail)
 
 	delta = proc > sample ? proc - sample : sample - proc;
 	if (delta / proc > 0.02) {
-		#if !defined (__PPC__) && !defined (__PPC64__)
-		fprintf(stderr, "Warning: measured timestamp frequency "
-				"%g differs from nominal %g MHz\n",
-				sample, proc);
-		if (!no_cpu_freq_fail)
-			fprintf(stderr, "         Add --CPU-freq flag to show report\n");
-		#endif
 		return sample;
 	}
 	return proc;
diff --git a/src/perftest_communication.c b/src/perftest_communication.c
index 4a5c2e1..cd219fd 100755
--- a/src/perftest_communication.c
+++ b/src/perftest_communication.c
@@ -64,9 +64,9 @@ static int post_one_recv_wqe(struct pingpong_context *ctx)
 	struct ibv_recv_wr *bad_wr;
 	struct ibv_sge list;
 
-	list.addr   = (uintptr_t)ctx->buf;
+	list.addr   = (uintptr_t)ctx->buf[0];
 	list.length = sizeof(struct pingpong_dest);
-	list.lkey   = ctx->mr->lkey;
+	list.lkey   = ctx->mr[0]->lkey;
 
 	wr.next = NULL;
 	wr.wr_id = SYNC_SPEC_ID;
@@ -90,9 +90,9 @@ static int post_recv_to_get_ah(struct pingpong_context *ctx)
 	struct ibv_recv_wr *bad_wr;
 	struct ibv_sge list;
 
-	list.addr   = (uintptr_t)ctx->buf;
+	list.addr   = (uintptr_t)ctx->buf[0];
 	list.length = UD_ADDITION + sizeof(uint32_t);
-	list.lkey   = ctx->mr->lkey;
+	list.lkey   = ctx->mr[0]->lkey;
 
 	wr.next = NULL;
 	wr.wr_id = 0;
@@ -120,11 +120,11 @@ static int send_qp_num_for_ah(struct pingpong_context *ctx,
 	struct ibv_wc wc;
 	int ne;
 
-	memcpy(ctx->buf,&ctx->qp[0]->qp_num,sizeof(uint32_t));
+	memcpy(ctx->buf[0], &ctx->qp[0]->qp_num, sizeof(uint32_t));
 
-	list.addr   = (uintptr_t)ctx->buf;
+	list.addr   = (uintptr_t)ctx->buf[0];
 	list.length = sizeof(uint32_t);
-	list.lkey   = ctx->mr->lkey;
+	list.lkey   = ctx->mr[0]->lkey;
 
 	wr.wr_id      = 0;
 	wr.sg_list    = &list;
@@ -177,7 +177,7 @@ static int create_ah_from_wc_recv(struct pingpong_context *ctx,
 		return 1;
 	}
 
-	ctx->ah[0] = ibv_create_ah_from_wc(ctx->pd,&wc,(struct ibv_grh*)ctx->buf,ctx->cm_id->port_num);
+	ctx->ah[0] = ibv_create_ah_from_wc(ctx->pd, &wc, (struct ibv_grh*)ctx->buf[0], ctx->cm_id->port_num);
 	user_param->rem_ud_qpn = ntohl(wc.imm_data);
 	ibv_query_qp(ctx->qp[0],&attr, IBV_QP_QKEY,&init_attr);
 	user_param->rem_ud_qkey = attr.qkey;
@@ -358,13 +358,13 @@ static int rdma_write_keys(struct pingpong_dest *my_dest,
 		m_my_dest.gid.raw[i] = my_dest->gid.raw[i];
 	}
 
-	memcpy(comm->rdma_ctx->buf, &m_my_dest, sizeof(struct pingpong_dest));
+	memcpy(comm->rdma_ctx->buf[0], &m_my_dest, sizeof(struct pingpong_dest));
 	#else
-	memcpy(comm->rdma_ctx->buf, &my_dest, sizeof(struct pingpong_dest));
+	memcpy(comm->rdma_ctx->buf[0], &my_dest, sizeof(struct pingpong_dest));
 	#endif
-	list.addr   = (uintptr_t)comm->rdma_ctx->buf;
+	list.addr   = (uintptr_t)comm->rdma_ctx->buf[0];
 	list.length = sizeof(struct pingpong_dest);
-	list.lkey   = comm->rdma_ctx->mr->lkey;
+	list.lkey   = comm->rdma_ctx->mr[0]->lkey;
 
 
 	wr.wr_id      = SYNC_SPEC_ID;
@@ -413,7 +413,7 @@ static int rdma_read_keys(struct pingpong_dest *rem_dest,
 	}
 
 	#ifdef HAVE_ENDIAN
-	memcpy(&a_rem_dest,comm->rdma_ctx->buf,sizeof(struct pingpong_dest));
+	memcpy(&a_rem_dest,comm->rdma_ctx->buf[0],sizeof(struct pingpong_dest));
 	rem_dest->lid   = ntohl(a_rem_dest.lid);
 	rem_dest->out_reads     = ntohl(a_rem_dest.out_reads);
 	rem_dest->qpn   = ntohl(a_rem_dest.qpn);
@@ -423,7 +423,7 @@ static int rdma_read_keys(struct pingpong_dest *rem_dest,
 	rem_dest->vaddr         = be64toh(a_rem_dest.vaddr);
 	memcpy(rem_dest->gid.raw, &(a_rem_dest.gid), 16*sizeof(uint8_t));
 	#else
-	memcpy(&rem_dest,comm->rdma_ctx->buf,sizeof(struct pingpong_dest));
+	memcpy(&rem_dest,comm->rdma_ctx->buf[0],sizeof(struct pingpong_dest));
 	#endif
 
 	if (post_one_recv_wqe(comm->rdma_ctx)) {
@@ -625,11 +625,14 @@ int set_up_connection(struct pingpong_context *ctx,
 
 		my_dest[i].qpn   = ctx->qp[i]->qp_num;
 		my_dest[i].psn   = lrand48() & 0xffffff;
-		my_dest[i].rkey  = ctx->mr->rkey;
+		my_dest[i].rkey  = ctx->mr[i]->rkey;
 
 		/* Each qp gives his receive buffer address.*/
 		my_dest[i].out_reads = user_param->out_reads;
-		my_dest[i].vaddr = (uintptr_t)ctx->buf + (user_param->num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		if (user_param->mr_per_qp)
+			my_dest[i].vaddr = (uintptr_t)ctx->buf[i] + BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		else
+			my_dest[i].vaddr = (uintptr_t)ctx->buf[0] + (user_param->num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
 
 		if (user_param->dualport==ON) {
 
@@ -783,7 +786,7 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters
 	temp = user_param->work_rdma_cm;
 	user_param->work_rdma_cm = ON;
 
-	if (ctx_init(ctx,user_param)) {
+	if (ctx_init(ctx, user_param)) {
 		fprintf(stderr," Unable to create the resources needed by comm struct\n");
 		return FAILURE;
 	}
@@ -862,7 +865,6 @@ int retry_rdma_connect(struct pingpong_context *ctx,
 		}
 		if (rdma_client_connect(ctx,user_param) == SUCCESS)
 			return SUCCESS;
-
 		if (destroy_rdma_resources(ctx,user_param)) {
 			fprintf(stderr,"Unable to destroy rdma resources\n");
 			return FAILURE;
@@ -992,30 +994,33 @@ int rdma_server_connect(struct pingpong_context *ctx,
 int create_comm_struct(struct perftest_comm *comm,
 		struct perftest_parameters *user_param)
 {
-	ALLOCATE(comm->rdma_params,struct perftest_parameters,1);
-	memset(comm->rdma_params,0,sizeof(struct perftest_parameters));
-
-	comm->rdma_params->port		   = user_param->port;
-	comm->rdma_params->sockfd      = -1;
-	comm->rdma_params->gid_index   = user_param->gid_index;
-	comm->rdma_params->gid_index2 = user_param->gid_index2;
-	comm->rdma_params->use_rdma_cm = user_param->use_rdma_cm;
-	comm->rdma_params->servername  = user_param->servername;
-	comm->rdma_params->machine 	   = user_param->machine;
-	comm->rdma_params->side		   = LOCAL;
-	comm->rdma_params->verb		   = user_param->verb;
-	comm->rdma_params->use_mcg	   = user_param->use_mcg;
-	comm->rdma_params->duplex	   = user_param->duplex;
-	comm->rdma_params->tos         = DEF_TOS;
-	comm->rdma_params->use_xrc	   = user_param->use_xrc;
+	ALLOCATE(comm->rdma_params, struct perftest_parameters, 1);
+	memset(comm->rdma_params, 0, sizeof(struct perftest_parameters));
+
+	comm->rdma_params->port		   	= user_param->port;
+	comm->rdma_params->sockfd      		= -1;
+	comm->rdma_params->gid_index   		= user_param->gid_index;
+	comm->rdma_params->gid_index2 		= user_param->gid_index2;
+	comm->rdma_params->use_rdma_cm 		= user_param->use_rdma_cm;
+	comm->rdma_params->servername  		= user_param->servername;
+	comm->rdma_params->machine 	   	= user_param->machine;
+	comm->rdma_params->side		   	= LOCAL;
+	comm->rdma_params->verb		   	= user_param->verb;
+	comm->rdma_params->use_mcg	   	= user_param->use_mcg;
+	comm->rdma_params->duplex	   	= user_param->duplex;
+	comm->rdma_params->tos         		= DEF_TOS;
+	comm->rdma_params->use_xrc	   	= user_param->use_xrc;
 	comm->rdma_params->connection_type	= user_param->connection_type;
-	comm->rdma_params->output      = user_param->output;
-	comm->rdma_params->report_per_port = user_param->report_per_port;
+	comm->rdma_params->output      		= user_param->output;
+	comm->rdma_params->report_per_port 	= user_param->report_per_port;
+	comm->rdma_params->retry_count		= user_param->retry_count;
+	comm->rdma_params->mr_per_qp		= user_param->mr_per_qp;
+	comm->rdma_params->dlid			= user_param->dlid;
 
 	if (user_param->use_rdma_cm) {
 
-		ALLOCATE(comm->rdma_ctx,struct pingpong_context,1);
-		memset(comm->rdma_ctx,0,sizeof(struct pingpong_context));
+		ALLOCATE(comm->rdma_ctx, struct pingpong_context, 1);
+		memset(comm->rdma_ctx, 0, sizeof(struct pingpong_context));
 
 		comm->rdma_params->tx_depth = 1;
 		comm->rdma_params->rx_depth = 1;
@@ -1025,6 +1030,8 @@ int create_comm_struct(struct perftest_comm *comm,
 		comm->rdma_params->size = sizeof(struct pingpong_dest);
 		comm->rdma_ctx->context = NULL;
 
+		ALLOCATE(comm->rdma_ctx->mr, struct ibv_mr*, user_param->num_of_qps);
+		ALLOCATE(comm->rdma_ctx->buf, void* , user_param->num_of_qps);
 		ALLOCATE(comm->rdma_ctx->qp,struct ibv_qp*,comm->rdma_params->num_of_qps);
 		comm->rdma_ctx->buff_size = user_param->cycle_buffer;
 
@@ -1212,7 +1219,7 @@ int rdma_read_data(void *data,
 		return 1;
 	}
 
-	memcpy(data,comm->rdma_ctx->buf,size);
+	memcpy(data,comm->rdma_ctx->buf[0], size);
 
 	if (post_one_recv_wqe(comm->rdma_ctx)) {
 		fprintf(stderr, "Couldn't post send \n");
@@ -1233,11 +1240,11 @@ int rdma_write_data(void *data,
 	struct ibv_sge list;
 	struct ibv_wc wc;
 	int ne;
-	memcpy(comm->rdma_ctx->buf,data,size);
+	memcpy(comm->rdma_ctx->buf[0],data,size);
 
-	list.addr   = (uintptr_t)comm->rdma_ctx->buf;
+	list.addr   = (uintptr_t)comm->rdma_ctx->buf[0];
 	list.length = size;
-	list.lkey   = comm->rdma_ctx->mr->lkey;
+	list.lkey   = comm->rdma_ctx->mr[0]->lkey;
 
 	wr.wr_id      = SYNC_SPEC_ID;
 	wr.sg_list    = &list;
@@ -1399,10 +1406,15 @@ void ctx_print_pingpong_data(struct pingpong_dest *element,
 		struct perftest_comm *comm)
 {
 	int is_there_mgid,local_mgid,remote_mgid;
+
+	/* use dlid value from user (if user specified and only on the remote side) */
+	uint16_t dlid = (comm->rdma_params->dlid && comm->rdma_params->side) ?
+				comm->rdma_params->dlid : element->lid;
+
 	if (comm->rdma_params->output != FULL_VERBOSITY)
 		return;
 	/*First of all we print the basic format.*/
-	printf(BASIC_ADDR_FMT,sideArray[comm->rdma_params->side],element->lid,element->qpn,element->psn);
+	printf(BASIC_ADDR_FMT, sideArray[comm->rdma_params->side], dlid, element->qpn, element->psn);
 
 	switch (comm->rdma_params->verb) {
 		case 2  : printf(READ_FMT,element->out_reads);
diff --git a/src/perftest_parameters.c b/src/perftest_parameters.c
index 482f416..66d4e19 100755
--- a/src/perftest_parameters.c
+++ b/src/perftest_parameters.c
@@ -7,6 +7,7 @@
 #include "perftest_parameters.h"
 
 #define MAC_LEN (17)
+#define ETHERTYPE_LEN (6)
 #define MAC_ARR_LEN (6)
 #define HEX_BASE (16)
 
@@ -67,6 +68,18 @@ static int parse_mac_from_str(char *mac, u_int8_t *addr)
 	return SUCCESS;
 }
 
+static int parse_ethertype_from_str(char *ether_str, uint16_t *ethertype_val)
+{
+	if (strlen(ether_str) != ETHERTYPE_LEN) {
+		fprintf(stderr, "invalid ethertype length\n");
+		return FAILURE;
+	}
+	*ethertype_val = strtoul(ether_str, NULL, HEX_BASE);
+	if (!*ethertype_val)
+		return FAILURE;
+	return SUCCESS;
+}
+
 /******************************************************************************
   parse_ip_from_str.
  *
@@ -181,7 +194,7 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection
 	printf(" measure results within margins. (default=2sec)\n");
 
 	printf("  -F, --CPU-freq ");
-	printf(" Do not fail even if cpufreq_ondemand module is loaded\n");
+	printf(" Do not show a warning even if cpufreq_ondemand module is loaded, and cpu-freq is not on max.\n");
 
 	if (verb == SEND) {
 		printf("  -g, --mcg ");
@@ -304,6 +317,9 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection
 	printf("      --cpu_util ");
 	printf(" Show CPU Utilization in report, valid only in Duration mode \n");
 
+	printf("      --dlid ");
+	printf(" Set a Destination LID instead of getting it from the other side.\n");
+
 	printf("      --dont_xchg_versions ");
 	printf(" Do not exchange versions and MTU with other side \n");
 
@@ -320,6 +336,16 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection
 		printf(" delay time between each post send\n");
 	}
 
+	printf("      --mmap=file ");
+	printf(" Use an mmap'd file as the buffer for testing P2P transfers.\n");
+	printf("      --mmap-offset=<offset> ");
+	printf(" Use an mmap'd file as the buffer for testing P2P transfers.\n");
+
+	if (tst == BW) {
+		printf("      --mr_per_qp ");
+		printf(" Create memory region for each qp.\n");
+	}
+
 	#ifdef HAVE_ODP
 	printf("      --odp ");
 	printf(" Use On Demand Paging instead of Memory Registration.\n");
@@ -355,6 +381,7 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection
 	printf(" Use CUDA lib for GPU-Direct testing.\n");
 	#endif
 
+
 	#ifdef HAVE_VERBS_EXP
 	printf("      --use_exp ");
 	printf(" Use Experimental verbs in data path. Default is OFF.\n");
@@ -409,6 +436,9 @@ void usage_raw_ethernet()
 	printf("  -k, --source_port ");
 	printf(" source port number (using to send packets with UDP header as default, or you can use --tcp flag to send TCP Header)\n");
 
+	printf("  -Y, --ethertype ");
+	printf(" ethertype value in the ethernet frame by this format 0xXXXX\n");
+
 	printf("  -Z, --server ");
 	printf(" choose server side for the current machine (--server/--client must be selected )\n");
 
@@ -484,6 +514,8 @@ static void init_perftest_params(struct perftest_parameters *user_param)
 	user_param->rate_units		= MEGA_BYTE_PS;
 	user_param->output		= -1;
 	user_param->use_cuda		= 0;
+	user_param->mmap_file		= NULL;
+	user_param->mmap_offset		= 0;
 	user_param->iters_per_port[0]	= 0;
 	user_param->iters_per_port[1]	= 0;
 
@@ -517,16 +549,18 @@ static void init_perftest_params(struct perftest_parameters *user_param)
 		user_param->cycle_buffer = DEF_PAGE_SIZE;
 	}
 
-	user_param->verb_type = NORMAL_INTF;
-	user_param->is_exp_cq = 0;
-	user_param->is_exp_qp = 0;
-	user_param->use_res_domain = 0;
+	user_param->verb_type		= NORMAL_INTF;
+	user_param->is_exp_cq		= 0;
+	user_param->is_exp_qp		= 0;
+	user_param->use_res_domain	= 0;
+	user_param->mr_per_qp		= 0;
+	user_param->dlid		= 0;
 }
 
 /******************************************************************************
  *
  ******************************************************************************/
-static int ctx_chk_pkey_index(struct ibv_context *context,int pkey_idx) 
+static int ctx_chk_pkey_index(struct ibv_context *context,int pkey_idx)
 {
 	int idx = 0;
 	struct ibv_device_attr attr;
@@ -800,6 +834,18 @@ static void force_dependecies(struct perftest_parameters *user_param)
 			exit(1);
 		}
 
+		if ((user_param->is_server_port == ON) && (user_param->is_server_ip == OFF || user_param->is_client_ip == OFF)) {
+			printf(RESULT_LINE);
+			fprintf(stderr," Invalid Command line.\nPlease provide source_ip and/or dest_ip when using UDP\n");
+			exit(1);
+		}
+		//UDP packet is ok by now. check tcp flag
+		if (user_param->tcp == ON && user_param->is_server_port == OFF) {
+			printf(RESULT_LINE);
+			fprintf(stderr,"Invalid Command line.\nPlease provide UDP information (IP & UDP Port src/dest) in order to use TCP\n");
+			exit(1);
+		}
+
 		/* Mac forwarding dependencies */
 		if (user_param->duplex == OFF && user_param->mac_fwd == ON) {
 			printf("mac_fwd should run in duplex mode only. changing to duplex mode.\n");
@@ -952,6 +998,12 @@ static void force_dependecies(struct perftest_parameters *user_param)
 			exit(1);
 		}
 	}
+
+	if (user_param->use_cuda && user_param->mmap_file != NULL) {
+		printf(RESULT_LINE);
+		fprintf(stderr,"You cannot use CUDA and an mmap'd file at the same time\n");
+		exit(1);
+	}
 	#endif
 
 	if ( (user_param->connection_type == UD) && (user_param->inline_size > MAX_INLINE_UD) ) {
@@ -991,26 +1043,31 @@ static void force_dependecies(struct perftest_parameters *user_param)
 			fprintf(stderr, "Accelerated verbs support RC/UC/RAW_ETH connections only.\n");
 			exit(1);
 		}
+
 		if (user_param->verb != SEND) {
 			fprintf(stderr, "Accelerated verbs support SEND opcode only.\n");
 			exit(1);
 		}
+
 		if (user_param->num_of_qps > 1) {
 			fprintf(stderr, "Accelerated verbs in perftest support only 1 qp for now.\n");
 			exit(1);
 		}
-		if (user_param->post_list > 1) {
-			fprintf(stderr, "Accelerated verbs in perftest does not support in postlist feature for now.\n");
-			exit(1);
-		}
+
 		if (user_param->tst != BW) {
 			fprintf(stderr, "Accelerated verbs in perftest supports only BW tests for now.\n");
 			exit(1);
 		}
+
 		if (user_param->duplex) {
 			fprintf(stderr, "Accelerated verbs in perftest supports only unidir tests for now\n");
 			exit(1);
 		}
+
+		if (user_param->test_method == RUN_INFINITELY) {
+			fprintf(stderr, "Accelerated verbs in perftest does not support Run Infinitely mode for now\n");
+			exit(1);
+		}
 	}
 	#endif
 
@@ -1271,6 +1328,8 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 	static int dont_xchg_versions_flag = 0;
 	static int use_exp_flag = 0;
 	static int use_cuda_flag = 0;
+	static int mmap_file_flag = 0;
+	static int mmap_offset_flag = 0;
 	static int ipv6_flag = 0;
 	static int report_per_port_flag = 0;
 	static int odp_flag = 0;
@@ -1278,6 +1337,8 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 	static int raw_mcast_flag = 0;
 	static int verb_type_flag = 0;
 	static int use_res_domain_flag = 0;
+	static int mr_per_qp_flag = 0;
+	static int dlid_flag = 0;
 
 	init_perftest_params(user_param);
 
@@ -1328,6 +1389,7 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 			{ .name = "source_ip",		.has_arg = 1, .val = 'j' },
 			{ .name = "dest_port",		.has_arg = 1, .val = 'K' },
 			{ .name = "source_port",	.has_arg = 1, .val = 'k' },
+			{ .name = "ethertype",		.has_arg = 1, .val = 'Y' },
 			{ .name = "limit_bw",		.has_arg = 1, .val = 'w' },
 			{ .name = "limit_msgrate",	.has_arg = 1, .val = 'y' },
 			{ .name = "server",		.has_arg = 0, .val = 'Z' },
@@ -1351,6 +1413,8 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 			{ .name = "retry_count",	.has_arg = 1, .flag = &retry_count_flag, .val = 1},
 			{ .name = "dont_xchg_versions",	.has_arg = 0, .flag = &dont_xchg_versions_flag, .val = 1},
 			{ .name = "use_cuda",		.has_arg = 0, .flag = &use_cuda_flag, .val = 1},
+			{ .name = "mmap",		.has_arg = 1, .flag = &mmap_file_flag, .val = 1},
+			{ .name = "mmap-offset",	.has_arg = 1, .flag = &mmap_offset_flag, .val = 1},
 			{ .name = "ipv6",		.has_arg = 0, .flag = &ipv6_flag, .val = 1},
 			{ .name = "report-per-port",	.has_arg = 0, .flag = &report_per_port_flag, .val = 1},
 			{ .name = "odp",		.has_arg = 0, .flag = &odp_flag, .val = 1},
@@ -1363,6 +1427,8 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 			{ .name = "verb_type",		.has_arg = 1, .flag = &verb_type_flag, .val = 1},
 			{ .name = "use_res_domain",	.has_arg = 0, .flag = &use_res_domain_flag, .val = 1},
 			#endif
+			{ .name = "mr_per_qp",		.has_arg = 0, .flag = &mr_per_qp_flag, .val = 1},
+			{ .name = "dlid",		.has_arg = 1, .flag = &dlid_flag, .val = 1},
 			{ 0 }
 		};
 		c = getopt_long(argc,argv,"w:y:p:d:i:m:s:n:t:u:S:x:c:q:I:o:M:r:Q:A:l:D:f:B:T:E:J:j:K:k:aFegzRvhbNVCHUOZP",long_options,NULL);
@@ -1557,6 +1623,13 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 					  return FAILURE;
 				  }
 				  break;
+			case 'Y':
+				  user_param->is_ethertype = ON;
+				  if (parse_ethertype_from_str(optarg, &user_param->ethertype)) {
+					  fprintf(stderr, " Invalid ethertype value\n");
+					  return FAILURE;
+				  }
+				  break;
 			case 'w':
 				  user_param->is_limit_bw = ON;
 				  user_param->limit_bw = strtof(optarg,NULL);
@@ -1656,7 +1729,18 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 					  }
 					  verb_type_flag = 0;
 				  }
-
+				  if (mmap_file_flag) {
+					  user_param->mmap_file = strdup(optarg);
+					  mmap_file_flag = 0;
+				  }
+				  if (mmap_offset_flag) {
+					  user_param->mmap_offset = strtol(optarg, NULL, 0);
+					  mmap_offset_flag = 0;
+				  }
+				  if (dlid_flag) {
+					  user_param->dlid = (uint16_t)strtol(optarg, NULL, 0);
+					  dlid_flag = 0;
+				  }
 				  break;
 
 			default:
@@ -1731,6 +1815,11 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
 	if (raw_mcast_flag) {
 		user_param->raw_mcast = 1;
 	}
+
+	if (mr_per_qp_flag) {
+		user_param->mr_per_qp = 1;
+	}
+
 	if (optind == argc - 1) {
 		GET_STRING(user_param->servername,strdupa(argv[optind]));
 
@@ -2210,11 +2299,6 @@ void print_report_lat (struct perftest_parameters *user_param)
 
 	} else {
 		cycles_to_units = get_cpu_mhz(user_param->cpu_freq_f);
-		if ((cycles_to_units == 0 && !user_param->cpu_freq_f)) {
-			fprintf(stderr,"Can't produce a report\n");
-			exit(1);
-		}
-
 		units = "usec";
 	}
 
@@ -2263,10 +2347,6 @@ void print_report_lat_duration (struct perftest_parameters *user_param)
 
 	rtt_factor = (user_param->verb == READ || user_param->verb == ATOMIC) ? 1 : 2;
 	cycles_to_units = get_cpu_mhz(user_param->cpu_freq_f);
-	if ((cycles_to_units == 0 && !user_param->cpu_freq_f)) {
-		fprintf(stderr,"Can't produce a report\n");
-		exit(1);
-	}
 
 	test_sample_time = (user_param->tcompleted[0] - user_param->tposted[0]);
 	latency = (((test_sample_time / cycles_to_units) / rtt_factor) / user_param->iters);
diff --git a/src/perftest_parameters.h b/src/perftest_parameters.h
index 3ccdedf..fa9d4d8 100755
--- a/src/perftest_parameters.h
+++ b/src/perftest_parameters.h
@@ -323,6 +323,8 @@ struct perftest_parameters {
 	int				tcp;
 	int				is_server_port;
 	int				is_client_port;
+	uint16_t			ethertype;
+	int				is_ethertype;
 	int				cpu_freq_f;
 	int				connection_type;
 	int				num_of_qps;
@@ -375,6 +377,8 @@ struct perftest_parameters {
 	int             		pkey_index;
 	int				raw_qos;
 	int				use_cuda;
+	char				*mmap_file;
+	unsigned long			mmap_offset;
 	/* New test params format pilot. will be used in all flags soon,. */
 	enum ctx_test_method 		test_method;
 	enum ibv_transport_type 	transport_type;
@@ -411,6 +415,8 @@ struct perftest_parameters {
 	int				is_exp_cq;
 	int				is_exp_qp;
 	int				use_res_domain;
+	int				mr_per_qp;
+	uint16_t			dlid;
 };
 
 struct report_options {
diff --git a/src/perftest_resources.c b/src/perftest_resources.c
index 3e603ae..71a1541 100755
--- a/src/perftest_resources.c
+++ b/src/perftest_resources.c
@@ -9,6 +9,7 @@
 #include <signal.h>
 #include <string.h>
 #include <ctype.h>
+#include <sys/mman.h>
 
 #include "perftest_resources.h"
 #include "config.h"
@@ -49,7 +50,6 @@ static CUcontext cuContext;
 
 static int pp_init_gpu(struct pingpong_context *ctx, size_t _size)
 {
-	int ret = 0;
 	const size_t gpu_page_size = 64*1024;
 	size_t size = (_size + gpu_page_size - 1) & ~(gpu_page_size - 1);
 	printf("initializing CUDA\n");
@@ -98,15 +98,16 @@ static int pp_init_gpu(struct pingpong_context *ctx, size_t _size)
 		return 1;
 	}
 
-	printf("cuMemAlloc() of a %d bytes GPU buffer\n", size);
+	printf("cuMemAlloc() of a %zd bytes GPU buffer\n", size);
 	CUdeviceptr d_A;
 	error = cuMemAlloc(&d_A, size);
 	if (error != CUDA_SUCCESS) {
 		printf("cuMemAlloc error=%d\n", error);
 		return 1;
 	}
-	printf("allocated GPU buffer address at %016llx pointer=%p\n", d_A, d_A);
-	ctx->buf = (void*)d_A;
+	printf("allocated GPU buffer address at %016llx pointer=%p\n", d_A,
+	       (void *) d_A);
+	ctx->buf[0] = (void*)d_A;
 
 	return 0;
 }
@@ -114,7 +115,7 @@ static int pp_init_gpu(struct pingpong_context *ctx, size_t _size)
 static int pp_free_gpu(struct pingpong_context *ctx)
 {
 	int ret = 0;
-	CUdeviceptr d_A = (CUdeviceptr) ctx->buf;
+	CUdeviceptr d_A = (CUdeviceptr) ctx->buf[0];
 
 	printf("deallocating RX GPU buffer\n");
 	cuMemFree(d_A);
@@ -127,6 +128,35 @@ static int pp_free_gpu(struct pingpong_context *ctx)
 }
 #endif
 
+static int pp_init_mmap(struct pingpong_context *ctx, size_t size,
+			const char *fname, unsigned long offset)
+{
+	int fd = open(fname, O_RDWR);
+	if (fd < 0) {
+		printf("Unable to open '%s': %s\n", fname, strerror(errno));
+		return 1;
+	}
+
+	ctx->buf[0] = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd,
+			offset);
+	close(fd);
+
+	if (ctx->buf[0] == MAP_FAILED) {
+		printf("Unable to mmap '%s': %s\n", fname, strerror(errno));
+		return 1;
+	}
+
+	printf("allocated mmap buffer of size %zd at %p\n", size, ctx->buf[0]);
+
+	return 0;
+}
+
+static int pp_free_mmap(struct pingpong_context *ctx)
+{
+	munmap(ctx->buf[0], ctx->buff_size);
+	return 0;
+}
+
 #ifdef HAVE_VERBS_EXP
 static void get_verbs_pointers(struct pingpong_context *ctx)
 {
@@ -601,6 +631,7 @@ struct ibv_device* ctx_find_dev(const char *ib_devname)
 void alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_param)
 {
 	uint64_t tarr_size;
+	int num_of_qps_factor;
 
 	ctx->cycle_buffer = user_param->cycle_buffer;
 	ctx->cache_line_size = user_param->cache_line_size;
@@ -608,13 +639,16 @@ void alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_par
 	ALLOCATE(user_param->port_by_qp, uint64_t, user_param->num_of_qps);
 
 	tarr_size = (user_param->noPeak) ? 1 : user_param->iters*user_param->num_of_qps;
-	ALLOCATE(user_param->tposted,cycles_t,tarr_size);
+	ALLOCATE(user_param->tposted, cycles_t, tarr_size);
 	memset(user_param->tposted, 0, sizeof(cycles_t)*tarr_size);
 
 	if (user_param->tst == LAT && user_param->test_type == DURATION)
-		ALLOCATE(user_param->tcompleted,cycles_t,1);
+		ALLOCATE(user_param->tcompleted, cycles_t, 1);
+
+	ALLOCATE(ctx->qp, struct ibv_qp*, user_param->num_of_qps);
+	ALLOCATE(ctx->mr, struct ibv_mr*, user_param->num_of_qps);
+	ALLOCATE(ctx->buf, void* , user_param->num_of_qps);
 
-	ALLOCATE(ctx->qp,struct ibv_qp*,user_param->num_of_qps);
 	#ifdef HAVE_ACCL_VERBS
 	ALLOCATE(ctx->qp_burst_family, struct ibv_exp_qp_burst_family*, user_param->num_of_qps);
 	#endif
@@ -622,9 +656,9 @@ void alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_par
 	#ifdef HAVE_DC
 	if (user_param->connection_type == DC) {
 		#ifdef HAVE_VERBS_EXP
-		ALLOCATE(ctx->dct,struct ibv_exp_dct*,user_param->num_of_qps);
+		ALLOCATE(ctx->dct, struct ibv_exp_dct*, user_param->num_of_qps);
 		#else
-		ALLOCATE(ctx->dct,struct ibv_dct*,user_param->num_of_qps);
+		ALLOCATE(ctx->dct, struct ibv_dct*, user_param->num_of_qps);
 		#endif
 	}
 	#endif
@@ -669,7 +703,9 @@ void alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_par
 		ctx->cycle_buffer = user_param->size * user_param->rx_depth;
 
 	ctx->size = user_param->size;
-	ctx->buff_size = BUFF_SIZE(ctx->size,ctx->cycle_buffer)*2*user_param->num_of_qps;
+
+	num_of_qps_factor = (user_param->mr_per_qp) ? 1 : user_param->num_of_qps;
+	ctx->buff_size = BUFF_SIZE(ctx->size, ctx->cycle_buffer) * 2 * num_of_qps_factor;
 
 	user_param->buff_size = ctx->buff_size;
 	if (user_param->connection_type == UD)
@@ -682,10 +718,12 @@ void alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_par
 int destroy_ctx(struct pingpong_context *ctx,
 		struct perftest_parameters *user_param)
 {
-	int i, first;
+	int i, first, dereg_counter;
 	int test_result = 0;
 	int num_of_qps = user_param->num_of_qps;
 
+	dereg_counter = (user_param->mr_per_qp) ? user_param->num_of_qps : 1;
+
 	if (user_param->work_rdma_cm == ON)
 		rdma_disconnect(ctx->cm_id);
 
@@ -779,9 +817,11 @@ int destroy_ctx(struct pingpong_context *ctx,
 		}
 	}
 
-	if (ibv_dereg_mr(ctx->mr)) {
-		fprintf(stderr, "failed to deregister MR\n");
-		test_result = 1;
+	for (i = 0; i < dereg_counter; i++) {
+		if (ibv_dereg_mr(ctx->mr[i])) {
+			fprintf(stderr, "failed to deregister MR #%d\n", i+1);
+			test_result = 1;
+		}
 	}
 
 	if (user_param->verb == SEND && user_param->work_rdma_cm == ON && ctx->send_rcredit) {
@@ -819,9 +859,13 @@ int destroy_ctx(struct pingpong_context *ctx,
 	}
 	else
 	#endif
-	if (ctx->is_contig_supported == FAILURE)
-		free(ctx->buf);
-
+	if (user_param->mmap_file != NULL) {
+		pp_free_mmap(ctx);
+	} else if (ctx->is_contig_supported == FAILURE) {
+		for (i = 0; i < dereg_counter; i++) {
+			free(ctx->buf[i]);
+		}
+	}
 	free(ctx->qp);
 
 	if ((user_param->tst == BW ) && (user_param->machine == CLIENT || user_param->duplex)) {
@@ -857,6 +901,9 @@ int destroy_ctx(struct pingpong_context *ctx,
 	return test_result;
 }
 
+/******************************************************************************
+ *
+ ******************************************************************************/
 #ifdef HAVE_VERBS_EXP
 static int check_inline_recv_support(struct pingpong_context *ctx,
 					struct perftest_parameters *user_param)
@@ -883,6 +930,9 @@ static int check_inline_recv_support(struct pingpong_context *ctx,
 }
 #endif
 
+/******************************************************************************
+ *
+ ******************************************************************************/
 #ifdef HAVE_ODP
 static int check_odp_support(struct pingpong_context *ctx)
 {
@@ -906,6 +956,9 @@ static int check_odp_support(struct pingpong_context *ctx)
 }
 #endif
 
+/******************************************************************************
+ *
+ ******************************************************************************/
 int create_reg_cqs(struct pingpong_context *ctx,
 		   struct perftest_parameters *user_param,
 		   int tx_buffer_depth, int need_recv_cq)
@@ -930,6 +983,9 @@ int create_reg_cqs(struct pingpong_context *ctx,
 	return SUCCESS;
 }
 
+/******************************************************************************
+ *
+ ******************************************************************************/
 #ifdef HAVE_VERBS_EXP
 int create_exp_cqs(struct pingpong_context *ctx,
 		   struct perftest_parameters *user_param,
@@ -991,6 +1047,9 @@ int create_exp_cqs(struct pingpong_context *ctx,
 }
 #endif
 
+/******************************************************************************
+ *
+ ******************************************************************************/
 int create_cqs(struct pingpong_context *ctx, struct perftest_parameters *user_param)
 {
 	int ret;
@@ -1016,6 +1075,10 @@ int create_cqs(struct pingpong_context *ctx, struct perftest_parameters *user_pa
 
 	return ret;
 }
+
+/******************************************************************************
+ *
+ ******************************************************************************/
 #ifdef HAVE_ACCL_VERBS
 struct ibv_exp_res_domain* create_res_domain(struct pingpong_context *ctx, struct perftest_parameters *user_param)
 {
@@ -1054,26 +1117,15 @@ struct ibv_exp_res_domain* create_res_domain(struct pingpong_context *ctx, struc
 /******************************************************************************
  *
  ******************************************************************************/
-int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_param)
+int create_single_mr(struct pingpong_context *ctx, struct perftest_parameters *user_param, int qp_index)
 {
-	int i;
 	int flags = IBV_ACCESS_LOCAL_WRITE;
-	int num_of_qps = user_param->num_of_qps / 2;
-	#ifdef HAVE_ACCL_VERBS
-	enum ibv_exp_query_intf_status intf_status;
-	struct ibv_exp_query_intf_params intf_params;
-	#endif
+
 	#ifdef HAVE_VERBS_EXP
 	struct ibv_exp_reg_mr_in reg_mr_exp_in;
 	uint64_t exp_flags = IBV_EXP_ACCESS_LOCAL_WRITE;
-	struct ibv_exp_device_attr dattr;
-
-	memset(&dattr, 0, sizeof(dattr));
-	get_verbs_pointers(ctx);
 	#endif
 
-	ctx->is_contig_supported  = check_for_contig_pages_support(ctx->context);
-
 	/* ODP */
 	#ifdef HAVE_ODP
 	if (user_param->use_odp) {
@@ -1091,65 +1143,45 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para
 		ctx->is_contig_supported = FAILURE;
 		if(pp_init_gpu(ctx, ctx->buff_size)) {
 			fprintf(stderr, "Couldn't allocate work buf.\n");
-			return NULL;
+			return 1;
 		}
-	}
-	else {
+	} else
 	#endif
+
+	if (user_param->mmap_file != NULL) {
+		ctx->is_contig_supported = FAILURE;
+		if (pp_init_mmap(ctx, ctx->buff_size, user_param->mmap_file,
+				 user_param->mmap_offset))
+		{
+			fprintf(stderr, "Couldn't allocate work buf.\n");
+			return 1;
+		}
+
+	} else {
 		/* Allocating buffer for data, in case driver not support contig pages. */
 		if (ctx->is_contig_supported == FAILURE) {
-			ctx->buf = memalign(user_param->cycle_buffer,ctx->buff_size);
-			if (!ctx->buf) {
+			ctx->buf[qp_index] = memalign(user_param->cycle_buffer, ctx->buff_size);
+			if (!ctx->buf[qp_index]) {
 				fprintf(stderr, "Couldn't allocate work buf.\n");
-				exit(1);
+				return 1;
 			}
 
-			memset(ctx->buf, 0,ctx->buff_size);
-
+			memset(ctx->buf[qp_index], 0, ctx->buff_size);
 		} else {
-			ctx->buf = NULL;
+			ctx->buf[qp_index] = NULL;
 			#ifdef HAVE_VERBS_EXP
 			exp_flags |= IBV_EXP_ACCESS_ALLOCATE_MR;
 			#else
 			flags |= (1 << 5);
 			#endif
 		}
-	#ifdef HAVE_CUDA
-	}
-	#endif
-
-	/* Allocating an event channel if requested. */
-	if (user_param->use_event) {
-		ctx->channel = ibv_create_comp_channel(ctx->context);
-		if (!ctx->channel) {
-			fprintf(stderr, "Couldn't create completion channel\n");
-			return FAILURE;
-		}
-	}
-
-	/* Allocating the Protection domain. */
-	ctx->pd = ibv_alloc_pd(ctx->context);
-	if (!ctx->pd) {
-		fprintf(stderr, "Couldn't allocate PD\n");
-		return FAILURE;
-	}
-
-	#ifdef HAVE_ACCL_VERBS
-	if (user_param->use_res_domain) {
-		ctx->res_domain = create_res_domain(ctx, user_param);
-		if (!ctx->res_domain) {
-			fprintf(stderr, "Couldn't create resource domain\n");
-			return FAILURE;
-		}
 	}
-	#endif
 
 	if (user_param->verb == WRITE) {
 		flags |= IBV_ACCESS_REMOTE_WRITE;
 		#ifdef HAVE_VERBS_EXP
 		exp_flags |= IBV_EXP_ACCESS_REMOTE_WRITE;
 		#endif
-
 	} else if (user_param->verb == READ) {
 		flags |= IBV_ACCESS_REMOTE_READ;
 		#ifdef HAVE_VERBS_EXP
@@ -1160,7 +1192,6 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para
 		#ifdef HAVE_VERBS_EXP
 		exp_flags |= IBV_EXP_ACCESS_REMOTE_WRITE;
 		#endif
-
 	} else if (user_param->verb == ATOMIC) {
 		flags |= IBV_ACCESS_REMOTE_ATOMIC;
 		#ifdef HAVE_VERBS_EXP
@@ -1172,26 +1203,111 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para
 	#ifdef HAVE_VERBS_EXP
 	if (ctx->is_contig_supported == SUCCESS || user_param->use_odp) {
 		reg_mr_exp_in.pd = ctx->pd;
-		reg_mr_exp_in.addr = ctx->buf;
+		reg_mr_exp_in.addr = ctx->buf[qp_index];
 		reg_mr_exp_in.length = ctx->buff_size;
 		reg_mr_exp_in.exp_access = exp_flags;
 		reg_mr_exp_in.comp_mask = 0;
 
-		ctx->mr = ibv_exp_reg_mr(&reg_mr_exp_in);
+		ctx->mr[qp_index] = ibv_exp_reg_mr(&reg_mr_exp_in);
 	}
 	else
-		ctx->mr = ibv_reg_mr(ctx->pd,ctx->buf,ctx->buff_size,flags);
+		ctx->mr[qp_index] = ibv_reg_mr(ctx->pd, ctx->buf[qp_index], ctx->buff_size, flags);
 	#else
-	ctx->mr = ibv_reg_mr(ctx->pd,ctx->buf,ctx->buff_size,flags);
+	ctx->mr[qp_index] = ibv_reg_mr(ctx->pd, ctx->buf[qp_index], ctx->buff_size, flags);
 	#endif
 
-	if (!ctx->mr) {
+	if (!ctx->mr[qp_index]) {
 		fprintf(stderr, "Couldn't allocate MR\n");
-		return FAILURE;
+		return 1;
 	}
 
 	if (ctx->is_contig_supported == SUCCESS)
-		ctx->buf = ctx->mr->addr;
+		ctx->buf[qp_index] = ctx->mr[qp_index]->addr;
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ ******************************************************************************/
+int create_mr(struct pingpong_context *ctx, struct perftest_parameters *user_param)
+{
+	int i;
+
+	/* create first MR */
+	if (create_single_mr(ctx, user_param, 0)) {
+		fprintf(stderr, "failed to create mr\n");
+		return 1;
+	}
+
+	/* create the rest if needed, or copy the first one */
+	for (i = 1; i < user_param->num_of_qps; i++) {
+		if (user_param->mr_per_qp) {
+			if (create_single_mr(ctx, user_param, i)) {
+				fprintf(stderr, "failed to create mr\n");
+				return 1;
+			}
+		} else {
+			ALLOCATE(ctx->mr[i], struct ibv_mr, 1);
+			memset(ctx->mr[i], 0, sizeof(struct ibv_mr));
+			ctx->mr[i] = ctx->mr[0];
+			ctx->buf[i] = ctx->buf[0] + (i*BUFF_SIZE(ctx->size, ctx->cycle_buffer));
+		}
+	}
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ ******************************************************************************/
+int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_param)
+{
+	int i;
+	int num_of_qps = user_param->num_of_qps / 2;
+
+	#ifdef HAVE_ACCL_VERBS
+	enum ibv_exp_query_intf_status intf_status;
+	struct ibv_exp_query_intf_params intf_params;
+	#endif
+
+	#ifdef HAVE_VERBS_EXP
+	struct ibv_exp_device_attr dattr;
+	memset(&dattr, 0, sizeof(dattr));
+	get_verbs_pointers(ctx);
+	#endif
+
+	ctx->is_contig_supported  = check_for_contig_pages_support(ctx->context);
+
+	/* Allocating an event channel if requested. */
+	if (user_param->use_event) {
+		ctx->channel = ibv_create_comp_channel(ctx->context);
+		if (!ctx->channel) {
+			fprintf(stderr, "Couldn't create completion channel\n");
+			return FAILURE;
+		}
+	}
+
+	/* Allocating the Protection domain. */
+	ctx->pd = ibv_alloc_pd(ctx->context);
+	if (!ctx->pd) {
+		fprintf(stderr, "Couldn't allocate PD\n");
+		return FAILURE;
+	}
+
+	#ifdef HAVE_ACCL_VERBS
+	if (user_param->use_res_domain) {
+		ctx->res_domain = create_res_domain(ctx, user_param);
+		if (!ctx->res_domain) {
+			fprintf(stderr, "Couldn't create resource domain\n");
+			return FAILURE;
+		}
+	}
+	#endif
+
+	if (create_mr(ctx, user_param)) {
+		fprintf(stderr, "Failed to create MR\n");
+	}
 
 	if (create_cqs(ctx, user_param)) {
 		fprintf(stderr, "Failed to create CQs\n");
@@ -1811,7 +1927,7 @@ static int ctx_modify_dc_qp_to_rtr(struct ibv_qp *qp,
 	else
 		attr->ah_attr.port_num = user_param->ib_port;
 
-	attr->ah_attr.dlid = dest->lid;
+	attr->ah_attr.dlid = (user_param->dlid) ? user_param->dlid : dest->lid;
 	if (user_param->gid_index == DEF_GID_INDEX) {
 
 		attr->ah_attr.is_global = 0;
@@ -1872,7 +1988,7 @@ static int ctx_modify_qp_to_rtr(struct ibv_qp *qp,
 
 	if (user_param->connection_type != RawEth) {
 
-		attr->ah_attr.dlid = dest->lid;
+		attr->ah_attr.dlid = (user_param->dlid) ? user_param->dlid : dest->lid;
 		attr->ah_attr.sl = user_param->sl;
 
 		if (((attr->ah_attr.port_num == user_param->ib_port) && (user_param->gid_index == DEF_GID_INDEX))
@@ -2110,9 +2226,16 @@ void ctx_set_send_exp_wqes(struct pingpong_context *ctx,
 
 	for (i = 0; i < num_of_qps ; i++) {
 		memset(&ctx->exp_wr[i*user_param->post_list],0,sizeof(struct ibv_exp_send_wr));
-		ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf + (i*BUFF_SIZE(ctx->size,ctx->cycle_buffer));
-		if (user_param->mac_fwd)
-			ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf + (num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf[i];
+
+		if (user_param->mac_fwd) {
+			if (user_param->mr_per_qp) {
+				ctx->sge_list[i*user_param->post_list].addr = 
+					(uintptr_t)ctx->buf[0] + (num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+			} else {
+				ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf[i];
+			}
+		}
 
 		if (user_param->verb == WRITE || user_param->verb == READ)
 			ctx->exp_wr[i*user_param->post_list].wr.rdma.remote_addr   = rem_dest[xrc_offset + i].vaddr;
@@ -2124,7 +2247,7 @@ void ctx_set_send_exp_wqes(struct pingpong_context *ctx,
 
 			ctx->scnt[i] = 0;
 			ctx->ccnt[i] = 0;
-			ctx->my_addr[i] = (uintptr_t)ctx->buf + (i*BUFF_SIZE(ctx->size,ctx->cycle_buffer));
+			ctx->my_addr[i] = (uintptr_t)ctx->buf[i];
 			if (user_param->verb != SEND)
 				ctx->rem_addr[i] = rem_dest[xrc_offset + i].vaddr;
 		}
@@ -2134,7 +2257,7 @@ void ctx_set_send_exp_wqes(struct pingpong_context *ctx,
 			ctx->sge_list[i*user_param->post_list + j].length =
 				(user_param->connection_type == RawEth) ? (user_param->size - HW_CRC_ADDITION) : user_param->size;
 
-			ctx->sge_list[i*user_param->post_list + j].lkey = ctx->mr->lkey;
+			ctx->sge_list[i*user_param->post_list + j].lkey = ctx->mr[i]->lkey;
 
 			if (j > 0) {
 
@@ -2266,9 +2389,16 @@ void ctx_set_send_reg_wqes(struct pingpong_context *ctx,
 
 	for (i = 0; i < num_of_qps ; i++) {
 		memset(&ctx->wr[i*user_param->post_list],0,sizeof(struct ibv_send_wr));
-		ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf + (i*BUFF_SIZE(ctx->size,ctx->cycle_buffer));
-		if (user_param->mac_fwd)
-			ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf + (num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf[i];
+
+		if (user_param->mac_fwd) {
+			if (user_param->mr_per_qp) {
+				ctx->sge_list[i*user_param->post_list].addr =
+					(uintptr_t)ctx->buf[0] + (num_of_qps + i)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+			} else {
+				ctx->sge_list[i*user_param->post_list].addr = (uintptr_t)ctx->buf[i];
+			}
+		}
 
 		if (user_param->verb == WRITE || user_param->verb == READ)
 			ctx->wr[i*user_param->post_list].wr.rdma.remote_addr   = rem_dest[xrc_offset + i].vaddr;
@@ -2280,7 +2410,7 @@ void ctx_set_send_reg_wqes(struct pingpong_context *ctx,
 
 			ctx->scnt[i] = 0;
 			ctx->ccnt[i] = 0;
-			ctx->my_addr[i] = (uintptr_t)ctx->buf + (i*BUFF_SIZE(ctx->size,ctx->cycle_buffer));
+			ctx->my_addr[i] = (uintptr_t)ctx->buf[i];
 			if (user_param->verb != SEND)
 				ctx->rem_addr[i] = rem_dest[xrc_offset + i].vaddr;
 		}
@@ -2290,7 +2420,7 @@ void ctx_set_send_reg_wqes(struct pingpong_context *ctx,
 			ctx->sge_list[i*user_param->post_list + j].length =
 				(user_param->connection_type == RawEth) ? (user_param->size - HW_CRC_ADDITION) : user_param->size;
 
-			ctx->sge_list[i*user_param->post_list + j].lkey = ctx->mr->lkey;
+			ctx->sge_list[i*user_param->post_list + j].lkey = ctx->mr[i]->lkey;
 
 			if (j > 0) {
 
@@ -2388,11 +2518,10 @@ void ctx_set_send_reg_wqes(struct pingpong_context *ctx,
  ******************************************************************************/
 int ctx_set_recv_wqes(struct pingpong_context *ctx,struct perftest_parameters *user_param)
 {
-	int	i,j,k;
-	int num_of_qps = user_param->num_of_qps;
-	struct ibv_recv_wr  *bad_wr_recv;
-	i = 0;
-	int size_per_qp = user_param->rx_depth;
+	int			i = 0,j,k;
+	int			num_of_qps = user_param->num_of_qps;
+	struct ibv_recv_wr	*bad_wr_recv;
+	int			size_per_qp = user_param->rx_depth;
 
 	if((user_param->use_xrc || user_param->connection_type == DC) &&
 				(user_param->duplex || user_param->tst == LAT)) {
@@ -2409,15 +2538,18 @@ int ctx_set_recv_wqes(struct pingpong_context *ctx,struct perftest_parameters *u
 		num_of_qps = 1;
 	}
 	for (k = 0; i < user_param->num_of_qps; i++,k++) {
-
-		ctx->recv_sge_list[i].addr  = (uintptr_t)ctx->buf +
-			(num_of_qps + k)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		if (!user_param->mr_per_qp) {
+			ctx->recv_sge_list[i].addr  = (uintptr_t)ctx->buf[0] +
+				(num_of_qps + k)*BUFF_SIZE(ctx->size,ctx->cycle_buffer);
+		} else {
+			ctx->recv_sge_list[i].addr  = (uintptr_t)ctx->buf[i];
+		}
 
 		if (user_param->connection_type == UD)
 			ctx->recv_sge_list[i].addr += (ctx->cache_line_size - UD_ADDITION);
 
 		ctx->recv_sge_list[i].length = SIZE(user_param->connection_type,user_param->size,1);
-		ctx->recv_sge_list[i].lkey   = ctx->mr->lkey;
+		ctx->recv_sge_list[i].lkey   = ctx->mr[i]->lkey;
 
 		ctx->rwr[i].sg_list = &ctx->recv_sge_list[i];
 		ctx->rwr[i].wr_id   = i;
@@ -2646,6 +2778,8 @@ int run_iter_bw(struct pingpong_context *ctx,struct perftest_parameters *user_pa
 	int 			cpu_mhz = 0;
 	int 			return_value = 0;
 	int			wc_id;
+	int pl_index;
+	struct ibv_sge		*sg_l;
 
 	ALLOCATE(wc ,struct ibv_wc ,CTX_POLL_BATCH);
 
@@ -2756,8 +2890,12 @@ int run_iter_bw(struct pingpong_context *ctx,struct perftest_parameters *user_pa
 				#ifdef HAVE_VERBS_EXP
 				#ifdef HAVE_ACCL_VERBS
 				if (user_param->verb_type == ACCL_INTF) {
-					struct ibv_sge *sg_l = ctx->exp_wr[index*user_param->post_list].sg_list;
-					err = ctx->qp_burst_family[index]->send_burst(ctx->qp[index], sg_l, 1, ctx->exp_wr[index].exp_send_flags);
+					for (pl_index = 0; pl_index < user_param->post_list; pl_index++) {
+						sg_l = ctx->exp_wr[index*user_param->post_list + pl_index].sg_list;
+						ctx->qp_burst_family[index]->send_pending(ctx->qp[index], sg_l->addr, sg_l->length, sg_l->lkey,
+												ctx->exp_wr[index*user_param->post_list + pl_index].exp_send_flags);
+					}
+					ctx->qp_burst_family[index]->send_flush(ctx->qp[index]);
 				} else {
 				#endif
 					if (user_param->use_exp == 1) {
@@ -3730,8 +3868,9 @@ int run_iter_lat_write(struct pingpong_context *ctx,struct perftest_parameters *
 
 	if((user_param->use_xrc || user_param->connection_type == DC))
 		poll_buf_offset = 1;
-	post_buf = (char*)ctx->buf + user_param->size - 1;
-	poll_buf = (char*)ctx->buf + (user_param->num_of_qps + poll_buf_offset)*BUFF_SIZE(ctx->size,ctx->cycle_buffer) + user_param->size - 1;
+
+	post_buf = (char*)ctx->buf[0] + user_param->size - 1;
+	poll_buf = (char*)ctx->buf[0] + (user_param->num_of_qps + poll_buf_offset)*BUFF_SIZE(ctx->size, ctx->cycle_buffer) + user_param->size - 1;
 
 	/* Duration support in latency tests. */
 	if (user_param->test_type == DURATION) {
diff --git a/src/perftest_resources.h b/src/perftest_resources.h
index 1e47e34..c5b6413 100755
--- a/src/perftest_resources.h
+++ b/src/perftest_resources.h
@@ -129,10 +129,10 @@ struct pingpong_context {
 	struct ibv_context			*context;
 	struct ibv_comp_channel			*channel;
 	struct ibv_pd				*pd;
-	struct ibv_mr				*mr;
+	struct ibv_mr				**mr;
 	struct ibv_cq				*send_cq;
 	struct ibv_cq				*recv_cq;
-	void					*buf;
+	void					**buf;
 	struct ibv_ah				**ah;
 	struct ibv_qp				**qp;
 	struct ibv_srq				*srq;
@@ -777,4 +777,38 @@ struct ibv_qp* ctx_exp_qp_create(struct pingpong_context *ctx,
 int modify_qp_to_init(struct pingpong_context *ctx,
                 struct perftest_parameters *user_param, int qp_index, int num_of_qps);
 
+
+/* create_single_mr
+ *
+ * Description :
+ *
+ *	Creates a single MR for a specific QP index.
+ *
+ *	Parameters :
+ *      	ctx - Resources sructure.
+ *		user_param - the perftest parameters.
+ *		qp_index  - QP index to register a MR
+ *
+ * Return Value : SUCCESS, FAILURE.
+ *
+ */
+int create_single_mr(struct pingpong_context *ctx,
+		struct perftest_parameters *user_param, int qp_index);
+
+/* create_mr
+ *
+ * Description :
+ *
+ *	Creates Memory Regions for the test.
+ *	Takes into consideration all user parameters and test type.
+ *
+ *	Parameters :
+ *      	ctx - Resources sructure.
+ *		user_param - the perftest parameters.
+ *
+ * Return Value : SUCCESS, FAILURE.
+ *
+ */
+int create_mr(struct pingpong_context *ctx,
+		struct perftest_parameters *user_param);
 #endif /* PERFTEST_RESOURCES_H */
diff --git a/src/raw_ethernet_resources.c b/src/raw_ethernet_resources.c
index 4b37e46..e87654d 100755
--- a/src/raw_ethernet_resources.c
+++ b/src/raw_ethernet_resources.c
@@ -49,11 +49,15 @@
 
 struct perftest_parameters* duration_param;
 
-int check_flow_steering_support()
+int check_flow_steering_support(char *dev_name)
 {
 	char* file_name = "/sys/module/mlx4_core/parameters/log_num_mgm_entry_size";
 	FILE *fp;
 	char line[4];
+
+	if (strstr(dev_name, "mlx5") != NULL)
+		return 0;
+
 	fp = fopen(file_name, "r");
 	fgets(line,4,fp);
 	int val = atoi(line);
@@ -431,13 +435,14 @@ void create_raw_eth_pkt( struct perftest_parameters *user_param,
 	int offset = 0;
 	struct ETH_header* eth_header;
 	uint16_t ip_next_protocol = 0;
-	uint16_t eth_type = (user_param->is_client_ip || user_param->is_server_ip ? IP_ETHER_TYPE : (ctx->size-RAWETH_ADDITION));
+	uint16_t eth_type = user_param->is_ethertype ? user_param->ethertype :
+		(user_param->is_client_ip || user_param->is_server_ip ? IP_ETHER_TYPE : (ctx->size-RAWETH_ADDITION));
 	if(user_param->is_client_port && user_param->is_server_port)
 		ip_next_protocol = (user_param->tcp ? TCP_PROTOCOL : UDP_PROTOCOL);
 
 	DEBUG_LOG(TRACE,">>>>>>%s",__FUNCTION__);
 
-	eth_header = (void*)ctx->buf;
+	eth_header = (void*)ctx->buf[0];
 
 	/* build single packet on ctx buffer */
 	build_pkt_on_buffer(eth_header,my_dest_info,rem_dest_info,user_param,eth_type,ip_next_protocol,PRINT_ON,ctx->size-RAWETH_ADDITION);
@@ -447,7 +452,7 @@ void create_raw_eth_pkt( struct perftest_parameters *user_param,
 		if (ctx->size <= (ctx->cycle_buffer / 2)) {
 			while (offset < ctx->cycle_buffer-INC(ctx->size,ctx->cache_line_size)) {
 				offset += INC(ctx->size,ctx->cache_line_size);
-				eth_header = (void*)ctx->buf+offset;
+				eth_header = (void*)ctx->buf[0]+offset;
 				build_pkt_on_buffer(eth_header,my_dest_info,rem_dest_info,
 						user_param,eth_type,ip_next_protocol,
 						PRINT_OFF,ctx->size-RAWETH_ADDITION);
@@ -617,6 +622,12 @@ int send_set_up_connection(
 			memset((void*)&spec_info->tcp_udp.mask.dst_port, 0xFF,sizeof(spec_info->ipv4.mask.dst_ip));
 			memset((void*)&spec_info->tcp_udp.mask.src_port, 0xFF,sizeof(spec_info->ipv4.mask.src_ip));
 		}
+
+		if (user_param->is_ethertype) {
+			spec_info->eth.val.ether_type = htons(user_param->ethertype);
+			spec_info->eth.mask.ether_type = 0xffff;
+		}
+
 	}
 
 	if (user_param->machine == CLIENT || user_param->duplex) {
diff --git a/src/raw_ethernet_resources.h b/src/raw_ethernet_resources.h
index d02f890..ce3061d 100644
--- a/src/raw_ethernet_resources.h
+++ b/src/raw_ethernet_resources.h
@@ -108,7 +108,7 @@ void print_ip_header(struct IP_V4_header* ip_header);
 void print_udp_header(struct UDP_header* udp_header);
 void print_pkt(void* pkt,struct perftest_parameters *user_param);
 
-int check_flow_steering_support();
+int check_flow_steering_support(char *dev_name);
 
 /* build_pkt_on_buffer
  * Description: build single Ethernet packet on ctx buffer
diff --git a/src/raw_ethernet_send_bw.c b/src/raw_ethernet_send_bw.c
index 0f0ccc7..3fa6296 100755
--- a/src/raw_ethernet_send_bw.c
+++ b/src/raw_ethernet_send_bw.c
@@ -82,10 +82,6 @@ int main(int argc, char *argv[])
 	strncpy(user_param.version, VERSION, sizeof(user_param.version));
 	user_param.connection_type = RawEth;
 
-	if (check_flow_steering_support()) {
-		return 1;
-	}
-
 	ret_parser = parser(&user_param,argv,argc);
 
 	if (ret_parser) {
@@ -130,6 +126,11 @@ int main(int argc, char *argv[])
 		DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__);
 		return 1;
 	}
+	GET_STRING(user_param.ib_devname, ibv_get_device_name(ib_dev));
+
+	if (check_flow_steering_support(user_param.ib_devname)) {
+		return 1;
+	}
 
 	/* Getting the relevant context from the device */
 	ctx.context = ibv_open_device(ib_dev);
diff --git a/src/raw_ethernet_send_lat.c b/src/raw_ethernet_send_lat.c
index d07b279..052ef3c 100755
--- a/src/raw_ethernet_send_lat.c
+++ b/src/raw_ethernet_send_lat.c
@@ -84,9 +84,6 @@ int main(int argc, char *argv[])
 	user_param.connection_type = RawEth;
 	user_param.r_flag  = &report;
 
-	if (check_flow_steering_support()) {
-		return 1;
-	}
 
 	/* Configure the parameters values according to user
 	   arguments or default values. */
@@ -113,6 +110,11 @@ int main(int argc, char *argv[])
 		DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__);
 		return 1;
 	}
+	GET_STRING(user_param.ib_devname, ibv_get_device_name(ib_dev));
+
+	if (check_flow_steering_support(user_param.ib_devname)) {
+		return 1;
+	}
 
 	/* Getting the relevant context from the device */
 	ctx.context = ibv_open_device(ib_dev);
diff --git a/src/send_lat.c b/src/send_lat.c
index 920b838..bc194d8 100755
--- a/src/send_lat.c
+++ b/src/send_lat.c
@@ -105,58 +105,31 @@ static int send_set_up_connection(struct pingpong_context *ctx,
 		struct perftest_comm *comm)
 {
 	int i;
-	srand48(getpid() * time(NULL));
-	union ibv_gid temp_gid;
 
-	if (user_param->gid_index != -1) {
-		if (ibv_query_gid(ctx->context,user_param->ib_port,user_param->gid_index,&temp_gid)) {
-			return -1;
-		}
+	if (set_up_connection(ctx,user_param,my_dest)) {
+		fprintf(stderr," Unable to set up my IB connection parameters\n");
+		return FAILURE;
 	}
-	for (i = 0; i < user_param->num_of_qps; i++) {
-		if (user_param->use_mcg) {
-
-			if (set_mcast_group(ctx,user_param,mcg_params)) {
-				return 1;
-			}
-
-			my_dest[i].gid = mcg_params->mgid;
-			my_dest[i].lid = mcg_params->mlid;
-			my_dest[i].qpn = QPNUM_MCAST;
 
-		} else {
-			memcpy(my_dest[i].gid.raw,temp_gid.raw ,16);
-			my_dest[i].lid   	   = ctx_get_local_lid(ctx->context,user_param->ib_port);
-			my_dest[i].qpn   	   = ctx->qp[i]->qp_num;
-		}
+	if (user_param->use_mcg && (user_param->duplex || user_param->machine == SERVER)) {
 
-		my_dest[i].psn = lrand48() & 0xffffff;
-
-		/* We do not fail test upon lid above RoCE. */
-		if (user_param->gid_index < 0) {
-			if (!my_dest->lid) {
-				fprintf(stderr," Local lid 0x0 detected,without any use of gid. Is SM running?\n");
-				return -1;
-			}
+		mcg_params->user_mgid = user_param->user_mgid;
+		set_multicast_gid(mcg_params,ctx->qp[0]->qp_num,(int)user_param->machine);
+		if (set_mcast_group(ctx,user_param,mcg_params)) {
+			return 1;
 		}
 
-		#ifdef HAVE_XRCD
-		if (user_param->use_xrc || user_param->connection_type == DC) {
-			if (ibv_get_srq_num(ctx->srq,&(my_dest[i].srqn))) {
-				fprintf(stderr, "Couldn't get SRQ number\n");
+		for (i=0; i < user_param->num_of_qps; i++) {
+			if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) {
+				fprintf(stderr, "Couldn't attach QP to MultiCast group");
 				return 1;
 			}
 		}
-		#endif
 
-		#ifdef HAVE_DC
-		if (user_param->connection_type == DC) {
-			if (ibv_get_srq_num(ctx->srq,&(my_dest[i].srqn))) {
-				fprintf(stderr, "Couldn't get SRQ number\n");
-				return 1;
-			}
-		}
-		#endif
+		mcg_params->mcast_state |= MCAST_IS_ATTACHED;
+		my_dest->gid = mcg_params->mgid;
+		my_dest->lid = mcg_params->mlid;
+		my_dest->qpn = QPNUM_MCAST;
 	}
 
 	return 0;

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



More information about the Pkg-ofed-commits mailing list