├── .gitignore ├── COPYING ├── Makefile.am ├── README ├── README_sparc ├── autogen.sh ├── configure.ac ├── debian ├── changelog ├── control ├── perftest.install └── rules ├── hsainfo.py ├── perftest.spec ├── run_perftest_loopback ├── runme └── src ├── atomic_bw.c ├── atomic_lat.c ├── clock_test.c ├── get_clock.c ├── get_clock.h ├── multicast_resources.c ├── multicast_resources.h ├── perftest_communication.c ├── perftest_communication.h ├── perftest_parameters.c ├── perftest_parameters.h ├── perftest_resources.c ├── perftest_resources.h ├── raw_ethernet_resources.c ├── raw_ethernet_resources.h ├── raw_ethernet_send_bw.c ├── raw_ethernet_send_lat.c ├── read_bw.c ├── read_lat.c ├── send_bw.c ├── send_lat.c ├── write_bw.c └── write_lat.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object Files 2 | *.o 3 | *.lo 4 | *.la 5 | 6 | # Libraries 7 | *.lib 8 | *.a 9 | .libs 10 | 11 | # Shared objects 12 | *.so 13 | *.so.* 14 | 15 | # Dependencies 16 | .dirstamp 17 | .deps 18 | 19 | # Automake 20 | Makefile 21 | Makefile.in 22 | aclocal.m4 23 | autom4te.cache/ 24 | config.h 25 | config.h.in 26 | config.log 27 | config.status 28 | config/ 29 | configure 30 | libtool 31 | m4/ 32 | stamp-h1 33 | 34 | # Project/Eclipse 35 | .cproject 36 | .project 37 | 38 | #Ctags 39 | tags 40 | 41 | #Programs 42 | ib_atomic_bw 43 | ib_atomic_lat 44 | ib_read_bw 45 | ib_read_lat 46 | ib_send_bw 47 | ib_send_lat 48 | ib_write_bw 49 | ib_write_lat 50 | raw_ethernet_bw 51 | raw_ethernet_lat 52 | 53 | #Debian Stuff 54 | debian/compat 55 | debian/*.log 56 | debian/files 57 | debian/perftest 58 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | This software is available to you under a choice of one of two 2 | licenses. You may choose to be licensed under the terms of the GNU 3 | General Public License (GPL) Version 2, available from the file 4 | COPYING in the main directory of this source tree, or the 5 | OpenIB.org BSD license below: 6 | 7 | Redistribution and use in source and binary forms, with or 8 | without modification, are permitted provided that the following 9 | conditions are met: 10 | 11 | - Redistributions of source code must retain the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer. 14 | 15 | - Redistributions in binary form must reproduce the above 16 | copyright notice, this list of conditions and the following 17 | disclaimer in the documentation and/or other materials 18 | provided with the distribution. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 24 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 25 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) Mellanox Technologies Ltd. 2001-2011. ALL RIGHTS RESERVED. 3 | # This software product is a proprietary product of Mellanox Technologies Ltd. 4 | # (the "Company") and all right, title, and interest and to the software product, 5 | # including all associated intellectual property rights, are and shall 6 | # remain exclusively with the Company. 7 | # 8 | # This software product is governed by the End User License Agreement 9 | # provided with the software product. 10 | # $COPYRIGHT$ 11 | # $HEADER$ 12 | # 13 | 14 | ACLOCAL_AMFLAGS= -I m4 15 | AUTOMAKE_OPTIONS= subdir-objects 16 | 17 | noinst_LIBRARIES = libperftest.a 18 | libperftest_a_SOURCES = src/get_clock.c src/perftest_communication.c src/perftest_parameters.c src/perftest_resources.c 19 | noinst_HEADERS = src/get_clock.h src/perftest_communication.h src/perftest_parameters.h src/perftest_resources.h 20 | 21 | bin_PROGRAMS = ib_send_bw ib_send_lat ib_write_lat ib_write_bw ib_read_lat ib_read_bw ib_atomic_lat ib_atomic_bw 22 | bin_SCRIPTS = run_perftest_loopback 23 | 24 | if HAVE_RAW_ETH 25 | libperftest_a_SOURCES += src/raw_ethernet_resources.c 26 | noinst_HEADERS += src/raw_ethernet_resources.h 27 | bin_PROGRAMS += raw_ethernet_bw raw_ethernet_lat 28 | else 29 | libperftest_a_SOURCES += 30 | noinst_HEADERS += 31 | bin_PROGRAMS += 32 | endif 33 | 34 | ib_send_bw_SOURCES = src/send_bw.c src/multicast_resources.c src/multicast_resources.h 35 | ib_send_bw_LDADD = libperftest.a $(LIBUMAD) $(LIBMATH) 36 | 37 | ib_send_lat_SOURCES = src/send_lat.c src/multicast_resources.c src/multicast_resources.h 38 | ib_send_lat_LDADD = libperftest.a $(LIBUMAD) $(LIBMATH) 39 | 40 | ib_write_lat_SOURCES = src/write_lat.c 41 | ib_write_lat_LDADD = libperftest.a $(LIBMATH) 42 | 43 | ib_write_bw_SOURCES = src/write_bw.c 44 | ib_write_bw_LDADD = libperftest.a $(LIBMATH) 45 | 46 | ib_read_lat_SOURCES = src/read_lat.c 47 | ib_read_lat_LDADD = libperftest.a $(LIBMATH) 48 | 49 | ib_read_bw_SOURCES = src/read_bw.c 50 | ib_read_bw_LDADD = libperftest.a $(LIBMATH) 51 | 52 | ib_atomic_lat_SOURCES = src/atomic_lat.c 53 | ib_atomic_lat_LDADD = libperftest.a $(LIBMATH) 54 | 55 | ib_atomic_bw_SOURCES = src/atomic_bw.c 56 | ib_atomic_bw_LDADD = libperftest.a $(LIBMATH) 57 | 58 | if HAVE_RAW_ETH 59 | raw_ethernet_bw_SOURCES = src/raw_ethernet_send_bw.c 60 | raw_ethernet_bw_LDADD = libperftest.a $(LIBMATH) 61 | 62 | raw_ethernet_lat_SOURCES = src/raw_ethernet_send_lat.c 63 | raw_ethernet_lat_LDADD = libperftest.a $(LIBMATH) 64 | 65 | else 66 | raw_ethernet_bw_SOURCES = 67 | raw_ethernet_bw_LDADD = 68 | 69 | raw_ethernet_lat_SOURCES = 70 | raw_ethernet_lat_LDADD = 71 | 72 | endif 73 | 74 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Open Fabrics Enterprise Distribution (OFED) 2 | Performance Tests README for OFED 3.0 3 | 4 | March 2015 5 | 6 | 7 | 8 | =============================================================================== 9 | Table of Contents 10 | =============================================================================== 11 | 1. Overview 12 | 2. Notes on Testing Methodology 13 | 3. Test Descriptions 14 | 4. Running Tests 15 | 5. Known Issues 16 | 17 | =============================================================================== 18 | 1. Overview 19 | =============================================================================== 20 | This is a collection of tests written over uverbs intended for use as a 21 | performance micro-benchmark. The tests may be used for HW or SW tuning 22 | as well as for functional testing. 23 | 24 | The collection contains a set of bandwidth and latency benchmark such as: 25 | 26 | * Send - ib_send_bw and ib_send_lat 27 | * RDMA Read - ib_read_bw and ib_read_lat 28 | * RDMA Write - ib_write_bw and ib_wriet_lat 29 | * RDMA Atomic - ib_atomic_bw and ib_atomic_lat 30 | * Native Ethernet (when working with MOFED2) - raw_ethernet_bw, raw_ethernet_lat 31 | 32 | Please post results/observations to the openib-general mailing list. 33 | See "Contact Us" at http://openib.org/mailman/listinfo/openib-general and 34 | http://www.openib.org. 35 | 36 | =============================================================================== 37 | 2. Notes on Testing Methodology 38 | =============================================================================== 39 | - The benchmarks use the CPU cycle counter to get time stamps without context 40 | switch. Some CPU architectures (e.g., Intel's 80486 or older PPC) do not 41 | have such capability. 42 | 43 | - The latency benchmarks measure round-trip time but report half of that as one-way 44 | latency. This means that the results may not be accurate for asymmetrical configurations. 45 | 46 | - On all unidirectional bandwidth benchmarks, the client measures the bandwidth. 47 | On bidirectional bandwidth benchmarks, each side measured the bandwidth of 48 | the traffic it initiates, and at the end of the measurement period, the server 49 | reports the result to the client, who combines them together. 50 | 51 | - Latency tests report minimum, median and maximum latency results. 52 | The median latency is typically less sensitive to high latency variations, 53 | compared to average latency measurement. 54 | Typically, the first value measured is the maximum value, due to warmup effects. 55 | 56 | - Long sampling periods have very limited impact on measurement accuracy. 57 | The default value of 1000 iterations is pretty good. 58 | Note that the program keeps data structures with memory footprint proportional 59 | to the number of iterations. Setting a very high number of iteration may 60 | have negative impact on the measured performance which are not related to 61 | the devices under test. 62 | If a high number of iterations is strictly necessary, it is recommended to 63 | use the -N flag (No Peak). 64 | 65 | - Bandwidth benchmarks may be run for a number of iterations, or for a fixed duration. 66 | Use the -D flag to instruct the test to run for the specified number of seconds. 67 | The --run_infinitely flag instructs the program to run until interrupted by 68 | the user, and print the measured bandwidth every 5 seconds. 69 | 70 | - The "-H" option in latency benchmarks dumps a histogram of the results. 71 | See xgraph, ygraph, r-base (http://www.r-project.org/), PSPP, or other 72 | statistical analysis programs. 73 | 74 | *** IMPORTANT NOTE: 75 | When running the benchmarks over an Infiniband fabric, 76 | a Subnet Manager must run on the switch or on one of the 77 | nodes in your fabric, prior to starting the benchmarks. 78 | 79 | Architectures tested: i686, x86_64, ia64 80 | 81 | =============================================================================== 82 | 3. Benchmarks Description 83 | =============================================================================== 84 | 85 | The benchmarks generate a synthetic stream of operations, which is very useful 86 | for hardware and software benchmarking and analysis. 87 | The benchmarks are not designed to emulate any real application traffic. 88 | Real application traffic may be affected by many parameters, and hence 89 | might not be predictable based only on the results of those benchmarks. 90 | 91 | ib_send_lat latency test with send transactions 92 | ib_send_bw bandwidth test with send transactions 93 | ib_write_lat latency test with RDMA write transactions 94 | ib_write_bw bandwidth test with RDMA write transactions 95 | ib_read_lat latency test with RDMA read transactions 96 | ib_read_bw bandwidth test with RDMA read transactions 97 | ib_atomic_lat latency test with atomic transactions 98 | ib_atomic_bw bandwidth test with atomic transactions 99 | 100 | Raw Ethernet interface benchmarks: 101 | raw_ethernet_send_lat latency test over raw Etherent interface 102 | raw_ethernet_send_bw bandwidth test over raw Etherent interface 103 | 104 | =============================================================================== 105 | 4. Running Tests 106 | =============================================================================== 107 | 108 | Prerequisites: 109 | kernel 2.6 110 | (kernel module) matches libibverbs 111 | (kernel module) matches librdmacm 112 | (kernel module) matches libibumad 113 | (kernel module) matches libmath (lm). 114 | 115 | 116 | Server: ./ 117 | Client: ./ 118 | 119 | o is IPv4 or IPv6 address. You can use the IPoIB 120 | address if IPoIB is configured. 121 | o --help lists the available 122 | 123 | *** IMPORTANT NOTE: 124 | The SAME OPTIONS must be passed to both server and client. 125 | 126 | Common Options to all tests: 127 | ---------------------------- 128 | -h, --help Display this help message screen 129 | -p, --port= Listen on/connect to port (default: 18515) 130 | -R, --rdma_cm Connect QPs with rdma_cm and run test on those QPs 131 | -z, --com_rdma_cm Communicate with rdma_cm module to exchange data - use regular QPs 132 | -m, --mtu= QP Mtu size (default: active_mtu from ibv_devinfo) 133 | -c, --connection= Connection type RC/UC/UD/XRC/DC (default RC). 134 | -d, --ib-dev= Use IB device (default: first device found) 135 | -i, --ib-port= Use network port of IB device (default: 1) 136 | -s, --size= Size of message to exchange (default: 1) 137 | -a, --all Run sizes from 2 till 2^23 138 | -n, --iters= Number of exchanges (at least 100, default: 1000) 139 | -x, --gid-index= Test uses GID with GID index taken from command 140 | -V, --version Display version number 141 | -e, --events Sleep on CQ events (default poll) 142 | -F, --CPU-freq Do not fail even if cpufreq_ondemand module 143 | -I, --inline_size= Max size of message to be sent in inline mode 144 | -u, --qp-timeout= QP timeout = (4 uSec)*(2^timeout) (default: 14) 145 | -S, --sl= Service Level (default 0) 146 | -r, --rx-depth= Receive queue depth (default 600) 147 | 148 | Options for latency tests: 149 | -------------------------- 150 | 151 | -C, --report-cycles Report times in CPU cycle units 152 | -H, --report-histogram Print out all results (Default: summary only) 153 | -U, --report-unsorted Print out unsorted results (default sorted) 154 | 155 | Options for BW tests: 156 | --------------------- 157 | 158 | -b, --bidirectional Measure bidirectional bandwidth (default uni) 159 | -N, --no peak-bw Cancel peak-bw calculation (default with peak-bw) 160 | -Q, --cq-mod Generate Cqe only after completion 161 | -t, --tx-depth= Size of tx queue (default: 128) 162 | -O, --dualport Run test in dual-port mode (2 QPs). Both ports must be active (default OFF) 163 | -D, --duration= Run test for period of seconds 164 | -f, --margin= When in Duration, measure results within margins (default: 2) 165 | -l, --post_list= Post list of WQEs of size (instead of single post) 166 | -q, --qp= Num of QPs running in the process (default: 1) 167 | --run_infinitely Run test until interrupted by user, print results every 5 seconds 168 | 169 | SEND tests (ib_send_lat or ib_send_bw) flags: 170 | --------------------------------------------- 171 | 172 | -r, --rx-depth= Size of receive queue (default: 512 in BW test) 173 | -g, --mcg= Send messages to multicast group with qps attached to it 174 | -M, --MGID= In multicast, uses as the group MGID 175 | 176 | ATOMIC tests (ib_atomic_lat or ib_atomic_bw) flags: 177 | --------------------------------------------------- 178 | 179 | -A, --atomic_type= type of atomic operation from {CMP_AND_SWAP,FETCH_AND_ADD} 180 | -o, --outs= Number of outstanding read/atomic requests - also on READ tests 181 | 182 | Options for raw_ethernet_send_bw: 183 | --------------------------------- 184 | -B, --source_mac source MAC address by this format XX:XX:XX:XX:XX:XX (default take the MAC address form GID) 185 | -E, --dest_mac destination MAC address by this format XX:XX:XX:XX:XX:XX **MUST** be entered 186 | -J, --server_ip server ip address by this format X.X.X.X (using to send packets with IP header) 187 | -j, --client_ip client ip address by this format X.X.X.X (using to send packets with IP header) 188 | -K, --server_port server udp port number (using to send packets with UPD header) 189 | -k, --client_port client udp port number (using to send packets with UDP header) 190 | -Z, --server choose server side for the current machine (--server/--client must be selected) 191 | -P, --client choose client side for the current machine (--server/--client must be selected) 192 | 193 | ---------------------------------------------- 194 | Special feature detailed explanation in tests: 195 | ---------------------------------------------- 196 | 197 | 1. Usage of post_list feature (-l, --post_list=). 198 | In this case, each QP will prepare ibv_send_wr (instead of 1), and will chain them to each other. 199 | In chaining we mean allocating array, and setting 'next' pointer of each ibv_send_wr in the array 200 | to point to the following element in the array. the last ibv_send_wr in the array will point to NULL. 201 | In this case, when post sending the first ibv_send_wr in the list, will instruct the HW to post all of those WQEs. 202 | Which means each post_send will post messages. 203 | This feature is good we want to know the maximum message rate of QPs in a single process. 204 | Since we are limited to SW post_send (~ 10 Mpps, since we have ~ 500 ns between each SW post_send), we can see 205 | the true HW message rate when setting of 64 (for example) since it's not depended on SW limitations. 206 | 207 | 2. RDMA Connected Mode (CM) 208 | You can add the "-R" flag to all tests to connect the QPs from each side with the rdma_cm library. 209 | In this case, the library will connect the QPs and will use the IPoIB interface for doing it. 210 | It helps when you don't have Ethernet connection between the 2 nodes. 211 | You must supply the IPoIB interface as the server IP. 212 | 213 | 3. Multicast support in ib_send_lat and in ib_send_bw 214 | Send tests have built in feature of testing multicast performance, in verbs level. 215 | You can use "-g" to specify the number of QPs to attach to this multicast group. 216 | "-M" flag allows you to choose the multicast group address. 217 | 218 | 219 | =============================================================================== 220 | 5. Known Issues 221 | =============================================================================== 222 | 223 | 1. Multicast support in ib_send_lat and in ib_send_bw is not stable. 224 | The benchmark program may hang or exhibit other unexpected behavior. 225 | 226 | 2. Bidirectional support in ib_send_bw test, when running in UD or UC mode. 227 | In rare cases, the benchmark program may hang. 228 | perftest-2.3 release includes a feature for hang detection, which will exit test after 2 mins in those situations. 229 | 230 | 3. Different versions of perftest may not be compatible with each other. 231 | Please use the same perftest version on both sides to ensure consistency of benchmark results. 232 | 233 | 4. Test version 5.3 and above won't work with previous versions of perftest. 234 | 235 | 5. This perftest package won't compile on MLNX_OFED-2.1 due to API changes in MLNX_OFED-2.2 236 | In order to compile it properly, please do: 237 | ./configure --disable-verbs_exp 238 | make 239 | 240 | 6. In te x390x platform virtualized environment the results shown by package test applications can be incorrect. 241 | 242 | 7. perftest-2.3 release includes support for dualport VPI test - port1-Ethernet , port2-IB. (in addition to Eth:Eth, IB:IB) 243 | Currently, running dualport when port1-IB , port2-Ethernet still not working. 244 | 245 | 8. for postlist, tests will not finish correctly when using iterations and num_iters/poslist_val has a remainder. 246 | -------------------------------------------------------------------------------- /README_sparc: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Build instructions: 3 | ======================================= 4 | 5 | # ./autogen.sh 6 | 7 | # ./configure --build= --host=sparc64-redhat-linux-gnu 8 | --target=sparc64-linux --program-prefix= --prefix=/usr 9 | --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin 10 | --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include 11 | --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var 12 | --sharedstatedir=/var/lib --mandir=/usr/share/man 13 | --infodir=/usr/share/info 14 | 15 | # make clean && make V=1 16 | 17 | 18 | ======================================= 19 | RPM queries: 20 | ======================================= 21 | 22 | # rpm --eval %{_target} 23 | sparc64-linux 24 | 25 | # rpm --eval %{_host} 26 | sparc64-redhat-linux-gnu 27 | 28 | 29 | ======================================= 30 | GCC queries: 31 | ======================================= 32 | 33 | Get all the gcc definitions for the platform: 34 | 35 | # gcc -E -dM - < /dev/null 36 | ... 37 | #define __sparc__ 1 38 | ... 39 | #define __arch64__ 1 40 | ... 41 | 42 | 43 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | test -d ./config || mkdir ./config 4 | mkdir -p m4 config/m4 config/aux 5 | aclocal -I config 6 | libtoolize --force --copy 7 | autoheader 8 | automake --foreign --add-missing --copy 9 | autoconf 10 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) Mellanox Technologies Ltd. 2001-2011. ALL RIGHTS RESERVED. 3 | # This software product is a proprietary product of Mellanox Technologies Ltd. 4 | # (the "Company") and all right, title, and interest and to the software product, 5 | # including all associated intellectual property rights, are and shall 6 | # remain exclusively with the Company. 7 | # 8 | # This software product is governed by the End User License Agreement 9 | # provided with the software product. 10 | # $COPYRIGHT$ 11 | # $HEADER$ 12 | dnl Process this file with autoconf to produce a configure script. 13 | 14 | AC_INIT([perftest],[5.5],[linux-rdma@vger.kernel.org]) 15 | AC_CONFIG_HEADERS([config.h]) 16 | AC_CONFIG_AUX_DIR([config]) 17 | AC_CONFIG_MACRO_DIR([m4]) 18 | AM_INIT_AUTOMAKE([foreign]) 19 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 20 | 21 | AC_SUBST(MAJOR_VERSION) 22 | AC_SUBST(MINOR_VERSION) 23 | 24 | AC_ARG_VAR(CUDA_H_PATH, help-string) 25 | AC_ARG_VAR(RANLIB, ranlib tool) 26 | 27 | AC_ARG_VAR(HSA_INC_PATH, Location of HSA header files to enable ROCm support) 28 | 29 | 30 | AC_ARG_ENABLE([verbs_exp], 31 | [AS_HELP_STRING([--disable-verbs_exp], 32 | [Disable Verbs Experimental])], 33 | [], [enable_verbs_exp=yes]) 34 | 35 | AS_IF([test "x$enable_verbs_exp" = "xyes"], 36 | [USE_VERBS_EXP=yes], 37 | [USE_VERBS_EXP=no]) 38 | 39 | AC_PROG_CC 40 | AC_PROG_CXX 41 | AM_PROG_AS 42 | AC_PROG_INSTALL 43 | AC_PROG_LIBTOOL 44 | AC_PROG_RANLIB 45 | AC_HEADER_STDC 46 | AC_CHECK_HEADERS([infiniband/verbs.h],,[AC_MSG_ERROR([ibverbs header files not found])]) 47 | AC_CHECK_LIB([ibverbs], [ibv_get_device_list], [], [AC_MSG_ERROR([libibverbs not found])]) 48 | AC_CHECK_LIB([rdmacm], [rdma_create_event_channel], [], AC_MSG_ERROR([librdmacm-devel not found])) 49 | AC_CHECK_LIB([ibumad], [umad_init], [LIBUMAD=-libumad], AC_MSG_ERROR([libibumad not found])) 50 | AC_CHECK_LIB([m], [log], [LIBMATH=-lm], AC_MSG_ERROR([libm not found])) 51 | 52 | AC_TRY_LINK([#include ], 53 | [struct ibv_exp_flow *t = ibv_exp_create_flow(NULL,NULL);],[HAVE_RAW_ETH_EXP=yes], [HAVE_RAW_ETH_EXP=no]) 54 | 55 | AM_CONDITIONAL([HAVE_RAW_ETH_EXP],[test "x$HAVE_RAW_ETH_EXP" = "xyes"]) 56 | if test $HAVE_RAW_ETH_EXP = yes; then 57 | AC_DEFINE([HAVE_RAW_ETH_EXP], [1], [Enable RAW_ETH_TEST_EXP]) 58 | fi 59 | 60 | AC_TRY_LINK([#include ], 61 | [struct ibv_flow *t = ibv_create_flow(NULL,NULL);],[HAVE_RAW_ETH_REG=yes], [HAVE_RAW_ETH_REG=no]) 62 | 63 | AM_CONDITIONAL([HAVE_RAW_ETH_REG],[test "x$HAVE_RAW_ETH_REG" = "xyes"]) 64 | if test $HAVE_RAW_ETH_REG = yes; then 65 | AC_DEFINE([HAVE_RAW_ETH_REG], [1], [Enable RAW_ETH_TEST_REG]) 66 | fi 67 | 68 | AM_CONDITIONAL([HAVE_RAW_ETH],true) 69 | if [test $HAVE_RAW_ETH_REG = yes] || [test $HAVE_RAW_ETH_EXP = yes]; then 70 | AC_DEFINE([HAVE_RAW_ETH], [1], [Enable RAW_ETH_TEST]) 71 | else 72 | AM_CONDITIONAL([HAVE_RAW_ETH],false) 73 | fi 74 | 75 | 76 | AC_TRY_LINK([#include ], 77 | [struct ibv_xrcd *t = ibv_open_xrcd(NULL,NULL);],[HAVE_XRCD=yes], [HAVE_XRCD=no]) 78 | 79 | AM_CONDITIONAL([HAVE_XRCD],[test "x$HAVE_XRCD" = "xyes"]) 80 | if test $HAVE_XRCD = yes; then 81 | AC_DEFINE([HAVE_XRCD], [1], [Enable XRCD feature]) 82 | fi 83 | 84 | AC_TRY_LINK([#include ], 85 | [int x = htobe32(0);],[HAVE_ENDIAN=yes], [HAVE_ENDIAN=no]) 86 | 87 | AM_CONDITIONAL([HAVE_ENDIAN],[test "x$HAVE_ENDIAN" = "xyes"]) 88 | if test $HAVE_ENDIAN = yes; then 89 | AC_DEFINE([HAVE_ENDIAN], [1], [Enable endian conversion]) 90 | fi 91 | 92 | AC_TRY_LINK([#include ], 93 | [char *c = IBV_LINK_LAYER_SCIF;],[HAVE_SCIF=yes], [HAVE_SCIF=no]) 94 | 95 | AM_CONDITIONAL([HAVE_SCIF],[test "x$HAVE_SCIF" = "xyes"]) 96 | if test $HAVE_SCIF = yes; then 97 | AC_DEFINE([HAVE_SCIF], [1], [Enable SCIF link Layer]) 98 | fi 99 | 100 | AC_CHECK_HEADERS([infiniband/verbs_exp.h],[HAVE_VERBS_EXP=yes],[HAVE_VERBS_EXP=no],[#include ]) 101 | AM_CONDITIONAL([HAVE_VERBS_EXP],[test "x$HAVE_VERBS_EXP" = "xyes"]) 102 | if [test $HAVE_VERBS_EXP = yes] && [test $USE_VERBS_EXP = yes]; then 103 | AC_DEFINE([HAVE_VERBS_EXP], [1], [Have verbs_exp header]) 104 | else 105 | HAVE_VERBS_EXP=no 106 | fi 107 | 108 | AC_TRY_LINK([ 109 | #include 110 | #include ], 111 | [int x = IBV_EXP_DEVICE_ATTR_EXT_ATOMIC_ARGS;],[HAVE_MASKED_ATOMICS=yes], [HAVE_MASKED_ATOMICS=no]) 112 | AM_CONDITIONAL([HAVE_MASKED_ATOMICS],[test "x$HAVE_MASKED_ATOMICS" = "xyes"]) 113 | if [test $HAVE_MASKED_ATOMICS = yes] && [test $HAVE_VERBS_EXP = yes]; then 114 | AC_DEFINE([HAVE_MASKED_ATOMICS], [1], [Have MASKED ATOMICS in verbs_exp header]) 115 | fi 116 | 117 | AC_TRY_LINK([ 118 | #include 119 | #include ], 120 | [int x = IBV_EXP_DEVICE_ATTR_RSS_TBL_SZ;],[HAVE_RSS_EXP=yes], [HAVE_RSS_EXP=no]) 121 | AM_CONDITIONAL([HAVE_RSS_EXP],[test "x$HAVE_RSS_EXP" = "xyes"]) 122 | if [test $HAVE_RSS_EXP = yes] && [test $HAVE_VERBS_EXP = yes]; then 123 | AC_DEFINE([HAVE_RSS_EXP], [1], [Have RSS in verbs_exp header]) 124 | fi 125 | 126 | AC_TRY_LINK([ 127 | #include 128 | #include ], 129 | [int x = IBV_EXP_DCT_CREATE_FLAGS_MASK;],[HAVE_DC=yes], [HAVE_DC=no]) 130 | AM_CONDITIONAL([HAVE_DC],[test "x$HAVE_DC" = "xyes"]) 131 | if [test $HAVE_DC = yes] && [test $HAVE_VERBS_EXP = yes]; then 132 | AC_DEFINE([HAVE_DC], [1], [Enable DC feature]) 133 | fi 134 | 135 | AC_TRY_LINK([ 136 | #include 137 | #include ], 138 | [int x = IBV_EXP_INTF_GLOBAL;],[HAVE_ACCL_VERBS=yes], [HAVE_ACCL_VERBS=no]) 139 | AM_CONDITIONAL([HAVE_ACCL_VERBS],[test "x$HAVE_ACCL_VERBS" = "xyes"]) 140 | if [test $HAVE_ACCL_VERBS = yes] && [test $HAVE_VERBS_EXP = yes]; then 141 | AC_DEFINE([HAVE_ACCL_VERBS], [1], [Enable Accelerated verbs feature]) 142 | fi 143 | 144 | AC_TRY_LINK([ 145 | #include 146 | #include ], 147 | [int x = IBV_EXP_ACCESS_ON_DEMAND;],[HAVE_ODP=yes], [HAVE_ODP=no]) 148 | AM_CONDITIONAL([HAVE_ODP],[test "x$HAVE_ODP" = "xyes"]) 149 | if [test $HAVE_ODP = yes] && [test $HAVE_VERBS_EXP = yes]; then 150 | AC_DEFINE([HAVE_ODP], [1], [Have ODP support]) 151 | fi 152 | 153 | if [test "$CUDA_H_PATH" ]; then 154 | AC_DEFINE([HAVE_CUDA], [1], [Enable CUDA feature]) 155 | AC_DEFINE_UNQUOTED([CUDA_PATH], "$CUDA_H_PATH" , [Enable CUDA feature]) 156 | LIBS=$LIBS" -lcuda" 157 | fi 158 | 159 | if [test "$HSA_INC_PATH" ]; then 160 | AC_MSG_NOTICE([Enable ROCm Support]) 161 | AC_CHECK_SIZEOF([void*]) 162 | if test "x$ac_cv_sizeof_voidp" == "x"; then 163 | AC_ERROR([Cannot determine size of void*]) 164 | fi 165 | if test "${ac_cv_sizeof_voidp}" = "4"; then 166 | AC_ERROR([You are trying to enable HSA support on a 32-bit platform]) 167 | fi 168 | AC_DEFINE([HAVE_ROCM], [1], [Enable ROCm platform support]) 169 | AC_DEFINE_UNQUOTED([HSA_PATH], "$HSA_INC_PATH/hsa.h" , [Enable HSA feature]) 170 | AC_DEFINE_UNQUOTED([HSA_EXT_AMD_PATH], "$HSA_INC_PATH/hsa_ext_amd.h" , [Enable HSA AMD extension]) 171 | 172 | AC_SEARCH_LIBS([hsa_init], [hsa-runtime64], [], [ 173 | AC_MSG_ERROR([Unable to find libhsa-runtime64 library]) 174 | ]) 175 | fi 176 | 177 | CFLAGS="-g -Wall -D_GNU_SOURCE -O3" 178 | AC_SUBST([LIBUMAD]) 179 | AC_SUBST([LIBMATH]) 180 | AC_CONFIG_FILES([Makefile]) 181 | AC_OUTPUT 182 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | perftest (3.0-0) stable; urgency=low 2 | 3 | * Initial release For Ubuntu (Closes: #182805) 4 | 5 | -- Gil Rockah Sun, 29 March 2015 10:58:00 +0200 6 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: perftest 2 | Section: net 3 | Priority: extra 4 | Maintainer: Gil Rockah 5 | Build-Depends: debhelper (>= 8.0.0), libibverbs-dev (>= 1.1.6), librdmacm-dev 6 | Standards-Version: 3.9.2 7 | Homepage: https://openfabrics.org/downloads/perftest/ 8 | Vcs-Git: git://git.openfabrics.org/~shamoya/perftest.git 9 | Vcs-Browser: http://git.openfabrics.org/git?p=~shamoya/perftest.git;a=summary 10 | 11 | Package: perftest 12 | Architecture: any 13 | Depends: ${shlibs:Depends}, ${misc:Depends}, libibverbs1 (>= 1.1.6), librdmacm1 (>=1.0.8) 14 | Description: Infiniband verbs performance tests 15 | This is a collection of tests written using Infiniband verbs intended for 16 | use as a performance micro-benchmark. The tests can measure the latency 17 | bandwidth and message rate of Infiniband or Ethernet (RoCE) fabrics. 18 | -------------------------------------------------------------------------------- /debian/perftest.install: -------------------------------------------------------------------------------- 1 | ib_atomic_bw usr/bin/ 2 | ib_atomic_lat usr/bin/ 3 | ib_read_bw usr/bin/ 4 | ib_read_lat usr/bin/ 5 | ib_send_bw usr/bin/ 6 | ib_send_lat usr/bin/ 7 | ib_write_bw usr/bin/ 8 | ib_write_lat usr/bin/ 9 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # 5 | # This file was originally written by Joey Hess and Craig Small. 6 | # As a special exception, when this file is copied by dh-make into a 7 | # dh-make output file, you may use that output file without restriction. 8 | # This special exception was added by Craig Small in version 0.37 of dh-make. 9 | # 10 | # Modified to make a template file for a multi-binary package with separated 11 | # build-arch and build-indep targets by Bill Allombert 2001 12 | 13 | # Uncomment this to turn on verbose mode. 14 | #export DH_VERBOSE=1 15 | 16 | # This has to be exported to make some magic below work. 17 | export DH_OPTIONS 18 | 19 | 20 | %: 21 | dh $@ 22 | -------------------------------------------------------------------------------- /hsainfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright 2016 Advanced Micro Devices, Inc. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a 5 | # copy of this software and associated documentation files (the "Software"), 6 | # to deal in the Software without restriction, including without limitation 7 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | # and/or sell copies of the Software, and to permit persons to whom the 9 | # Software is furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 | # OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | import ctypes 22 | import ctypes.util 23 | import os 24 | 25 | args = {} 26 | 27 | # Define HSA related constant borrowed from C header file 28 | HSA_DEVICE_TYPE_GPU = 1 29 | 30 | HSA_AGENT_INFO_NAME = 0 31 | HSA_AGENT_INFO_VENDOR_NAME = 1 32 | HSA_AGENT_INFO_FEATURE = 2 33 | HSA_AGENT_INFO_MACHINE_MODEL = 3 34 | HSA_AGENT_INFO_PROFILE = 4 35 | HSA_AGENT_INFO_DEVICE = 17 36 | 37 | 38 | HSA_AMD_AGENT_INFO_BDFID = 0xA006 39 | HSA_AMD_AGENT_INFO_CHIP_ID = 0xA000 40 | 41 | 42 | HSA_REGION_INFO_SEGMENT = 0 43 | HSA_REGION_INFO_GLOBAL_FLAGS = 1 44 | HSA_REGION_INFO_SIZE = 2 45 | HSA_REGION_INFO_ALLOC_MAX_SIZE = 4 46 | HSA_REGION_INFO_RUNTIME_ALLOC_ALLOWED = 5 47 | HSA_REGION_INFO_RUNTIME_ALLOC_GRANULE = 6 48 | HSA_REGION_INFO_RUNTIME_ALLOC_ALIGNMENT = 7 49 | 50 | HSA_AMD_REGION_INFO_HOST_ACCESSIBLE = 0xA000 51 | HSA_AMD_REGION_INFO_BASE = 0xA001 52 | HSA_AMD_REGION_INFO_BUS_WIDTH = 0xA002 53 | 54 | 55 | HSA_REGION_SEGMENT_GLOBAL = 0 56 | HSA_REGION_SEGMENT_READONLY = 1 57 | HSA_REGION_SEGMENT_PRIVATE = 2 58 | HSA_REGION_SEGMENT_GROUP = 3 59 | 60 | 61 | # Define map to convert id to string 62 | hsa_segment_name = { HSA_REGION_SEGMENT_GLOBAL : "HSA_REGION_SEGMENT_GLOBAL" , 63 | HSA_REGION_SEGMENT_READONLY : "HSA_REGION_SEGMENT_READONLY", 64 | HSA_REGION_SEGMENT_PRIVATE : "HSA_REGION_SEGMENT_PRIVATE", 65 | HSA_REGION_SEGMENT_GROUP : "HSA_REGION_SEGMENT_GROUP" 66 | } 67 | 68 | 69 | 70 | HSA_AMD_MEMORY_POOL_INFO_SEGMENT = 0 71 | HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS = 1 72 | HSA_AMD_MEMORY_POOL_INFO_SIZE = 2 73 | HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED = 5 74 | HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE = 6 75 | HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT = 7 76 | HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL = 15 77 | 78 | 79 | HSA_AMD_SEGMENT_GLOBAL = 0 80 | HSA_AMD_SEGMENT_READONLY = 1 81 | HSA_AMD_SEGMENT_PRIVATE = 2 82 | HSA_AMD_SEGMENT_GROUP = 3 83 | 84 | # Define map to convert id to string 85 | hsa_amd_segment_name = { HSA_AMD_SEGMENT_GLOBAL : "HSA_AMD_SEGMENT_GLOBAL" , 86 | HSA_AMD_SEGMENT_READONLY : "HSA_AMD_SEGMENT_READONLY", 87 | HSA_AMD_SEGMENT_PRIVATE : "HSA_AMD_SEGMENT_PRIVATE", 88 | HSA_AMD_SEGMENT_GROUP : "HSA_AMD_SEGMENT_GROUP" 89 | } 90 | 91 | 92 | # Load HSA RT library 93 | hsalibpath = ctypes.util.find_library("hsa-runtime64") 94 | 95 | if hsalibpath == None: 96 | hsalibpath = "/opt/hsa/lib/libhsa-runtime64.so" 97 | 98 | try: 99 | hsa = ctypes.CDLL(hsalibpath) 100 | except: 101 | hsalibpath = os.environ.get('HOME') + "/git/compute/out/lib/libhsa-runtime64.so" 102 | hsa = ctypes.CDLL(hsalibpath) 103 | 104 | # Define HSA RT API prototypes to use from python 105 | agents_callback_type = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_void_p) 106 | 107 | hsa.hsa_agent_get_info.argtypes = [ctypes.c_long, ctypes.c_int, ctypes.c_void_p] 108 | hsa.hsa_agent_get_info.restype = ctypes.c_int 109 | 110 | regions_callback_type = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_void_p) 111 | 112 | hsa.hsa_region_get_info.argtypes = [ctypes.c_long, ctypes.c_int, ctypes.c_void_p] 113 | hsa.hsa_region_get_info.restype = ctypes.c_int 114 | 115 | 116 | pools_callback_type = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_void_p) 117 | hsa.hsa_amd_memory_pool_get_info.argtypes = [ctypes.c_long, ctypes.c_int, ctypes.c_void_p] 118 | hsa.hsa_amd_memory_pool_get_info.restype = ctypes.c_int 119 | 120 | 121 | class pci_bdf(ctypes.Structure): 122 | _fields_ = [("function", ctypes.c_uint, 3), 123 | ("device", ctypes.c_uint, 5), 124 | ("bus", ctypes.c_uint, 8), 125 | ("unused", ctypes.c_uint, 16) 126 | ] 127 | 128 | 129 | class region_global_flags(ctypes.Structure): 130 | _fields_ = [("HSA_REGION_GLOBAL_FLAG_KERNARG", ctypes.c_uint, 1), 131 | ("HSA_REGION_GLOBAL_FLAG_FINE_GRAINED", ctypes.c_uint, 1), 132 | ("HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED", ctypes.c_uint, 1) 133 | ] 134 | 135 | class amd_pool_global_flags(ctypes.Structure): 136 | _fields_ = [("HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT", ctypes.c_uint, 1), 137 | ("HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED", ctypes.c_uint, 1), 138 | ("HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED", ctypes.c_uint, 1) 139 | ] 140 | 141 | 142 | # Globals to store informations 143 | hsa_agents = [] 144 | memory_regions = {} 145 | amd_pools = {} 146 | current_agent_handle = 0 147 | 148 | 149 | class region_info(object): 150 | def __init__(self, region_handle): 151 | self.region_handle = region_handle 152 | 153 | self.segment = ctypes.c_int(0xff) 154 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_SEGMENT, 155 | ctypes.pointer(self.segment)) 156 | 157 | self.size = ctypes.c_longlong(0) 158 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_SIZE, 159 | ctypes.pointer(self.size)) 160 | 161 | self.global_flags = region_global_flags() 162 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_GLOBAL_FLAGS, 163 | ctypes.pointer(self.global_flags)) 164 | 165 | self.alloc_max_size = ctypes.c_longlong(0) 166 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_ALLOC_MAX_SIZE, 167 | ctypes.pointer(self.alloc_max_size)) 168 | 169 | self.alloc_allowed = ctypes.c_long(0) 170 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_RUNTIME_ALLOC_ALLOWED, 171 | ctypes.pointer(self.alloc_allowed)) 172 | 173 | self.alloc_granule = ctypes.c_long(0) 174 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_RUNTIME_ALLOC_GRANULE, 175 | ctypes.pointer(self.alloc_granule)) 176 | 177 | self.alloc_alignment = ctypes.c_long(0) 178 | hsa.hsa_region_get_info(region_handle, HSA_REGION_INFO_RUNTIME_ALLOC_ALIGNMENT, 179 | ctypes.pointer(self.alloc_alignment)) 180 | 181 | self.host_accessible = ctypes.c_long(0) 182 | hsa.hsa_region_get_info(region_handle, HSA_AMD_REGION_INFO_HOST_ACCESSIBLE, 183 | ctypes.pointer(self.host_accessible)) 184 | 185 | self.info_base = ctypes.c_longlong(0) 186 | hsa.hsa_region_get_info(region_handle, HSA_AMD_REGION_INFO_BASE, 187 | ctypes.pointer(self.info_base)) 188 | 189 | self.info_bus_width = ctypes.c_long(0) 190 | hsa.hsa_region_get_info(region_handle, HSA_AMD_REGION_INFO_BUS_WIDTH, 191 | ctypes.pointer(self.info_bus_width)) 192 | 193 | def alloc_allowed(self): 194 | return self.alloc_allowed 195 | 196 | def is_global(self): 197 | if self.segment.value == HSA_REGION_SEGMENT_GLOBAL: 198 | return True 199 | else: 200 | return False 201 | 202 | def print_info(self): 203 | print("Region segment: %s (%d)" % 204 | (hsa_segment_name[self.segment.value], 205 | self.segment.value)) 206 | 207 | print("Size %.02f MB / %.02f GB" % 208 | (self.size.value / (1024*1024), 209 | self.size.value / (1024*1024 * 1024) 210 | )) 211 | 212 | if not args.verbose: 213 | return 214 | 215 | if self.is_global(): 216 | print("Region Global flags:") 217 | print(" HSA_REGION_GLOBAL_FLAG_KERNARG %d" % 218 | (self.global_flags.HSA_REGION_GLOBAL_FLAG_KERNARG)) 219 | 220 | print(" HSA_REGION_GLOBAL_FLAG_FINE_GRAINED %d" % 221 | (self.global_flags.HSA_REGION_GLOBAL_FLAG_FINE_GRAINED)) 222 | 223 | print(" HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED %d" % 224 | (self.global_flags.HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED)) 225 | 226 | 227 | if not self.alloc_allowed: 228 | print("Allocation is not allowed") 229 | else: 230 | print("Allocation granularity 0x%x" % 231 | self.alloc_granule.value) 232 | print("Alignment 0x%x" % 233 | self.alloc_alignment.value) 234 | print("Host accessible %d" % 235 | self.host_accessible.value) 236 | 237 | 238 | def region_callback(region_handle, ignore): 239 | reg = region_info(region_handle) 240 | if not current_agent_handle in memory_regions: 241 | memory_regions[current_agent_handle] = [] 242 | memory_regions[current_agent_handle].append(reg) 243 | return 0 244 | 245 | 246 | class pool_info(object): 247 | def __init__(self, pool_handle): 248 | self.pool_handle = pool_handle 249 | 250 | self.amd_segment = ctypes.c_int(0xff) 251 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_SEGMENT, 252 | ctypes.pointer(self.amd_segment)) 253 | 254 | self.amd_global_flags = amd_pool_global_flags() 255 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, 256 | ctypes.pointer(self.amd_global_flags)) 257 | 258 | self.pool_size = ctypes.c_long(0) 259 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_SIZE, 260 | ctypes.pointer(self.pool_size)) 261 | 262 | self.alloc_allowed = ctypes.c_long(0) 263 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED, 264 | ctypes.pointer(self.alloc_allowed)) 265 | 266 | self.alloc_granule = ctypes.c_long(0) 267 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_GRANULE, 268 | ctypes.pointer(self.alloc_granule)) 269 | 270 | self.alloc_alignment = ctypes.c_long(0) 271 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALIGNMENT, 272 | ctypes.pointer(self.alloc_alignment)) 273 | 274 | self.accessible_by_all = ctypes.c_long(0) 275 | hsa.hsa_amd_memory_pool_get_info(pool_handle, HSA_AMD_MEMORY_POOL_INFO_ACCESSIBLE_BY_ALL, 276 | ctypes.pointer(self.accessible_by_all)) 277 | 278 | def alloc_allowed(self): 279 | return self.alloc_allowed 280 | 281 | def is_global(self): 282 | if self.amd_segment.value == HSA_AMD_SEGMENT_GLOBAL: 283 | return True 284 | else: 285 | return False 286 | 287 | def print_info(self): 288 | print("AMD pool segment: %s (%d)" % 289 | (hsa_amd_segment_name[self.amd_segment.value], 290 | self.amd_segment.value)) 291 | 292 | 293 | print("Size %.02f MB / %.02f GB" % 294 | (self.pool_size.value / (1024*1024), 295 | self.pool_size.value / (1024*1024 * 1024) 296 | )) 297 | 298 | if not args.verbose: 299 | return 300 | 301 | if self.is_global(): 302 | print("Pool Global flags:") 303 | print(" HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT %d" % 304 | (self.amd_global_flags.HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_KERNARG_INIT)) 305 | 306 | print(" HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED %d" % 307 | (self.amd_global_flags.HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED)) 308 | 309 | print(" HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED %d" % 310 | (self.amd_global_flags.HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED)) 311 | 312 | if not self.alloc_allowed: 313 | print("Allocation is not allowed") 314 | else: 315 | print("Allocation granularity 0x%x" % 316 | self.alloc_granule.value) 317 | print("Alignment 0x%x" % 318 | self.alloc_alignment.value) 319 | print("Accessible by all %d" % 320 | self.accessible_by_all.value) 321 | 322 | def amd_pool_callback(pool_handle, ignore): 323 | reg = pool_info(pool_handle) 324 | if not current_agent_handle in amd_pools: 325 | amd_pools[current_agent_handle] = [] 326 | amd_pools[current_agent_handle].append(reg) 327 | return 0 328 | 329 | class agent_info(object): 330 | def __init__(self, agent_handle): 331 | self.agent_handle = agent_handle 332 | 333 | self.agent_name = ctypes.create_string_buffer(256) 334 | hsa.hsa_agent_get_info(agent_handle, HSA_AGENT_INFO_NAME, self.agent_name) 335 | 336 | self.vendor_name = ctypes.create_string_buffer(256) 337 | hsa.hsa_agent_get_info(agent_handle, HSA_AGENT_INFO_VENDOR_NAME, self.vendor_name) 338 | 339 | self.device_type = ctypes.c_int(0xff) 340 | hsa.hsa_agent_get_info(agent_handle, HSA_AGENT_INFO_DEVICE, 341 | ctypes.pointer(self.device_type)) 342 | 343 | if self.device_type.value == HSA_DEVICE_TYPE_GPU: 344 | self.pci_bdfb = pci_bdf() 345 | hsa.hsa_agent_get_info(agent_handle, HSA_AMD_AGENT_INFO_BDFID, 346 | ctypes.pointer(self.pci_bdfb)) 347 | 348 | self.chipid = ctypes.c_int(0) 349 | hsa.hsa_agent_get_info(agent_handle, HSA_AMD_AGENT_INFO_CHIP_ID, 350 | ctypes.pointer(self.chipid)) 351 | 352 | regions_callback_func = regions_callback_type(region_callback) 353 | hsa.hsa_agent_iterate_regions(agent_handle, regions_callback_func, 354 | ctypes.c_void_p(0)); 355 | 356 | amd_pools_callback_func = regions_callback_type(amd_pool_callback) 357 | hsa.hsa_amd_agent_iterate_memory_pools(agent_handle, amd_pools_callback_func, 358 | ctypes.c_void_p(0)); 359 | 360 | def is_gpu(self): 361 | if self.device_type.value == HSA_DEVICE_TYPE_GPU: 362 | return True 363 | else: 364 | return False 365 | 366 | def print_info(self): 367 | 368 | if self.is_gpu(): 369 | print("GPU Agent : '%s'" % (self.agent_name.value.decode("utf-8"))) 370 | else: 371 | print("CPU Agent : '%s'" % (self.agent_name.value.decode("utf-8"))) 372 | 373 | print(" Vendor : '%s'" % (self.vendor_name.value.decode("utf-8"))) 374 | if self.is_gpu(): 375 | print(" Device topology PCI [B#%02x D#%02x F#%02x]" % 376 | (self.pci_bdfb.bus, self.pci_bdfb.device, 377 | self.pci_bdfb.function)) 378 | 379 | if args.segments == True: 380 | print("(**) Regions") 381 | global_index = 0 382 | if self.agent_handle in memory_regions: 383 | for r in memory_regions[self.agent_handle]: 384 | if r.is_global(): 385 | print("(***) Global region index ............%d" % (global_index)) 386 | r.print_info() 387 | global_index = global_index + 1 388 | elif args.nonglobal: 389 | print("(***) Non global region ..............") 390 | r.print_info() 391 | print("(**) AMD Pools") 392 | global_index = 0 393 | if self.agent_handle in amd_pools: 394 | for p in amd_pools[self.agent_handle]: 395 | if p.is_global(): 396 | print("(***) Global pool index ............%d" % (global_index)) 397 | p.print_info() 398 | global_index = global_index + 1 399 | elif args.nonglobal: 400 | print("(***) Non global pool..............") 401 | p.print_info() 402 | 403 | 404 | 405 | 406 | def agent_callback(agent_handle, ignore): 407 | global current_agent_handle 408 | current_agent_handle = agent_handle 409 | agent = agent_info(agent_handle) 410 | hsa_agents.append(agent) 411 | return 0 412 | 413 | def check_rdma(): 414 | try: 415 | with open("/sys/module/amdp2p/initstate", 'r') as f: 416 | read_data = f.read() 417 | if read_data.find("live") != -1: 418 | return True 419 | else: 420 | return False 421 | except: 422 | return False 423 | # 424 | # Main logic 425 | # 426 | if __name__ == "__main__": 427 | import sys 428 | import argparse 429 | print("**************************************************************************") 430 | print("* Display information about HSA agents and related memory") 431 | print("* Version 1.00") 432 | print("**************************************************************************") 433 | parser = argparse.ArgumentParser() 434 | parser.add_argument('--segments', action='store_true', default = False, 435 | help = "Display information about segments (Default: pool only)") 436 | parser.add_argument('--nonglobal', action='store_true', default = False, 437 | help = "Display information about non-global memory (Default: global only)") 438 | parser.add_argument('--verbose', action='store_true', default = False, 439 | help = "Display more information") 440 | args = parser.parse_args() 441 | print("Use '%s --help' for command line options" % sys.argv[0]); 442 | print("\n") 443 | 444 | agent_callback_func = agents_callback_type(agent_callback) 445 | 446 | hsa.hsa_init() 447 | hsa.hsa_iterate_agents(agent_callback_func, ctypes.c_void_p(0)) 448 | 449 | index = 0 450 | for a in hsa_agents: 451 | print("(*) Agent index ...................................... %d" % (index)) 452 | a.print_info() 453 | print("") 454 | index = index + 1 455 | hsa.hsa_shut_down() 456 | print("(*) System information:") 457 | if check_rdma(): 458 | print("RDMA / PeerDirect support is detected") 459 | else: 460 | print("RDMA / PeerDirect is not supported") 461 | -------------------------------------------------------------------------------- /perftest.spec: -------------------------------------------------------------------------------- 1 | Name: perftest 2 | Summary: IB Performance tests 3 | Version: 3.0 4 | Release: 0.16.gb2f2e82 5 | License: BSD 3-Clause, GPL v2 or later 6 | Group: Productivity/Networking/Diagnostic 7 | Source: http://www.openfabrics.org/downloads/perftest-3.0-0.16.gb2f2e82.tar.gz 8 | Url: http://www.openfabrics.org 9 | BuildRoot: %{_tmppath}/%{name}-%{version}-build 10 | BuildRequires: libibverbs-devel librdmacm-devel libibumad-devel 11 | 12 | %description 13 | gen3 uverbs microbenchmarks 14 | 15 | %prep 16 | %setup -q 17 | 18 | %build 19 | %configure 20 | %{__make} 21 | chmod -x runme 22 | 23 | %install 24 | rm -rf $RPM_BUILD_ROOT 25 | make DESTDIR=%{buildroot} install 26 | 27 | %clean 28 | rm -rf ${RPM_BUILD_ROOT} 29 | 30 | %files 31 | %defattr(-, root, root) 32 | %doc README COPYING runme 33 | %_bindir/* 34 | 35 | %changelog 36 | * Wed Jan 09 2013 - idos@mellanox.com 37 | - Use autotools for building package. 38 | * Sun Dec 30 2012 - idos@mellanox.com 39 | - Added raw_ethernet_bw to install script. 40 | * Sat Oct 21 2012 - idos@mellanox.com 41 | - Removed write_bw_postlist (feature contained in all BW tests) 42 | * Sat Oct 20 2012 - idos@mellanox.com 43 | - Version 2.0 is underway 44 | * Sun May 14 2012 - idos@mellanox.com 45 | - Removed (deprecated) rdma_bw and rdma_lat tests 46 | * Sun Feb 02 2012 - idos@mellanox.com 47 | - Updated to 1.4.0 version (no compability with older version). 48 | * Sun Feb 02 2012 - idos@mellanox.com 49 | - Merge perftest code for Linux & Windows 50 | * Mon Jan 01 2012 - idos@mellanox.com 51 | - Added atomic benchmarks 52 | * Sat Apr 18 2009 - hal.rosenstock@gmail.com 53 | - Change executable names for rdma_lat and rdma_bw 54 | * Mon Jul 09 2007 - hvogel@suse.de 55 | - Use correct version 56 | * Wed Jul 04 2007 - hvogel@suse.de 57 | - Add GPL COPYING file [#289509] 58 | * Mon Jul 02 2007 - hvogel@suse.de 59 | - Update to the OFED 1.2 version 60 | * Fri Jun 22 2007 - hvogel@suse.de 61 | - Initial Package, Version 1.1 62 | -------------------------------------------------------------------------------- /run_perftest_loopback: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # trivial script to launch a loopback test on the same device 3 | # example: run_perftest_loopback 0 1 ib_write_bw -s 10 4 | 5 | if [ $# -lt 3 ] ; then 6 | echo "" 7 | echo "Usage: run_perftest_loopback " 8 | echo "example: run_perftest_loopback 0 1 ib_write_bw -s 10" 9 | exit 3 10 | fi 11 | 12 | server_core=$1 13 | client_core=$2 14 | shift 2 15 | 16 | taskset -c $server_core $* & 17 | #give server time to start 18 | sleep 1 19 | 20 | taskset -c $client_core $* localhost 21 | 22 | status=$? 23 | 24 | wait 25 | exit $status 26 | -------------------------------------------------------------------------------- /runme: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # trivial script to launch a server/client test with ssh 3 | # must be launched from client 4 | # example: runme 10.0.0.1 /home/perftest/rdma_lat -s 10 5 | 6 | if [ $# -lt 1 ] ; then 7 | echo "Usage: runme " 8 | exit 3 9 | fi 10 | 11 | server=$1 12 | shift 13 | ssh $server $* & 14 | #give server time to start 15 | sleep 2 16 | $* $server 17 | status=$? 18 | wait 19 | exit $status 20 | -------------------------------------------------------------------------------- /src/atomic_bw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 | * 6 | * This software is available to you under a choice of one of two 7 | * licenses. You may choose to be licensed under the terms of the GNU 8 | * General Public License (GPL) Version 2, available from the file 9 | * COPYING in the main directory of this source tree, or the 10 | * OpenIB.org BSD license below: 11 | * 12 | * Redistribution and use in source and binary forms, with or 13 | * without modification, are permitted provided that the following 14 | * conditions are met: 15 | * 16 | * - Redistributions of source code must retain the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer. 19 | * 20 | * - Redistributions in binary form must reproduce the above 21 | * copyright notice, this list of conditions and the following 22 | * disclaimer in the documentation and/or other materials 23 | * provided with the distribution. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | * SOFTWARE. 33 | * 34 | * $Id$ 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "perftest_parameters.h" 42 | #include "perftest_resources.h" 43 | #include "perftest_communication.h" 44 | 45 | /****************************************************************************** 46 | * 47 | ******************************************************************************/ 48 | int main(int argc, char *argv[]) 49 | { 50 | int ret_parser, i; 51 | struct ibv_device *ib_dev = NULL; 52 | struct pingpong_context ctx; 53 | struct pingpong_dest *my_dest = NULL; 54 | struct pingpong_dest *rem_dest = NULL; 55 | struct perftest_parameters user_param; 56 | struct perftest_comm user_comm; 57 | struct bw_report_data my_bw_rep, rem_bw_rep; 58 | 59 | /* init default values to user's parameters */ 60 | memset(&ctx, 0, sizeof(struct pingpong_context)); 61 | memset(&user_param, 0, sizeof(struct perftest_parameters)); 62 | memset(&user_comm, 0, sizeof(struct perftest_comm)); 63 | 64 | user_param.verb = ATOMIC; 65 | user_param.tst = BW; 66 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 67 | 68 | ret_parser = parser(&user_param, argv, argc); 69 | if (ret_parser) { 70 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 71 | fprintf(stderr, " Parser function exited with Error\n"); 72 | return 1; 73 | } 74 | 75 | if (user_param.use_xrc && user_param.duplex) { 76 | user_param.num_of_qps *= 2; 77 | } 78 | 79 | ib_dev = ctx_find_dev(user_param.ib_devname); 80 | if (!ib_dev) 81 | return 7; 82 | 83 | /* Getting the relevant context from the device */ 84 | ctx.context = ibv_open_device(ib_dev); 85 | if (!ctx.context) { 86 | fprintf(stderr, " Couldn't get context for the device\n"); 87 | return 1; 88 | } 89 | 90 | #ifdef HAVE_MASKED_ATOMICS 91 | if (check_masked_atomics_support(&ctx)) { 92 | user_param.masked_atomics = 1; 93 | user_param.use_exp = 1; 94 | } 95 | 96 | if (user_param.masked_atomics && (user_param.work_rdma_cm || user_param.use_rdma_cm)) { 97 | fprintf(stderr, "atomic test is not supported with -R/-z flag (rdma_cm) with this device.\n"); 98 | return 1; 99 | } 100 | #endif 101 | 102 | /* See if MTU and link type are valid and supported. */ 103 | if (check_link(ctx.context, &user_param)) { 104 | fprintf(stderr, " Couldn't get context for the device\n"); 105 | return FAILURE; 106 | } 107 | 108 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 109 | if (create_comm_struct(&user_comm, &user_param)) { 110 | fprintf(stderr, " Unable to create RDMA_CM resources\n"); 111 | return 1; 112 | } 113 | 114 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 115 | printf("\n************************************\n"); 116 | printf("* Waiting for client to connect... *\n"); 117 | printf("************************************\n"); 118 | } 119 | 120 | /* Initialize the connection and print the local data. */ 121 | if (establish_connection(&user_comm)) { 122 | fprintf(stderr, " Unable to init the socket connection\n"); 123 | return FAILURE; 124 | } 125 | 126 | exchange_versions(&user_comm, &user_param); 127 | 128 | check_sys_data(&user_comm, &user_param); 129 | 130 | /* See if MTU and link type are valid and supported. */ 131 | if (check_mtu(ctx.context, &user_param, &user_comm)) { 132 | fprintf(stderr, " Couldn't get context for the device\n"); 133 | return FAILURE; 134 | } 135 | 136 | /* Print basic test information. */ 137 | ctx_print_test_info(&user_param); 138 | 139 | ALLOCATE(my_dest, struct pingpong_dest, user_param.num_of_qps); 140 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 141 | ALLOCATE(rem_dest, struct pingpong_dest, user_param.num_of_qps); 142 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 143 | 144 | /* Allocating arrays needed for the test. */ 145 | alloc_ctx(&ctx, &user_param); 146 | 147 | /* Create (if nessacery) the rdma_cm ids and channel. */ 148 | if (user_param.work_rdma_cm == ON) { 149 | 150 | if (user_param.machine == CLIENT) { 151 | if (retry_rdma_connect(&ctx, &user_param)) { 152 | fprintf(stderr, "Unable to perform rdma_client function\n"); 153 | return FAILURE; 154 | } 155 | 156 | } else { 157 | if (create_rdma_resources(&ctx, &user_param)) { 158 | fprintf(stderr, " Unable to create the rdma_resources\n"); 159 | return FAILURE; 160 | } 161 | if (rdma_server_connect(&ctx, &user_param)) { 162 | fprintf(stderr, "Unable to perform rdma_client function\n"); 163 | return FAILURE; 164 | } 165 | } 166 | 167 | } else { 168 | 169 | /* create all the basic IB resources. */ 170 | if (ctx_init(&ctx, &user_param)) { 171 | fprintf(stderr, " Couldn't create IB resources\n"); 172 | return FAILURE; 173 | } 174 | } 175 | 176 | /* Set up the Connection. */ 177 | if (set_up_connection(&ctx, &user_param, my_dest)) { 178 | fprintf(stderr, " Unable to set up socket connection\n"); 179 | return FAILURE; 180 | } 181 | 182 | /* Print this machine QP information */ 183 | for (i = 0; i < user_param.num_of_qps; i++) 184 | ctx_print_pingpong_data(&my_dest[i], &user_comm); 185 | 186 | user_comm.rdma_params->side = REMOTE; 187 | for (i = 0; i < user_param.num_of_qps; i++) { 188 | 189 | /* shaking hands and gather the other side info. */ 190 | if (ctx_hand_shake(&user_comm, &my_dest[i], &rem_dest[i])) { 191 | fprintf(stderr, "Failed to exchange data between server and clients\n"); 192 | return 1; 193 | } 194 | ctx_print_pingpong_data(&rem_dest[i], &user_comm); 195 | } 196 | 197 | if (user_param.work_rdma_cm == OFF) { 198 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 199 | fprintf(stderr, "\n Found Incompatibility issue with GID types.\n"); 200 | fprintf(stderr, " Please Try to use a different IP version.\n\n"); 201 | return 1; 202 | } 203 | } 204 | 205 | if (user_param.work_rdma_cm == OFF) { 206 | if (ctx_connect(&ctx, rem_dest, &user_param, my_dest)) { 207 | fprintf(stderr, " Unable to Connect the HCA's through the link\n"); 208 | return 1; 209 | } 210 | } 211 | 212 | /* An additional handshake is required after moving qp to RTR. */ 213 | if (ctx_hand_shake(&user_comm, &my_dest[0], &rem_dest[0])) { 214 | fprintf(stderr, "Failed to exchange data between server and clients\n"); 215 | return 1; 216 | } 217 | 218 | /* For half duplex tests, server just waits for client to exit */ 219 | if (user_param.machine == SERVER && !user_param.duplex) { 220 | if (user_param.output == FULL_VERBOSITY) { 221 | printf(RESULT_LINE); 222 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 223 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 224 | } 225 | 226 | if (ctx_hand_shake(&user_comm, &my_dest[0], &rem_dest[0])) { 227 | fprintf(stderr, " Failed to exchange data between server and clients\n"); 228 | return FAILURE; 229 | } 230 | 231 | xchg_bw_reports(&user_comm, &my_bw_rep, &rem_bw_rep, atof(user_param.rem_version)); 232 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 233 | 234 | if (user_param.output == FULL_VERBOSITY) { 235 | printf(RESULT_LINE); 236 | } 237 | 238 | if (ctx_close_connection(&user_comm, &my_dest[0], &rem_dest[0])) { 239 | fprintf(stderr, "Failed to close connection between server and client\n"); 240 | return 1; 241 | } 242 | 243 | return destroy_ctx(&ctx, &user_param); 244 | } 245 | 246 | if (user_param.use_event) { 247 | if (ibv_req_notify_cq(ctx.send_cq, 0)) { 248 | fprintf(stderr, "Couldn't request CQ notification\n"); 249 | return 1; 250 | } 251 | } 252 | if (user_param.output == FULL_VERBOSITY) { 253 | printf(RESULT_LINE); 254 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 255 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 256 | } 257 | 258 | ctx_set_send_wqes(&ctx, &user_param, rem_dest); 259 | 260 | if (user_param.test_method == RUN_REGULAR || user_param.test_method == RUN_ALL) { 261 | 262 | if (perform_warm_up(&ctx, &user_param)) { 263 | fprintf(stderr, "Problems with warm up\n"); 264 | return 1; 265 | } 266 | 267 | if (user_param.duplex) { 268 | if (ctx_hand_shake(&user_comm, &my_dest[0], &rem_dest[0])) { 269 | fprintf(stderr, "Failed to sync between server and client between different msg sizes\n"); 270 | return 1; 271 | } 272 | } 273 | 274 | if (run_iter_bw(&ctx, &user_param)) { 275 | fprintf(stderr, " Error occured in run_iter function\n"); 276 | return 1; 277 | } 278 | 279 | print_report_bw(&user_param, &my_bw_rep); 280 | 281 | if (user_param.duplex) { 282 | xchg_bw_reports(&user_comm, &my_bw_rep, &rem_bw_rep, atof(user_param.rem_version)); 283 | print_full_bw_report(&user_param, &my_bw_rep, &rem_bw_rep); 284 | } 285 | 286 | if (user_param.report_both && user_param.duplex) { 287 | printf(RESULT_LINE); 288 | printf("\n Local results:\n"); 289 | printf(RESULT_LINE); 290 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 291 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 292 | print_full_bw_report(&user_param, &my_bw_rep, NULL); 293 | printf(RESULT_LINE); 294 | 295 | printf("\n Remote results:\n"); 296 | printf(RESULT_LINE); 297 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 298 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 299 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 300 | } 301 | } else if (user_param.test_method == RUN_INFINITELY) { 302 | 303 | if (run_iter_bw_infinitely(&ctx, &user_param)) { 304 | fprintf(stderr, " Error occured while running infinitely! aborting ...\n"); 305 | return 1; 306 | } 307 | } 308 | 309 | if (user_param.output == FULL_VERBOSITY) { 310 | printf(RESULT_LINE); 311 | } 312 | /* For half duplex tests, server just waits for client to exit */ 313 | if (user_param.machine == CLIENT && !user_param.duplex) { 314 | 315 | if (ctx_hand_shake(&user_comm, &my_dest[0], &rem_dest[0])) { 316 | fprintf(stderr, " Failed to exchange data between server and clients\n"); 317 | return FAILURE; 318 | } 319 | 320 | xchg_bw_reports(&user_comm, &my_bw_rep, &rem_bw_rep, atof(user_param.rem_version)); 321 | } 322 | 323 | if (ctx_close_connection(&user_comm, &my_dest[0], &rem_dest[0])) { 324 | fprintf(stderr, "Failed to close connection between server and client\n"); 325 | return 1; 326 | } 327 | 328 | if (!user_param.is_bw_limit_passed && (user_param.is_limit_bw == ON)) { 329 | fprintf(stderr, "Error: BW result is below bw limit\n"); 330 | return 1; 331 | } 332 | 333 | if (!user_param.is_msgrate_limit_passed && (user_param.is_limit_bw == ON)) { 334 | fprintf(stderr, "Error: Msg rate is below msg_rate limit\n"); 335 | return 1; 336 | } 337 | 338 | return destroy_ctx(&ctx, &user_param); 339 | } 340 | -------------------------------------------------------------------------------- /src/atomic_lat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2005 Hewlett Packard, Inc (Grant Grundler) 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 | * 7 | * This software is available to you under a choice of one of two 8 | * licenses. You may choose to be licensed under the terms of the GNU 9 | * General Public License (GPL) Version 2, available from the file 10 | * COPYING in the main directory of this source tree, or the 11 | * OpenIB.org BSD license below: 12 | * 13 | * Redistribution and use in source and binary forms, with or 14 | * without modification, are permitted provided that the following 15 | * conditions are met: 16 | * 17 | * - Redistributions of source code must retain the above 18 | * copyright notice, this list of conditions and the following 19 | * disclaimer. 20 | * 21 | * - Redistributions in binary form must reproduce the above 22 | * copyright notice, this list of conditions and the following 23 | * disclaimer in the documentation and/or other materials 24 | * provided with the distribution. 25 | * 26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | * SOFTWARE. 34 | * 35 | * $Id$ 36 | */ 37 | 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "get_clock.h" 46 | #include "perftest_parameters.h" 47 | #include "perftest_resources.h" 48 | #include "perftest_communication.h" 49 | 50 | /****************************************************************************** 51 | * 52 | ******************************************************************************/ 53 | int main(int argc, char *argv[]) 54 | { 55 | int ret_parser, i; 56 | struct report_options report; 57 | struct pingpong_context ctx; 58 | struct pingpong_dest *my_dest = NULL; 59 | struct pingpong_dest *rem_dest = NULL; 60 | struct ibv_device *ib_dev; 61 | struct perftest_parameters user_param; 62 | struct perftest_comm user_comm; 63 | 64 | /* init default values to user's parameters */ 65 | memset(&ctx,0,sizeof(struct pingpong_context)); 66 | memset(&user_param, 0, sizeof(struct perftest_parameters)); 67 | memset(&user_comm,0,sizeof(struct perftest_comm)); 68 | 69 | user_param.verb = ATOMIC; 70 | user_param.tst = LAT; 71 | user_param.r_flag = &report; 72 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 73 | 74 | ret_parser = parser(&user_param,argv,argc); 75 | if (ret_parser) { 76 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 77 | fprintf(stderr," Parser function exited with Error\n"); 78 | return 1; 79 | } 80 | 81 | if(user_param.use_xrc) 82 | user_param.num_of_qps *= 2; 83 | 84 | /* Finding the IB device selected (or defalut if no selected). */ 85 | ib_dev = ctx_find_dev(user_param.ib_devname); 86 | if (!ib_dev) { 87 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 88 | return FAILURE; 89 | } 90 | 91 | /* Getting the relevant context from the device */ 92 | ctx.context = ibv_open_device(ib_dev); 93 | if (!ctx.context) { 94 | fprintf(stderr, " Couldn't get context for the device\n"); 95 | return 1; 96 | } 97 | 98 | #ifdef HAVE_MASKED_ATOMICS 99 | if (check_masked_atomics_support(&ctx)) { 100 | user_param.masked_atomics = 1; 101 | user_param.use_exp = 1; 102 | } 103 | 104 | if (user_param.masked_atomics && (user_param.work_rdma_cm || user_param.use_rdma_cm)) { 105 | fprintf(stderr, "atomic test is not supported with -R/-z flag (rdma_cm) with this device.\n"); 106 | return 1; 107 | } 108 | 109 | #endif 110 | 111 | /* See if MTU and link type are valid and supported. */ 112 | if (check_link(ctx.context,&user_param)) { 113 | fprintf(stderr, " Couldn't get context for the device\n"); 114 | return FAILURE; 115 | } 116 | 117 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 118 | if (create_comm_struct(&user_comm,&user_param)) { 119 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 120 | return 1; 121 | } 122 | 123 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 124 | printf("\n************************************\n"); 125 | printf("* Waiting for client to connect... *\n"); 126 | printf("************************************\n"); 127 | } 128 | 129 | /* Initialize the connection and print the local data. */ 130 | if (establish_connection(&user_comm)) { 131 | fprintf(stderr," Unable to init the socket connection\n"); 132 | return FAILURE; 133 | } 134 | 135 | exchange_versions(&user_comm, &user_param); 136 | 137 | check_sys_data(&user_comm, &user_param); 138 | 139 | /* See if MTU and link type are valid and supported. */ 140 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 141 | fprintf(stderr, " Couldn't get context for the device\n"); 142 | return FAILURE; 143 | } 144 | 145 | /* Print basic test information. */ 146 | ctx_print_test_info(&user_param); 147 | 148 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 149 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 150 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 151 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 152 | 153 | /* Allocating arrays needed for the test. */ 154 | alloc_ctx(&ctx,&user_param); 155 | 156 | /* Create (if nessacery) the rdma_cm ids and channel. */ 157 | if (user_param.work_rdma_cm == ON) { 158 | 159 | if (user_param.machine == CLIENT) { 160 | if (retry_rdma_connect(&ctx,&user_param)) { 161 | fprintf(stderr,"Unable to perform rdma_client function\n"); 162 | return FAILURE; 163 | } 164 | 165 | } else { 166 | if (create_rdma_resources(&ctx,&user_param)) { 167 | fprintf(stderr," Unable to create the rdma_resources\n"); 168 | return FAILURE; 169 | } 170 | if (rdma_server_connect(&ctx,&user_param)) { 171 | fprintf(stderr,"Unable to perform rdma_client function\n"); 172 | return FAILURE; 173 | } 174 | } 175 | 176 | } else { 177 | 178 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 179 | if (ctx_init(&ctx,&user_param)) { 180 | fprintf(stderr, " Couldn't create IB resources\n"); 181 | return FAILURE; 182 | } 183 | } 184 | 185 | /* Set up the Connection. */ 186 | if (set_up_connection(&ctx,&user_param,my_dest)) { 187 | fprintf(stderr," Unable to set up socket connection\n"); 188 | return 1; 189 | } 190 | 191 | for (i=0; i < user_param.num_of_qps; i++) 192 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 193 | 194 | /* shaking hands and gather the other side info. */ 195 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 196 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 197 | return 1; 198 | } 199 | 200 | user_comm.rdma_params->side = REMOTE; 201 | for (i=0; i < user_param.num_of_qps; i++) { 202 | 203 | /* shaking hands and gather the other side info. */ 204 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 205 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 206 | return 1; 207 | } 208 | 209 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 210 | } 211 | 212 | if (user_param.work_rdma_cm == OFF) { 213 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 214 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 215 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 216 | return 1; 217 | } 218 | } 219 | 220 | if (user_param.work_rdma_cm == OFF) { 221 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 222 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 223 | return 1; 224 | } 225 | } 226 | 227 | /* An additional handshake is required after moving qp to RTR. */ 228 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 229 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 230 | return 1; 231 | } 232 | 233 | /* Only Client post read request. */ 234 | if (user_param.machine == SERVER) { 235 | if (ctx_close_connection(&user_comm,my_dest,rem_dest)) { 236 | fprintf(stderr,"Failed to close connection between server and client\n"); 237 | return 1; 238 | } 239 | if (user_param.output == FULL_VERBOSITY) { 240 | printf(RESULT_LINE); 241 | } 242 | return 0; 243 | } 244 | 245 | if (user_param.use_event) { 246 | if (ibv_req_notify_cq(ctx.send_cq, 0)) { 247 | fprintf(stderr, "Couldn't request CQ notification\n"); 248 | return 1; 249 | } 250 | } 251 | 252 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 253 | 254 | if (user_param.output == FULL_VERBOSITY) { 255 | printf(RESULT_LINE); 256 | printf("%s",(user_param.test_type == ITERATIONS) ? RESULT_FMT_LAT : RESULT_FMT_LAT_DUR); 257 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 258 | } 259 | if(run_iter_lat(&ctx,&user_param)) 260 | return 17; 261 | 262 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 263 | 264 | if (ctx_close_connection(&user_comm,my_dest,rem_dest)) { 265 | fprintf(stderr,"Failed to close connection between server and client\n"); 266 | return 1; 267 | } 268 | 269 | if (user_param.output == FULL_VERBOSITY) { 270 | printf(RESULT_LINE); 271 | } 272 | 273 | return 0; 274 | } 275 | -------------------------------------------------------------------------------- /src/clock_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "get_clock.h" 4 | 5 | int main() 6 | { 7 | int no_cpu_freq_fail = 0; 8 | double mhz; 9 | mhz = get_cpu_mhz(no_cpu_freq_fail); 10 | cycles_t c1, c2; 11 | 12 | if (!mhz) { 13 | printf("Unable to calibrate cycles. Exiting.\n"); 14 | return 2; 15 | } 16 | 17 | printf("Type CTRL-C to cancel.\n"); 18 | for (;;) { 19 | c1 = get_cycles(); 20 | sleep(1); 21 | c2 = get_cycles(); 22 | printf("1 sec = %g usec\n", (c2 - c1) / mhz); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/get_clock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 3 | * 4 | * This software is available to you under a choice of one of two 5 | * licenses. You may choose to be licensed under the terms of the GNU 6 | * General Public License (GPL) Version 2, available from the file 7 | * COPYING in the main directory of this source tree, or the 8 | * OpenIB.org BSD license below: 9 | * 10 | * Redistribution and use in source and binary forms, with or 11 | * without modification, are permitted provided that the following 12 | * conditions are met: 13 | * 14 | * - Redistributions of source code must retain the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer. 17 | * 18 | * - Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | * 32 | * $Id$ 33 | * 34 | * Author: Michael S. Tsirkin 35 | */ 36 | 37 | /* #define DEBUG 1 */ 38 | /* #define DEBUG_DATA 1 */ 39 | /* #define GET_CPU_MHZ_FROM_PROC 1 */ 40 | 41 | /* For gettimeofday */ 42 | #define _BSD_SOURCE 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include "get_clock.h" 49 | 50 | #ifndef DEBUG 51 | #define DEBUG 0 52 | #endif 53 | #ifndef DEBUG_DATA 54 | #define DEBUG_DATA 0 55 | #endif 56 | 57 | #define MEASUREMENTS 200 58 | #define USECSTEP 10 59 | #define USECSTART 100 60 | 61 | /* 62 | Use linear regression to calculate cycles per microsecond. 63 | http://en.wikipedia.org/wiki/Linear_regression#Parameter_estimation 64 | */ 65 | static double sample_get_cpu_mhz(void) 66 | { 67 | struct timeval tv1, tv2; 68 | cycles_t start; 69 | double sx = 0, sy = 0, sxx = 0, syy = 0, sxy = 0; 70 | double tx, ty; 71 | int i; 72 | 73 | /* Regression: y = a + b x */ 74 | long x[MEASUREMENTS]; 75 | cycles_t y[MEASUREMENTS]; 76 | double a; /* system call overhead in cycles */ 77 | double b; /* cycles per microsecond */ 78 | double r_2; 79 | 80 | for (i = 0; i < MEASUREMENTS; ++i) { 81 | start = get_cycles(); 82 | 83 | if (gettimeofday(&tv1, NULL)) { 84 | fprintf(stderr, "gettimeofday failed.\n"); 85 | return 0; 86 | } 87 | 88 | do { 89 | if (gettimeofday(&tv2, NULL)) { 90 | fprintf(stderr, "gettimeofday failed.\n"); 91 | return 0; 92 | } 93 | } while ((tv2.tv_sec - tv1.tv_sec) * 1000000 + 94 | (tv2.tv_usec - tv1.tv_usec) < USECSTART + i * USECSTEP); 95 | 96 | x[i] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + 97 | tv2.tv_usec - tv1.tv_usec; 98 | y[i] = get_cycles() - start; 99 | if (DEBUG_DATA) 100 | fprintf(stderr, "x=%ld y=%Ld\n", x[i], (long long)y[i]); 101 | } 102 | 103 | for (i = 0; i < MEASUREMENTS; ++i) { 104 | tx = x[i]; 105 | ty = y[i]; 106 | sx += tx; 107 | sy += ty; 108 | sxx += tx * tx; 109 | syy += ty * ty; 110 | sxy += tx * ty; 111 | } 112 | 113 | b = (MEASUREMENTS * sxy - sx * sy) / (MEASUREMENTS * sxx - sx * sx); 114 | a = (sy - b * sx) / MEASUREMENTS; 115 | 116 | if (DEBUG) 117 | fprintf(stderr, "a = %g\n", a); 118 | if (DEBUG) 119 | fprintf(stderr, "b = %g\n", b); 120 | if (DEBUG) 121 | fprintf(stderr, "a / b = %g\n", a / b); 122 | r_2 = (MEASUREMENTS * sxy - sx * sy) * (MEASUREMENTS * sxy - sx * sy) / 123 | (MEASUREMENTS * sxx - sx * sx) / 124 | (MEASUREMENTS * syy - sy * sy); 125 | 126 | if (DEBUG) 127 | fprintf(stderr, "r^2 = %g\n", r_2); 128 | if (r_2 < 0.9) { 129 | fprintf(stderr,"Correlation coefficient r^2: %g < 0.9\n", r_2); 130 | return 0; 131 | } 132 | 133 | return b; 134 | } 135 | 136 | #ifndef __s390x__ 137 | static double proc_get_cpu_mhz(int no_cpu_freq_warn) 138 | { 139 | FILE* f; 140 | char buf[256]; 141 | double mhz = 0.0; 142 | int print_flag = 0; 143 | double delta; 144 | 145 | f = fopen("/proc/cpuinfo","r"); 146 | if (!f) 147 | return 0.0; 148 | while(fgets(buf, sizeof(buf), f)) { 149 | double m; 150 | int rc; 151 | 152 | #if defined (__ia64__) 153 | /* Use the ITC frequency on IA64 */ 154 | rc = sscanf(buf, "itc MHz : %lf", &m); 155 | #elif defined (__PPC__) || defined (__PPC64__) 156 | /* PPC has a different format as well */ 157 | rc = sscanf(buf, "clock : %lf", &m); 158 | #elif defined (__sparc__) && defined (__arch64__) 159 | /* 160 | * on sparc the /proc/cpuinfo lines that hold 161 | * the cpu freq in HZ are as follow: 162 | * Cpu{cpu-num}ClkTck : 00000000a9beeee4 163 | */ 164 | char *s; 165 | unsigned val; 166 | 167 | s = strstr(buf, "ClkTck\t: "); 168 | if (!s) 169 | continue; 170 | s += (strlen("ClkTck\t: ") - strlen("0x")); 171 | strncpy(s, "0x", strlen("0x")); 172 | rc = sscanf(s, "%x", &val); 173 | m = val/1000000; 174 | #else 175 | rc = sscanf(buf, "cpu MHz : %lf", &m); 176 | #endif 177 | 178 | if (rc != 1) 179 | continue; 180 | 181 | if (mhz == 0.0) { 182 | mhz = m; 183 | continue; 184 | } 185 | delta = mhz > m ? mhz - m : m - mhz; 186 | if ((delta / mhz > 0.02) && (print_flag ==0)) { 187 | print_flag = 1; 188 | if (!no_cpu_freq_warn) { 189 | fprintf(stderr, "Conflicting CPU frequency values" 190 | " detected: %lf != %lf. CPU Frequency is not max.\n", mhz, m); 191 | } 192 | continue; 193 | } 194 | } 195 | 196 | fclose(f); 197 | return mhz; 198 | } 199 | #endif 200 | 201 | double get_cpu_mhz(int no_cpu_freq_warn) 202 | { 203 | #ifdef __s390x__ 204 | return sample_get_cpu_mgz(); 205 | #else 206 | double sample, proc, delta; 207 | sample = sample_get_cpu_mhz(); 208 | proc = proc_get_cpu_mhz(no_cpu_freq_warn); 209 | #ifdef __aarch64__ 210 | if (proc < 1) 211 | proc = sample; 212 | #endif 213 | if (!proc || !sample) 214 | return 0; 215 | 216 | delta = proc > sample ? proc - sample : sample - proc; 217 | if (delta / proc > 0.02) { 218 | return sample; 219 | } 220 | return proc; 221 | #endif 222 | } 223 | -------------------------------------------------------------------------------- /src/get_clock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 3 | * 4 | * This software is available to you under a choice of one of two 5 | * licenses. You may choose to be licensed under the terms of the GNU 6 | * General Public License (GPL) Version 2, available from the file 7 | * COPYING in the main directory of this source tree, or the 8 | * OpenIB.org BSD license below: 9 | * 10 | * Redistribution and use in source and binary forms, with or 11 | * without modification, are permitted provided that the following 12 | * conditions are met: 13 | * 14 | * - Redistributions of source code must retain the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer. 17 | * 18 | * - Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | * 32 | * $Id$ 33 | * 34 | * Author: Michael S. Tsirkin 35 | */ 36 | 37 | #ifndef GET_CLOCK_H 38 | #define GET_CLOCK_H 39 | 40 | #if defined (__x86_64__) || defined(__i386__) 41 | /* Note: only x86 CPUs which have rdtsc instruction are supported. */ 42 | typedef unsigned long long cycles_t; 43 | static inline cycles_t get_cycles() 44 | { 45 | unsigned low, high; 46 | unsigned long long val; 47 | asm volatile ("rdtsc" : "=a" (low), "=d" (high)); 48 | val = high; 49 | val = (val << 32) | low; 50 | return val; 51 | } 52 | #elif defined(__PPC__) || defined(__PPC64__) 53 | /* Note: only PPC CPUs which have mftb instruction are supported. */ 54 | /* PPC64 has mftb */ 55 | typedef unsigned long cycles_t; 56 | static inline cycles_t get_cycles() 57 | { 58 | cycles_t ret; 59 | 60 | asm volatile ("mftb %0" : "=r" (ret) : ); 61 | return ret; 62 | } 63 | #elif defined(__ia64__) 64 | /* Itanium2 and up has ar.itc (Itanium1 has errata) */ 65 | typedef unsigned long cycles_t; 66 | static inline cycles_t get_cycles() 67 | { 68 | cycles_t ret; 69 | 70 | asm volatile ("mov %0=ar.itc" : "=r" (ret)); 71 | return ret; 72 | } 73 | #elif defined(__s390x__) 74 | typedef unsigned long long cycles_t; 75 | static inline cycles_t get_cycles(void) 76 | { 77 | cycles_t clk; 78 | asm volatile("stck %0" : "=Q" (clk) : : "cc"); 79 | return clk >> 2; 80 | } 81 | #elif defined(__sparc__) && defined(__arch64__) 82 | typedef unsigned long long cycles_t; 83 | static inline cycles_t get_cycles(void) 84 | { 85 | cycles_t v; 86 | asm volatile ("rd %%tick, %0" : "=r" (v) : ); 87 | return v; 88 | } 89 | #elif defined(__aarch64__) 90 | 91 | typedef unsigned long cycles_t; 92 | static inline cycles_t get_cycles() 93 | { 94 | cycles_t cval; 95 | asm volatile("isb" : : : "memory"); 96 | asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); 97 | return cval; 98 | } 99 | 100 | #else 101 | #warning get_cycles not implemented for this architecture: attempt asm/timex.h 102 | #include 103 | #endif 104 | 105 | extern double get_cpu_mhz(int); 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/multicast_resources.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "multicast_resources.h" 19 | 20 | /* This is when we get sig handler from the user before we remove the join request. */ 21 | struct mcast_parameters *sighandler_params; 22 | 23 | /****************************************************************************** 24 | * signalCatcher - cacth user signal in order to reregiser the mcast group 25 | ******************************************************************************/ 26 | static void signalCatcher (int sig) 27 | { 28 | if (sig == SIGINT) { 29 | 30 | if (join_multicast_group(SUBN_ADM_METHOD_DELETE,sighandler_params)) 31 | fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); 32 | 33 | if (sighandler_params->is_2nd_mgid_used) { 34 | memcpy(sighandler_params->mgid.raw,sighandler_params->base_mgid.raw,16); 35 | if (join_multicast_group(SUBN_ADM_METHOD_DELETE,sighandler_params)) 36 | fprintf(stderr,"Couldn't Unregister the Base Mcast group on the SM\n"); 37 | } 38 | } 39 | exit(1); 40 | } 41 | 42 | /****************************************************************************** 43 | * prepare_mcast_mad 44 | ******************************************************************************/ 45 | static void prepare_mcast_mad(uint8_t method, 46 | struct mcast_parameters *params, 47 | struct sa_mad_packet_t *samad_packet) 48 | { 49 | uint8_t *ptr; 50 | uint64_t comp_mask; 51 | 52 | memset(samad_packet,0,sizeof(*samad_packet)); 53 | 54 | /* prepare the MAD header. according to Table 145 in IB spec 1.2.1 */ 55 | ptr = samad_packet->mad_header_buf; 56 | ptr[0] = 0x01; /* BaseVersion */ 57 | ptr[1] = MANAGMENT_CLASS_SUBN_ADM; /* MgmtClass */ 58 | ptr[2] = 0x02; /* ClassVersion */ 59 | ptr[3] = INSERTF(ptr[3], 0, method, 0, 7); /* Method */ 60 | (*(uint64_t *)(ptr + 8)) = htonll((uint64_t)DEF_TRANS_ID); /* TransactionID */ 61 | (*(uint16_t *)(ptr + 16)) = htons(SUBN_ADM_ATTR_MC_MEMBER_RECORD); /* AttributeID */ 62 | 63 | ptr = samad_packet->SubnetAdminData; 64 | 65 | memcpy(&ptr[0],params->mgid.raw, 16); 66 | memcpy(&ptr[16],params->port_gid.raw, 16); 67 | 68 | (*(uint32_t *)(ptr + 32)) = htonl(DEF_QKEY); 69 | (*(uint16_t *)(ptr + 40)) = htons(params->pkey); 70 | ptr[39] = DEF_TCLASS; 71 | ptr[44] = INSERTF(ptr[44], 4, DEF_SLL, 0, 4); 72 | ptr[44] = INSERTF(ptr[44], 0, DEF_FLOW_LABLE, 16, 4); 73 | ptr[45] = INSERTF(ptr[45], 0, DEF_FLOW_LABLE, 8, 8); 74 | ptr[46] = INSERTF(ptr[46], 0, DEF_FLOW_LABLE, 0, 8); 75 | ptr[48] = INSERTF(ptr[48], 0, MCMEMBER_JOINSTATE_FULL_MEMBER, 0, 4); 76 | 77 | comp_mask = SUBN_ADM_COMPMASK_MGID | SUBN_ADM_COMPMASK_PORT_GID | SUBN_ADM_COMPMASK_Q_KEY | 78 | SUBN_ADM_COMPMASK_P_KEY | SUBN_ADM_COMPMASK_TCLASS | SUBN_ADM_COMPMASK_SL | 79 | SUBN_ADM_COMPMASK_FLOW_LABEL | SUBN_ADM_COMPMASK_JOIN_STATE; 80 | 81 | samad_packet->ComponentMask = htonll(comp_mask); 82 | } 83 | 84 | /****************************************************************************** 85 | * check_mad_status 86 | ******************************************************************************/ 87 | static int check_mad_status(struct sa_mad_packet_t *samad_packet) 88 | { 89 | uint8_t *ptr; 90 | uint32_t user_trans_id; 91 | uint16_t mad_header_status; 92 | 93 | ptr = samad_packet->mad_header_buf; 94 | 95 | /* the upper 32 bits of TransactionID were set by the kernel */ 96 | user_trans_id = ntohl(*(uint32_t *)(ptr + 12)); 97 | 98 | /* check the TransactionID to make sure this is the response */ 99 | /* for the join/leave multicast group request we posted */ 100 | if (user_trans_id != DEF_TRANS_ID) { 101 | fprintf(stderr, "received a mad with TransactionID 0x%x, when expecting 0x%x\n", 102 | (unsigned int)user_trans_id, (unsigned int)DEF_TRANS_ID);; 103 | return 1; 104 | } 105 | 106 | mad_header_status = 0x0; 107 | mad_header_status = INSERTF(mad_header_status, 8, ptr[4], 0, 7); 108 | mad_header_status = INSERTF(mad_header_status, 0, ptr[5], 0, 8); 109 | 110 | if (mad_header_status) { 111 | fprintf(stderr,"received UMAD with an error: 0x%x\n", mad_header_status); 112 | return 1; 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | 119 | /****************************************************************************** 120 | * get_mlid_from_mad 121 | ******************************************************************************/ 122 | static void get_mlid_from_mad(struct sa_mad_packet_t *samad_packet,uint16_t *mlid) 123 | { 124 | uint8_t *ptr; 125 | ptr = samad_packet->SubnetAdminData; 126 | *mlid = ntohs(*(uint16_t *)(ptr + 36)); 127 | } 128 | 129 | /****************************************************************************** 130 | * set_multicast_gid 131 | ******************************************************************************/ 132 | void set_multicast_gid(struct mcast_parameters *params,uint32_t qp_num,int is_client) 133 | { 134 | uint8_t mcg_gid[16] = MCG_GID; 135 | const char *pstr = params->user_mgid; 136 | char *term = NULL; 137 | char tmp[20]; 138 | int i; 139 | 140 | if (params->user_mgid) { 141 | term = strpbrk(pstr, ":"); 142 | memcpy(tmp, pstr, term - pstr+1); 143 | tmp[term - pstr] = 0; 144 | 145 | mcg_gid[0] = (unsigned char)strtoll(tmp, NULL, 0); 146 | 147 | for (i = 1; i < 15; ++i) { 148 | pstr += term - pstr + 1; 149 | term = strpbrk(pstr, ":"); 150 | memcpy(tmp, pstr, term - pstr+1); 151 | tmp[term - pstr] = 0; 152 | 153 | mcg_gid[i] = (unsigned char)strtoll(tmp, NULL, 0); 154 | } 155 | pstr += term - pstr + 1; 156 | 157 | strcpy(tmp, pstr); 158 | mcg_gid[15] = (unsigned char)strtoll(tmp, NULL, 0); 159 | } 160 | 161 | memcpy(params->mgid.raw,mcg_gid,16); 162 | if (is_client && params->user_mgid==NULL) 163 | params->mgid.raw[15]++; 164 | } 165 | 166 | /****************************************************************************** 167 | * join_multicast_group 168 | ******************************************************************************/ 169 | int join_multicast_group(subn_adm_method method,struct mcast_parameters *params) 170 | { 171 | int portid = -1; 172 | int agentid = -1; 173 | void *umad_buff = NULL; 174 | void *mad = NULL; 175 | int length = MAD_SIZE; 176 | int test_result = 0; 177 | 178 | /* mlid will be assigned to the new LID after the join */ 179 | if (umad_init() < 0) { 180 | fprintf(stderr, "failed to init the UMAD library\n"); 181 | goto cleanup; 182 | } 183 | /* use casting to loose the "const char0 *" */ 184 | portid = umad_open_port((char*)params->ib_devname,params->ib_port); 185 | if (portid < 0) { 186 | fprintf(stderr,"failed to open UMAD port %d\n",params->ib_port); 187 | goto cleanup; 188 | } 189 | 190 | agentid = umad_register(portid,MANAGMENT_CLASS_SUBN_ADM, 2, 0, 0); 191 | if (agentid < 0) { 192 | fprintf(stderr,"failed to register UMAD agent for MADs\n"); 193 | goto cleanup; 194 | } 195 | 196 | umad_buff = umad_alloc(1, umad_size() + MAD_SIZE); 197 | if (!umad_buff) { 198 | fprintf(stderr, "failed to allocate MAD buffer\n"); 199 | goto cleanup; 200 | } 201 | 202 | mad = umad_get_mad(umad_buff); 203 | prepare_mcast_mad(method,params,(struct sa_mad_packet_t *)mad); 204 | 205 | if (umad_set_addr(umad_buff,params->sm_lid,1,params->sm_sl,QP1_WELL_KNOWN_Q_KEY) < 0) { 206 | fprintf(stderr, "failed to set the destination address of the SMP\n"); 207 | goto cleanup; 208 | } 209 | 210 | if (umad_send(portid,agentid,umad_buff,MAD_SIZE,100,5) < 0) { 211 | fprintf(stderr, "failed to send MAD\n"); 212 | goto cleanup; 213 | } 214 | 215 | if (umad_recv(portid,umad_buff,&length,5000) < 0) { 216 | fprintf(stderr, "failed to receive MAD response\n"); 217 | goto cleanup; 218 | } 219 | 220 | if (check_mad_status((struct sa_mad_packet_t*)mad)) { 221 | fprintf(stderr, "failed to get mlid from MAD\n"); 222 | goto cleanup; 223 | } 224 | 225 | /* "Join multicast group" message was sent */ 226 | if (method == SUBN_ADM_METHOD_SET) { 227 | get_mlid_from_mad((struct sa_mad_packet_t*)mad,¶ms->mlid); 228 | params->mcast_state |= MCAST_IS_JOINED; 229 | if (params->is_2nd_mgid_used == 0) { 230 | sighandler_params = params; 231 | signal(SIGINT,signalCatcher); 232 | } 233 | } else { 234 | params->mcast_state &= ~MCAST_IS_JOINED; 235 | } 236 | 237 | cleanup: 238 | if (umad_buff) 239 | umad_free(umad_buff); 240 | 241 | if (portid >= 0) { 242 | if (agentid >= 0) { 243 | if (umad_unregister(portid, agentid)) { 244 | fprintf(stderr, "failed to deregister UMAD agent for MADs\n"); 245 | test_result = 1; 246 | } 247 | } 248 | 249 | if (umad_close_port(portid)) { 250 | fprintf(stderr, "failed to close UMAD portid\n"); 251 | test_result = 1; 252 | } 253 | } 254 | 255 | return test_result; 256 | } 257 | 258 | /****************************************************************************** 259 | * End 260 | ******************************************************************************/ 261 | -------------------------------------------------------------------------------- /src/multicast_resources.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Mellanox Technologies Ltd. All rights reserved. 3 | * 4 | * This software is available to you under a choice of one of two 5 | * licenses. You may choose to be licensed under the terms of the GNU 6 | * General Public License (GPL) Version 2, available from the file 7 | * COPYING in the main directory of this source tree, or the 8 | * OpenIB.org BSD license below: 9 | * 10 | * Redistribution and use in source and binary forms, with or 11 | * without modification, are permitted provided that the following 12 | * conditions are met: 13 | * 14 | * - Redistributions of source code must retain the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer. 17 | * 18 | * - Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | * 32 | * Author: Ido Shamay 33 | */ 34 | 35 | #ifndef MULTICAST_RESOURCES_H 36 | #define MULTICAST_RESOURCES_H 37 | 38 | /* Multicast Module for perftest. 39 | * 40 | * Description : 41 | * 42 | * This file contains the structures and methods for implementing a multiple 43 | * multicast groups in user space enviroment. 44 | * The module is in use in "send_bw" and "send_lat" ,but can be used on other 45 | * applications and can generate more methods and serve more benchmarks. 46 | * The Module uses only the structire defined here , enabling generic use of it. 47 | * 48 | * Defined Types : 49 | * 50 | * mcast_parameters - Contains all the parameters needed for this module. 51 | * mcast_group - The multicast group entitiy itself. 52 | * mcg_qp - Is a QP structure that is attahced to the group. 53 | * 54 | */ 55 | 56 | 57 | /************************************************************************ 58 | * Macros , Defines and Files included for work. * 59 | ************************************************************************/ 60 | 61 | #include 62 | #include 63 | #include "get_clock.h" 64 | 65 | #define QPNUM_MCAST 0xffffff 66 | #define DEF_QKEY 0x11111111 67 | #define DEF_PKEY_IDX 0 68 | #define DEF_SLL 0 69 | #define MAX_POLL_ITERATION_TIMEOUT 1000000 70 | #define MCG_GID {255,1,0,0,0,2,201,133,0,0,0,0,0,0,0,0} 71 | 72 | /* Definitions section for MADs */ 73 | #define SUBN_ADM_ATTR_MC_MEMBER_RECORD 0x38 74 | #define MANAGMENT_CLASS_SUBN_ADM 0x03 /* Subnet Administration class */ 75 | #define MCMEMBER_JOINSTATE_FULL_MEMBER 0x1 76 | #define MAD_SIZE 256 /* The size of a MAD is 256 bytes */ 77 | #define QP1_WELL_KNOWN_Q_KEY 0x80010000 /* Q_Key value of QP1 */ 78 | #define DEF_TRANS_ID 0x12345678 /* TransactionID */ 79 | #define DEF_TCLASS 0 80 | #define DEF_FLOW_LABLE 0 81 | 82 | /* Macro for 64 bit variables to switch to from net */ 83 | #ifndef ntohll 84 | #define ntohll(x) (((uint64_t)(ntohl((int)((x << 32) >> 32))) << 32) | (unsigned int)ntohl(((int)(x >> 32)))) 85 | #endif 86 | #ifndef htonll 87 | #define htonll(x) ntohll(x) 88 | #endif 89 | 90 | /* generate a bit mask S bits width */ 91 | #define MASK32(S) ( ((uint32_t) ~0L) >> (32-(S)) ) 92 | 93 | /* generate a bit mask with bits O+S..O set (assumes 32 bit integer). */ 94 | #define BITS32(O,S) ( MASK32(S) << (O) ) 95 | 96 | /* extract S bits from (u_int32_t)W with offset O and shifts them O places to the right */ 97 | #define EXTRACT32(W,O,S) ( ((W)>>(O)) & MASK32(S) ) 98 | 99 | /* insert S bits with offset O from field F into word W (u_int32_t) */ 100 | #define INSERT32(W,F,O,S) (/*(W)=*/ ( ((W) & (~BITS32(O,S)) ) | (((F) & MASK32(S))<<(O)) )) 101 | 102 | #ifndef INSERTF 103 | #define INSERTF(W,O1,F,O2,S) (INSERT32(W, EXTRACT32(F, O2, S), O1, S) ) 104 | #endif 105 | 106 | 107 | /* according to Table 187 in the IB spec 1.2.1 */ 108 | typedef enum { 109 | SUBN_ADM_METHOD_SET = 0x2, 110 | SUBN_ADM_METHOD_DELETE = 0x15 111 | } subn_adm_method; 112 | 113 | /* Utilities for Umad Usage. */ 114 | typedef enum { 115 | SUBN_ADM_COMPMASK_MGID = (1ULL << 0), 116 | SUBN_ADM_COMPMASK_PORT_GID = (1ULL << 1), 117 | SUBN_ADM_COMPMASK_Q_KEY = (1ULL << 2), 118 | SUBN_ADM_COMPMASK_P_KEY = (1ULL << 7), 119 | SUBN_ADM_COMPMASK_TCLASS = (1ULL << 6), 120 | SUBN_ADM_COMPMASK_SL = (1ULL << 12), 121 | SUBN_ADM_COMPMASK_FLOW_LABEL = (1ULL << 13), 122 | SUBN_ADM_COMPMASK_JOIN_STATE = (1ULL << 16), 123 | } subn_adm_component_mask; 124 | 125 | typedef enum { 126 | MCAST_IS_JOINED = 1, 127 | MCAST_IS_ATTACHED = (1 << 1) 128 | } mcast_state; 129 | 130 | 131 | /************************************************************************ 132 | * Multicast data structures. * 133 | ************************************************************************/ 134 | 135 | /* Needed parameters for creating a multiple multicast group entity. */ 136 | struct mcast_parameters { 137 | int num_qps_on_group; 138 | int is_user_mgid; 139 | int mcast_state; 140 | int ib_port; 141 | uint16_t mlid; 142 | uint16_t base_mlid; 143 | const char *user_mgid; 144 | char *ib_devname; 145 | uint16_t pkey; 146 | uint16_t sm_lid; 147 | uint8_t sm_sl; 148 | union ibv_gid port_gid; 149 | union ibv_gid mgid; 150 | /* In case it's a latency test. */ 151 | union ibv_gid base_mgid; 152 | int is_2nd_mgid_used; 153 | }; 154 | 155 | /* according to Table 195 in the IB spec 1.2.1 */ 156 | 157 | struct sa_mad_packet_t { 158 | u_int8_t mad_header_buf[24]; 159 | u_int8_t rmpp_header_buf[12]; 160 | u_int64_t SM_Key; 161 | u_int16_t AttributeOffset; 162 | u_int16_t Reserved1; 163 | u_int64_t ComponentMask; 164 | u_int8_t SubnetAdminData[200]; 165 | }__attribute__((packed)); 166 | 167 | /************************************************************************ 168 | * Multicast resources methods. * 169 | ************************************************************************/ 170 | 171 | /* set_multicast_gid . 172 | * 173 | * Description : 174 | * 175 | * Sets the Multicast GID , and stores it in the "mgid" value of 176 | * mcast resourcs. If the user requested for a specific MGID, which 177 | * is stored in params->user_mgid (in this case params->is_user_mgid should be 1) 178 | * than it will be his MGID, if not the library choose a default one. 179 | * 180 | * Parameters : 181 | * 182 | * params - The parameters of the machine 183 | * my_dest ,rem_dest - The 2 sides that ends the connection. 184 | * 185 | * Return Value : 0 upon success. -1 if it fails. 186 | */ 187 | void set_multicast_gid(struct mcast_parameters *params,uint32_t qp_num,int is_client); 188 | 189 | 190 | /* ctx_close_connection . 191 | * 192 | * Description : 193 | * 194 | * Close the connection between the 2 machines. 195 | * It performs an handshake to ensure the 2 sides are there. 196 | * 197 | * Parameters : 198 | * 199 | * params - The parameters of the machine 200 | * my_dest ,rem_dest - The 2 sides that ends the connection. 201 | * 202 | * Return Value : 0 upon success. -1 if it fails. 203 | */ 204 | int join_multicast_group(subn_adm_method method,struct mcast_parameters *params); 205 | 206 | 207 | #endif /* MULTICAST_RESOURCES_H */ 208 | -------------------------------------------------------------------------------- /src/perftest_communication.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Mellanox Technologies Ltd. All rights reserved. 3 | * 4 | * This software is available to you under a choice of one of two 5 | * licenses. You may choose to be licensed under the terms of the GNU 6 | * General Public License (GPL) Version 2, available from the file 7 | * COPYING in the main directory of this source tree, or the 8 | * OpenIB.org BSD license below: 9 | * 10 | * Redistribution and use in source and binary forms, with or 11 | * without modification, are permitted provided that the following 12 | * conditions are met: 13 | * 14 | * - Redistributions of source code must retain the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer. 17 | * 18 | * - Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | * 32 | * Author: Ido Shamay 33 | * 34 | * Description : ... 35 | * 36 | * Methods : ... 37 | */ 38 | 39 | #ifndef PERFTEST_COMMUNICATION_H 40 | #define PERFTEST_COMMUNICATION_H 41 | 42 | #include 43 | #include 44 | #include 45 | #include "perftest_resources.h" 46 | 47 | /* Macro for 64 bit variables to switch to/from net */ 48 | #if __BYTE_ORDER == __BIG_ENDIAN || __BYTE_ORDER == __LITTLE_ENDIAN 49 | #if __BYTE_ORDER == __BIG_ENDIAN 50 | #define ntoh_64(x) (x) 51 | #define hton_64(x) (x) 52 | #define ntoh_double(x) (x) 53 | #define hton_double(x) (x) 54 | #else 55 | #define ntoh_64(x) bswap_64(x) 56 | #define hton_64(x) bswap_64(x) 57 | #define ntoh_double(x) bswap_double(x) 58 | #define hton_double(x) bswap_double(x) 59 | #endif 60 | #else 61 | #error "Only BIG_ENDIAN and LITTLE_ENDIAN are supported." 62 | #endif 63 | 64 | /* long is 64-bit in LP64 mode, 32-bit in LLP64 mode. */ 65 | #if defined(_LP64) || defined(__LP64__) 66 | #define ntoh_long(x) ntoh_64(x) 67 | #define hton_long(x) hton_64(x) 68 | #else 69 | #define ntoh_long(x) ntohl(x) 70 | #define hton_long(x) htonl(x) 71 | #endif 72 | 73 | /* int is 32-bit in both LP64 and LLP64 modes. */ 74 | #define ntoh_int(x) (int) ntohl((uint32_t) (x)) 75 | #define hton_int(x) (int) htonl((uint32_t) (x)) 76 | 77 | #define KEY_MSG_SIZE (59) /* Message size without gid. */ 78 | #define KEY_MSG_SIZE_GID (108) /* Message size with gid (MGID as well). */ 79 | #define SYNC_SPEC_ID (5) 80 | 81 | /* The Format of the message we pass through sockets , without passing Gid. */ 82 | #define KEY_PRINT_FMT "%04x:%04x:%06x:%06x:%08x:%016Lx:%08x" 83 | 84 | /* The Format of the message we pass through sockets (With Gid). */ 85 | #define KEY_PRINT_FMT_GID "%04x:%04x:%06x:%06x:%08x:%016Lx:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%08x:" 86 | 87 | /* The Basic print format for all verbs. */ 88 | #define BASIC_ADDR_FMT " %s address: LID %#04x QPN %#06x PSN %#06x" 89 | 90 | /* Addition format string for READ - the outstanding reads. */ 91 | #define READ_FMT " OUT %#04x" 92 | 93 | /* The print format of the pingpong_dest element for RDMA verbs. */ 94 | #define RDMA_FMT " RKey %#08x VAddr %#016Lx" 95 | 96 | /* The print number of SRQ in case of XRC */ 97 | #define XRC_FMT " SRQn %#08x" 98 | #define DC_FMT " SRQn %#08x" 99 | 100 | /* The print format of a global address or a multicast address. */ 101 | #define PERF_GID_FMT " %s: %02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d:%02d\n" 102 | 103 | /* The print format of a global address or a multicast address. */ 104 | #define PERF_RAW_MGID_FMT " %s: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n" 105 | 106 | struct perftest_comm { 107 | struct pingpong_context *rdma_ctx; 108 | struct perftest_parameters *rdma_params; 109 | }; 110 | 111 | /* bswap_double 112 | * 113 | * Description : swap byte order for double. 114 | * 115 | * Parameters : 116 | * x - input double variable 117 | * 118 | * Return Value : double after byte order being swapped. 119 | */ 120 | double bswap_double(double x); 121 | 122 | 123 | /* create_comm_struct 124 | * 125 | * Description : Creating the communication struct for Etherent or rdma_cm options. 126 | * 127 | * Parameters : 128 | * comm - An empty Communication struct. 129 | * user_param - Perftest parameters. 130 | * 131 | * Return Value : SUCCESS,FAILURE. 132 | */ 133 | int create_comm_struct (struct perftest_comm *comm, 134 | struct perftest_parameters *user_param); 135 | 136 | 137 | /* set_up_connection . 138 | * 139 | * Description : Fills the my_dest with all of the machine proporties. 140 | * 141 | * 142 | * Parameters : 143 | * ctx - Pingoong context after the ctx_init function. 144 | * user_param - Perftest parameters. 145 | * my_dest - An empty pingpong_dest struct. 146 | * 147 | * Return Value : SUCCESS,FAILURE. 148 | */ 149 | int set_up_connection(struct pingpong_context *ctx, 150 | struct perftest_parameters *user_param, 151 | struct pingpong_dest *my_dest); 152 | 153 | /* establish_connection . 154 | * 155 | * Description : 156 | * 157 | * Connect the client the a well known server to a requested port. 158 | * It assumes the Server is waiting for request on the port. 159 | * It uses Ethernet sockets or rdma_cm as mentioned in use_rdma_cm. 160 | * 161 | * Parameters : 162 | * comm - The communication struct with all the data. 163 | * 164 | * Return Value : SUCCESS,FAILURE. 165 | */ 166 | int establish_connection(struct perftest_comm *comm); 167 | 168 | /* rdma_client_connect . 169 | * 170 | * Description : Connects the client to a QP on the other machine with rdma_cm. 171 | * 172 | * Parameters : 173 | * ctx - An empty resources struct to fill the resources created for this QP. 174 | * user_param - Perftest parameters. 175 | * 176 | * Return Value : SUCCESS,FAILURE. 177 | */ 178 | int rdma_client_connect(struct pingpong_context *ctx, 179 | struct perftest_parameters *user_param); 180 | 181 | /* retry_rdma_connect . 182 | * 183 | * Description : Retries rdma_client_connect() because the listener may not be ready 184 | * when the rdma client attempts to connect 185 | * 186 | * Parameters : 187 | * ctx - An empty resources struct to fill the resources created for this QP. 188 | * user_param - Perftest parameters. 189 | * 190 | * Return Value : SUCCESS,FAILURE. 191 | */ 192 | int retry_rdma_connect(struct pingpong_context *ctx, 193 | struct perftest_parameters *user_param); 194 | 195 | /* rdma_server_connect . 196 | * 197 | * Description : Assinging a server to listen on a rdma_cm port and connect to it. 198 | * 199 | * Parameters : 200 | * ctx - An empty resources struct to fill the resources created for this QP. 201 | * user_param - Perftest parameters. 202 | * 203 | * Return Value : SUCCESS,FAILURE. 204 | */ 205 | int rdma_server_connect(struct pingpong_context *ctx, 206 | struct perftest_parameters *user_param); 207 | /* ctx_hand_shake . 208 | * 209 | * Description : 210 | * 211 | * Exchanging the data , represented in struct pingpong_dest , between 212 | * a server and client that performed the ctx_server/clinet_connect. 213 | * The method fills in rem_dest the remote machine data , and passed the data 214 | * in my_dest to other machine. 215 | * 216 | * Parameters : 217 | * 218 | * params - The parameters needed for this method. Are mentioned above ,and 219 | * contains standard IB info. (exists on perftest). 220 | * my_dest - Contains the data you want to pass to the other side. 221 | * rem_dest - The other side data. 222 | * 223 | * Return Value : 0 upon success. -1 if it fails. 224 | */ 225 | int ctx_hand_shake(struct perftest_comm *comm, 226 | struct pingpong_dest *my_dest, 227 | struct pingpong_dest *rem_dest); 228 | 229 | 230 | 231 | /* ctx_print_pingpong_data. 232 | * 233 | * Description : 234 | * 235 | * Prints the data stored in the struct pingpong_dest. 236 | * 237 | * Parameters : 238 | * 239 | * params - The parameters of the machine. 240 | * element - The element to print. 241 | */ 242 | void ctx_print_pingpong_data(struct pingpong_dest *element, 243 | struct perftest_comm *comm); 244 | 245 | /* ctx_close_connection . 246 | * 247 | * Description : 248 | * 249 | * Close the connection between the 2 machines. 250 | * It performs an handshake to ensure the 2 sides are there. 251 | * 252 | * Parameters : 253 | * 254 | * params - The parameters of the machine 255 | * my_dest ,rem_dest - The 2 sides that ends the connection. 256 | * 257 | * Return Value : 0 upon success. -1 if it fails. 258 | */ 259 | int ctx_close_connection(struct perftest_comm *comm, 260 | struct pingpong_dest *my_dest, 261 | struct pingpong_dest *rem_dest); 262 | 263 | /* ctx_xchg_data . 264 | * 265 | * Description : 266 | * 267 | * Exchanging data between 268 | * a server and client after performing ctx_server/client_connect. 269 | * The method fills in rem_data the remote machine data , and passed the data 270 | * in my_dest to other machine. 271 | * 272 | * Parameters : 273 | * 274 | * comm - contains connections info 275 | * my_data - Contains the data you want to pass to the other side. 276 | * rem_data - The other side data. 277 | * size - size of my_data (after casting is made) 278 | * 279 | * Return Value : 0 upon success. -1 if it fails. 280 | */ 281 | int ctx_xchg_data( struct perftest_comm *comm, 282 | void *my_data, 283 | void *rem_data,int size); 284 | 285 | /* ethernet_write_data . 286 | * 287 | * Description : 288 | * 289 | * Sends data that is written in msg using ethernet 290 | * This functions can send any basic type (int,float,double,char*,string, etc..). 291 | * If you need to send a struct, decoder and encoder must be implemented to convert 292 | * the struct to a string 293 | * 294 | * Parameters : 295 | * 296 | * comm - contains connections info 297 | * msg - message that will be sent 298 | * size - size of the message 299 | * Return Value : 0 upon success. -1 if it fails. 300 | */ 301 | int ethernet_write_data(struct perftest_comm *comm, char *msg, size_t size); 302 | 303 | /* ethernet_read_data . 304 | * 305 | * Description : 306 | * 307 | * Read data from remote machine using ethernet. 308 | * 309 | * Parameters : 310 | * 311 | * comm - contains connections info 312 | * recv_msg - function will return, in this argument, the message from remote machine 313 | * size - size of the message 314 | * Return Value : 0 upon success. -1 if it fails. 315 | */ 316 | int ethernet_read_data(struct perftest_comm *comm, char *recv_msg, size_t size); 317 | 318 | /* rdma_write_data . 319 | * 320 | * Description : 321 | * 322 | * Sends data that to remote machine using RDMA. 323 | * This functions can send any variable type 324 | * 325 | * Parameters : 326 | * 327 | * data - data that will be sent 328 | * comm - contains connections info 329 | * size - size of data 330 | * Return Value : 0 upon success. -1 if it fails. 331 | */ 332 | int rdma_write_data(void *data, struct perftest_comm *comm, int size); 333 | 334 | /* rdma_read_data . 335 | * 336 | * Description : 337 | * 338 | * Reads data from remote machine using RDMA. 339 | * This functions can read any variable type 340 | * 341 | * Parameters : 342 | * 343 | * data - data that will be sent 344 | * comm - contains connections info 345 | * size - size of data 346 | * Return Value : 0 upon success. -1 if it fails. 347 | * Return Value : 0 upon success. -1 if it fails. 348 | */ 349 | int rdma_read_data(void *data, struct perftest_comm *comm, int size); 350 | 351 | /* ctx_xchg_data . 352 | * 353 | * Description : 354 | * 355 | * Implements ctx_xchg_data for ethernet 356 | * 357 | * Parameters : 358 | * 359 | * comm - contains connections info 360 | * my_data - Contains the data you want to pass to the other side. 361 | * rem_data - The other side data. 362 | * size - size of my_data (after casting is made) 363 | * 364 | * Return Value : 0 upon success. -1 if it fails. 365 | */ 366 | int ctx_xchg_data_ethernet( struct perftest_comm *comm, void *my_data, void *rem_data,int size); 367 | 368 | /* ctx_xchg_data . 369 | * 370 | * Description : 371 | * 372 | * Implements ctx_xchg_data for RDMA 373 | * 374 | * Parameters : 375 | * 376 | * comm - contains connections info 377 | * my_data - Contains the data you want to pass to the other side. 378 | * rem_data - The other side data. 379 | * size - size of my_data (after casting is made) 380 | * 381 | * Return Value : 0 upon success. -1 if it fails. 382 | */ 383 | int ctx_xchg_data_rdma( struct perftest_comm *comm, void *my_data, void *rem_data,int size); 384 | 385 | /* ctx_xchg_data . 386 | * 387 | * Description : 388 | * 389 | * Exchanging bw reports between 390 | * a server and client after performing ctx_server/client_connect. 391 | * The method fills in rem_data the remote machine data , and passed the data 392 | * in my_dest to other machine. 393 | * 394 | * Parameters : 395 | * 396 | * comm - contains connections info 397 | * my_bw_rep - Contains the data you want to pass to the other side. 398 | * rem_bw_rep - The other side data. 399 | * 400 | * Return Value : 0 upon success. -1 if it fails. 401 | */ 402 | void xchg_bw_reports (struct perftest_comm *comm, struct bw_report_data *my_bw_rep, 403 | struct bw_report_data *rem_bw_rep, float remote_version); 404 | 405 | /* exchange_versions. 406 | * 407 | * Description : 408 | * Exchange versions between sides. 409 | * 410 | */ 411 | void exchange_versions (struct perftest_comm *user_comm, struct perftest_parameters *user_param); 412 | 413 | /* check_sys_data. 414 | * 415 | * Description : 416 | * Exchange system data between sides. 417 | * 418 | */ 419 | void check_sys_data(struct perftest_comm *user_comm, struct perftest_parameters *user_param); 420 | 421 | /* check_mtu 422 | * 423 | * Description : Configures test MTU. 424 | * 425 | * Parameters : 426 | * 427 | * context - Context of the device. 428 | * user_param - Perftest parameters. 429 | * user_comm - user communication struct. 430 | * Return Value : SUCCESS, FAILURE. 431 | */ 432 | int check_mtu(struct ibv_context *context,struct perftest_parameters *user_param, struct perftest_comm *user_comm); 433 | 434 | int ctx_check_gid_compatibility(struct pingpong_dest *my_dest, 435 | struct pingpong_dest *rem_dest); 436 | 437 | #endif /* PERFTEST_COMMUNICATION_H */ 438 | 439 | 440 | 441 | -------------------------------------------------------------------------------- /src/perftest_parameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Mellanox Technologies Ltd. All rights reserved. 3 | * 4 | * This software is available to you under a choice of one of two 5 | * licenses. You may choose to be licensed under the terms of the GNU 6 | * General Public License (GPL) Version 2, available from the file 7 | * COPYING in the main directory of this source tree, or the 8 | * OpenIB.org BSD license below: 9 | * 10 | * Redistribution and use in source and binary forms, with or 11 | * without modification, are permitted provided that the following 12 | * conditions are met: 13 | * 14 | * - Redistributions of source code must retain the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer. 17 | * 18 | * - Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | * 32 | * Author: Ido Shamay 33 | * 34 | * Description : 35 | * 36 | * This API defines structs, formats and enums for all perftest benchmarks. 37 | * It includes parameters parser, and a report generator. 38 | * 39 | * Methods : 40 | * 41 | * link_layer_str - Return a String representation of the link type. 42 | * parser - Setting default test parameters and parsing the user choices. 43 | * check_link - Configures test MTU,inline and link layer of the test. 44 | * check_link_and_mtu - Configures test MTU,inline and link layer of the test. 45 | * print_report_bw - Calculate the peak and average throughput of the BW test. 46 | * print_full_bw_report - Print the peak and average throughput of the BW test. 47 | * print_report_lat - Print the min/max/median latency samples taken from a latency test. 48 | * print_report_lat_duration - Prints only the avergae latency for samples taken from 49 | * a latency test with Duration.. 50 | * set_mtu - set MTU from the port or user. 51 | * set_eth_mtu - set MTU for Raw Ethernet tests. 52 | */ 53 | #ifndef PERFTEST_PARAMETERS_H 54 | #define PERFTEST_PARAMETERS_H 55 | 56 | #include 57 | #include 58 | #include 59 | #include "get_clock.h" 60 | 61 | #ifdef HAVE_CONFIG_H 62 | #include 63 | #endif 64 | 65 | #ifdef HAVE_VERBS_EXP 66 | #include 67 | #endif 68 | 69 | #ifdef HAVE_CUDA 70 | #include CUDA_PATH 71 | #endif 72 | 73 | #ifdef HAVE_ROCM 74 | #include HSA_PATH 75 | #include HSA_EXT_AMD_PATH 76 | #endif 77 | 78 | 79 | /* Connection types available. */ 80 | #define RC (0) 81 | #define UC (1) 82 | #define UD (2) 83 | #define RawEth (3) 84 | #define XRC (4) 85 | #define DC (5) 86 | 87 | /* Genral control definitions */ 88 | #define OFF (0) 89 | #define ON (1) 90 | #define SUCCESS (0) 91 | #define FAILURE (1) 92 | #define VERSION_EXIT (10) 93 | #define HELP_EXIT (11) 94 | #define MTU_FIX (7) 95 | #define MAX_SIZE (8388608) 96 | #define LINK_FAILURE (4) 97 | #define MAX_OUT_READ_HERMON (16) 98 | #define MAX_OUT_READ (4) 99 | #define UD_ADDITION (40) 100 | #define RAWETH_ADDITION (18) 101 | #define HW_CRC_ADDITION (4) 102 | 103 | /* Default Values of perftest parameters */ 104 | #define DEF_PORT (18515) 105 | #define DEF_IB_PORT (1) 106 | #define DEF_IB_PORT2 (2) 107 | #define DEF_SIZE_BW (65536) 108 | #define DEF_SIZE_LAT (2) 109 | #define DEF_ITERS (1000) 110 | #define DEF_ITERS_WB (5000) 111 | #define DEF_TX_BW (128) 112 | #define DEF_TX_LAT (1) 113 | #define DEF_QP_TIME (14) 114 | #define DEF_SL (0) 115 | #define DEF_GID_INDEX (-1) 116 | #define DEF_NUM_QPS (1) 117 | #define DEF_RX_RDMA (1) 118 | #define DEF_RX_SEND (512) 119 | #define DEF_CQ_MOD (100) 120 | #define DEF_SIZE_ATOMIC (8) 121 | #define DEF_QKEY 0x11111111 122 | #define DEF_DURATION (5) 123 | #define DEF_MARGIN (2) 124 | #define DEF_INIT_MARGIN (-1) 125 | #define DEF_INLINE (-1) 126 | #define DEF_TOS (-1) 127 | #define DEF_RETRY_COUNT (7) 128 | #define DEF_CACHE_LINE_SIZE (64) 129 | #define DEF_PAGE_SIZE (4096) 130 | 131 | /* Optimal Values for Inline */ 132 | #define DEF_INLINE_WRITE (220) 133 | #define DEF_INLINE_SEND_RC_UC (236) 134 | #define DEF_INLINE_SEND_XRC (236) 135 | #define DEF_INLINE_SEND_UD (188) 136 | #define DEF_INLINE_DC (150) 137 | 138 | /* Max and Min allowed values for perftest parameters. */ 139 | #define MIN_TOS (0) 140 | #define MAX_TOS (256) 141 | #define MIN_IB_PORT (1) 142 | #define MAX_IB_PORT (3) 143 | #define MIN_ITER (5) 144 | #define MAX_ITER (100000000) 145 | #define MIN_TX (1) 146 | #define MAX_TX (15000) 147 | #define MIN_SL (0) 148 | #define MAX_SL (15) 149 | #define MIN_GID_IX (0) 150 | #define MAX_GID_IX (64) 151 | #define MIN_QP_NUM (1) 152 | #define MAX_QP_NUM (16384) 153 | #define MIN_QP_MCAST (1) 154 | #define MAX_QP_MCAST (56) 155 | #define MIN_RX (1) 156 | #define MAX_RX (16384) 157 | #define UC_MAX_RX (16000) 158 | #define MIN_CQ_MOD (1) 159 | #define MAX_CQ_MOD (1024) 160 | #define MAX_INLINE (912) 161 | #define MAX_INLINE_UD (884) 162 | 163 | /* Raw etherent defines */ 164 | #define RAWETH_MIN_MSG_SIZE (64) 165 | #define MIN_MTU_RAW_ETERNET (64) 166 | #define MAX_MTU_RAW_ETERNET (9600) 167 | 168 | 169 | #define RESULT_LINE "---------------------------------------------------------------------------------------\n" 170 | 171 | #define RESULT_LINE_PER_PORT "-------------------------------------------------------------------------------------------------------------------------------------------------------------------\n" 172 | 173 | /* The format of the results */ 174 | #define RESULT_FMT " #bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]" 175 | 176 | #define RESULT_FMT_PER_PORT " #bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps] BW Port1[MB/sec] MsgRate Port1[Mpps] BW Port2[MB/sec] MsgRate Port2[Mpps]" 177 | 178 | #define RESULT_FMT_G " #bytes #iterations BW peak[Gb/sec] BW average[Gb/sec] MsgRate[Mpps]" 179 | 180 | #define RESULT_FMT_G_PER_PORT " #bytes #iterations BW peak[Gb/sec] BW average[Gb/sec] MsgRate[Mpps] BW Port1[Gb/sec] MsgRate Port1[Mpps] BW Port2[Gb/sec] MsgRate Port2[Mpps]" 181 | 182 | #define RESULT_FMT_QOS " #bytes #sl #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]" 183 | 184 | #define RESULT_FMT_G_QOS " #bytes #sl #iterations BW peak[Gb/sec] BW average[Gb/sec] MsgRate[Mpps]" 185 | 186 | #define RESULT_FMT_LAT " #bytes #iterations t_min[usec] t_max[usec] t_typical[usec]" 187 | 188 | #define RESULT_FMT_LAT_DUR " #bytes #iterations t_avg[usec] " 189 | 190 | #define RESULT_EXT "\n" 191 | 192 | #define RESULT_EXT_CPU_UTIL " CPU_Util[%%]\n" 193 | 194 | /* Result print format */ 195 | #define REPORT_FMT " %-7lu %-10lu %-7.2lf %-7.2lf %-7.6lf" 196 | 197 | #define REPORT_FMT_EXT " %-7lu %lu %-7.6lf %-7.6lf %-7.6lf" 198 | 199 | #define REPORT_FMT_PER_PORT " %-7lu %-10lu %-7.2lf %-7.2lf %-7.6lf %-7.2lf %-7.6lf %-7.2lf %-7.6lf" 200 | 201 | #define REPORT_EXT "\n" 202 | 203 | #define REPORT_EXT_CPU_UTIL " %-3.2f\n" 204 | 205 | #define REPORT_FMT_QOS " %-7lu %d %lu %-7.2lf %-7.2lf %-7.6lf\n" 206 | 207 | /* Result print format for latency tests. */ 208 | #define REPORT_FMT_LAT " %-7lu %d %-7.2f %-7.2f %-7.2f" 209 | 210 | #define REPORT_FMT_LAT_DUR " %-7lu %d %-7.2f" 211 | 212 | #define CHECK_VALUE(arg,type,minv,maxv,name) \ 213 | { arg = (type)strtol(optarg, NULL, 0); if ((arg < minv) || (arg > maxv)) \ 214 | { fprintf(stderr," %s should be between %d and %d\n",name,minv,maxv); return 1; }} 215 | 216 | /* Macro for allocating. */ 217 | #define ALLOCATE(var,type,size) \ 218 | { if((var = (type*)malloc(sizeof(type)*(size))) == NULL) \ 219 | { fprintf(stderr," Cannot Allocate\n"); exit(1);}} 220 | 221 | /* This is our string builder */ 222 | #define GET_STRING(orig,temp) \ 223 | { ALLOCATE(orig,char,(strlen(temp) + 1)); strcpy(orig,temp); } 224 | 225 | #define MTU_SIZE(mtu_ind) (((uint64_t)1 << (MTU_FIX + mtu_ind))) 226 | 227 | #define MAX_VERSION 16 /* Reserve 15 bytes for version numbers */ 228 | 229 | /* The Verb of the benchmark. */ 230 | typedef enum { SEND , WRITE, READ, ATOMIC } VerbType; 231 | 232 | /* The type of the test */ 233 | typedef enum { LAT , BW } TestType; 234 | 235 | /* The type of the machine ( server or client actually). */ 236 | typedef enum { SERVER , CLIENT , UNCHOSEN} MachineType; 237 | 238 | /* The type of the machine ( server or client actually). */ 239 | typedef enum { LOCAL , REMOTE } PrintDataSide; 240 | 241 | /* The atomic test type */ 242 | typedef enum {CMP_AND_SWAP, FETCH_AND_ADD} AtomicType; 243 | 244 | /* Type of test method. */ 245 | typedef enum { ITERATIONS , DURATION } TestMethod; 246 | 247 | /* for duration calculation */ 248 | typedef enum { START_STATE, SAMPLE_STATE, STOP_SAMPLE_STATE, END_STATE} DurationStates; 249 | 250 | /* Report format (Gbit/s VS MB/s) */ 251 | enum ctx_report_fmt { GBS, MBS }; 252 | 253 | /* Test method */ 254 | enum ctx_test_method {RUN_REGULAR, RUN_ALL, RUN_INFINITELY}; 255 | 256 | /* The type of the device */ 257 | enum ctx_device { 258 | DEVICE_ERROR = -1, 259 | UNKNOWN = 0, 260 | CONNECTX = 1, 261 | CONNECTX2 = 2, 262 | CONNECTX3 = 3, 263 | CONNECTIB = 4, 264 | LEGACY = 5, 265 | CHELSIO_T4 = 6, 266 | CHELSIO_T5 = 7, 267 | CONNECTX3_PRO = 8, 268 | SKYHAWK = 9, 269 | CONNECTX4 = 10, 270 | CONNECTX4LX = 11 271 | }; 272 | 273 | /* Units for rate limiter */ 274 | enum rate_limiter_units {MEGA_BYTE_PS, GIGA_BIT_PS, PACKET_PS}; 275 | 276 | /* Verbosity Levels for test report */ 277 | enum verbosity_level {FULL_VERBOSITY=-1, OUTPUT_BW=0, OUTPUT_MR, OUTPUT_LAT }; 278 | 279 | /*Accelerated verbs */ 280 | enum verbs_intf { 281 | NORMAL_INTF, 282 | ACCL_INTF, 283 | }; 284 | 285 | struct cpu_util_data { 286 | int enable; 287 | long long ustat[2]; 288 | long long idle[2]; 289 | }; 290 | 291 | struct check_alive_data { 292 | int current_totrcnt; 293 | int last_totrcnt; 294 | int g_total_iters; 295 | int to_exit; 296 | int is_events; 297 | }; 298 | 299 | struct perftest_parameters { 300 | 301 | int port; 302 | char *ib_devname; 303 | char *servername; 304 | uint8_t ib_port; 305 | uint8_t ib_port2; 306 | int mtu; 307 | enum ibv_mtu curr_mtu; 308 | uint64_t size; 309 | uint64_t dct_key; 310 | int iters; 311 | uint64_t iters_per_port[2]; 312 | uint64_t *port_by_qp; 313 | int tx_depth; 314 | uint8_t qp_timeout; 315 | uint8_t sl; 316 | int gid_index; 317 | int gid_index2; 318 | int use_gid_user; 319 | uint8_t source_mac[6]; 320 | uint8_t dest_mac[6]; 321 | int is_source_mac; 322 | int is_dest_mac; 323 | uint32_t server_ip; 324 | uint32_t client_ip; 325 | int is_server_ip; 326 | int is_client_ip; 327 | int server_port; 328 | int client_port; 329 | int tcp; 330 | int is_server_port; 331 | int is_client_port; 332 | uint16_t ethertype; 333 | int is_ethertype; 334 | int cpu_freq_f; 335 | int connection_type; 336 | int num_of_qps; 337 | int use_event; 338 | int inline_size; 339 | int inline_recv_size; 340 | int out_reads; 341 | int rx_depth; 342 | int duplex; 343 | int noPeak; 344 | int cq_mod; 345 | int spec; 346 | int dualport; 347 | int post_list; 348 | int duration; 349 | int use_srq; 350 | int use_xrc; 351 | int use_rss; 352 | int srq_exists; 353 | int tos; 354 | int margin; 355 | int is_bw_limit_passed; 356 | int is_msgrate_limit_passed; 357 | int is_limit_bw; 358 | int is_limit_msgrate; 359 | float limit_bw; 360 | float limit_msgrate; 361 | uint32_t rem_ud_qpn; 362 | uint32_t rem_ud_qkey; 363 | uint8_t link_type; 364 | uint8_t link_type2; 365 | MachineType machine; 366 | PrintDataSide side; 367 | VerbType verb; 368 | TestType tst; 369 | AtomicType atomicType; 370 | TestMethod test_type; 371 | DurationStates state; 372 | int sockfd; 373 | char version[MAX_VERSION]; 374 | char rem_version[MAX_VERSION]; 375 | cycles_t *tposted; 376 | cycles_t *tcompleted; 377 | int use_mcg; 378 | int use_rdma_cm; 379 | int is_reversed; 380 | int work_rdma_cm; 381 | char *user_mgid; 382 | int buff_size; 383 | int pkey_index; 384 | int raw_qos; 385 | int use_cuda; 386 | int use_rocm; 387 | unsigned long hsa_agent_index; 388 | unsigned long hsa_pool_index; 389 | char *mmap_file; 390 | unsigned long mmap_offset; 391 | /* New test params format pilot. will be used in all flags soon,. */ 392 | enum ctx_test_method test_method; 393 | enum ibv_transport_type transport_type; 394 | enum ctx_report_fmt report_fmt; 395 | struct report_options *r_flag ; 396 | int mac_fwd; 397 | int report_both; /* in bidirectional tests, report tx and rx separately */ 398 | /* results limits */ 399 | float min_bw_limit; 400 | float min_msgRate_limit; 401 | /* Rate Limiter */ 402 | int is_rate_limiting; 403 | int rate_limit; 404 | int burst_size; 405 | enum rate_limiter_units rate_units; 406 | 407 | enum verbosity_level output; 408 | int cpu_util; 409 | struct cpu_util_data cpu_util_data; 410 | int latency_gap; 411 | int retry_count; 412 | int dont_xchg_versions; 413 | int use_exp; 414 | int ipv6; 415 | int report_per_port; 416 | int use_odp; 417 | int use_promiscuous; 418 | int check_alive_exited; 419 | int raw_mcast; 420 | int masked_atomics; 421 | int cycle_buffer; 422 | int cache_line_size; 423 | enum verbs_intf verb_type; 424 | int is_exp_cq; 425 | int is_exp_qp; 426 | int use_res_domain; 427 | int mr_per_qp; 428 | uint16_t dlid; 429 | }; 430 | 431 | struct report_options { 432 | int unsorted; 433 | int histogram; 434 | int cycles; 435 | }; 436 | 437 | struct bw_report_data { 438 | unsigned long size; 439 | uint64_t iters; 440 | double bw_peak; 441 | double bw_avg; 442 | double bw_avg_p1; 443 | double bw_avg_p2; 444 | double msgRate_avg; 445 | double msgRate_avg_p1; 446 | double msgRate_avg_p2; 447 | int sl; 448 | }; 449 | 450 | /* link_layer_str 451 | * 452 | * Description : Return a String representation of the link type. 453 | * 454 | * link_layer : (According to verbs.h) : 455 | * IBV_LINK_LAYER_UNSPECIFIED. 456 | * IBV_LINK_LAYER_INFINIBAND. 457 | * IBV_LINK_LAYER_ETHERNET. 458 | * 459 | * Return Value :"IB", "Etherent" or "Unknown". 460 | */ 461 | const char *link_layer_str(uint8_t link_layer); 462 | 463 | /* parser 464 | * 465 | * Description : Setting default test parameters and parsing the user choises 466 | * 467 | * Parameters : 468 | * 469 | * user_param - the parameters element. 470 | * argv & argc - from the user prompt. 471 | * 472 | * Return Value : 0 upon success. -1 if it fails. 473 | */ 474 | int parser(struct perftest_parameters *user_param,char *argv[], int argc); 475 | 476 | /* check_link_and_mtu 477 | * 478 | * Description : Configures test MTU,inline and link layer of the test. 479 | * 480 | * Parameters : 481 | * 482 | * context - Context of the device. 483 | * user_param - Perftest parameters. 484 | * 485 | * Return Value : SUCCESS, FAILURE. 486 | */ 487 | int check_link(struct ibv_context *context,struct perftest_parameters *user_param); 488 | 489 | /* check_link_and_mtu 490 | * 491 | * Description : Configures test MTU,inline and link layer of the test. 492 | * 493 | * Parameters : 494 | * 495 | * context - Context of the device. 496 | * user_param - Perftest parameters. 497 | * 498 | * Return Value : SUCCESS, FAILURE. 499 | */ 500 | int check_link_and_mtu(struct ibv_context *context,struct perftest_parameters *user_param); 501 | 502 | /* ctx_print_test_info 503 | * 504 | * Description : Prints all the parameters selected for this run. 505 | * 506 | * Parameters : 507 | * 508 | * user_param - the parameters parameters. 509 | * 510 | */ 511 | void ctx_print_test_info(struct perftest_parameters *user_param); 512 | 513 | /* print_report_bw 514 | * 515 | * Description : Calculate the peak and average throughput of the BW test. 516 | * The function will print when not in duplex mode. 517 | * 518 | * Parameters : 519 | * 520 | * user_param - the parameters parameters. 521 | * my_bw_rep - get my bw test report. 522 | * 523 | */ 524 | void print_report_bw (struct perftest_parameters *user_param, struct bw_report_data *my_bw_rep); 525 | 526 | /* print_full_bw_report 527 | * 528 | * Description : Print the peak and average throughput of the BW test. 529 | * If rem_bw_rep is not NULL, the function will sum the server and client results. 530 | * 531 | * Parameters : 532 | * 533 | * user_param - the parameters parameters. 534 | * my_bw_rep - my bw test report. 535 | * rem_bw_rep - remote's bw test report. 536 | * 537 | */ 538 | void print_full_bw_report (struct perftest_parameters *user_param, struct bw_report_data *my_bw_rep, struct bw_report_data *rem_bw_rep); 539 | 540 | /* print_report_lat 541 | * 542 | * Description : Print the min/max/median latency samples taken from a latency test. 543 | * It also support a unsorted/histogram report of all samples. 544 | * 545 | * Parameters : 546 | * 547 | * user_param - the parameters parameters. 548 | * 549 | */ 550 | void print_report_lat (struct perftest_parameters *user_param); 551 | 552 | /* print_report_lat_duration 553 | * 554 | * Description : Prints only the avergae latency for samples taken from a latency test 555 | * With Duration. 556 | * 557 | * Parameters : 558 | * 559 | * user_param - the parameters parameters. 560 | * 561 | */ 562 | void print_report_lat_duration (struct perftest_parameters *user_param); 563 | 564 | /* set_mtu 565 | * 566 | * Description : set MTU from the port or user 567 | * 568 | * Parameters : 569 | * 570 | * context - Context of the device. 571 | * ib_port - ib port number that's in use. 572 | * user_mtu - MTU that the user supplied. 573 | * 574 | * Return Value : MTU size 575 | */ 576 | enum ibv_mtu set_mtu(struct ibv_context *context,uint8_t ib_port,int user_mtu); 577 | 578 | /* set_eth_mtu 579 | * 580 | * Description : set MTU for Raw Ethernet tests 581 | * 582 | * Parameters : 583 | * 584 | * user_param - the parameters parameters. 585 | * 586 | * Return Value : MTU size 587 | */ 588 | int set_eth_mtu(struct perftest_parameters *user_param); 589 | 590 | /****************************************************************************** 591 | * 592 | ******************************************************************************/ 593 | enum ctx_device ib_dev_name(struct ibv_context *context); 594 | 595 | #endif /* PERFTEST_RESOURCES_H */ 596 | -------------------------------------------------------------------------------- /src/raw_ethernet_resources.h: -------------------------------------------------------------------------------- 1 | #ifndef RAW_ETHERNET_RESOURCES_H 2 | #define RAW_ETHERNET_RESOURCES_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "perftest_parameters.h" 13 | #include "perftest_resources.h" 14 | #include "multicast_resources.h" 15 | #include "perftest_communication.h" 16 | #include 17 | 18 | #define INFO "INFO" 19 | #define TRACE "TRACE" 20 | 21 | #ifdef DEBUG 22 | #define DEBUG_LOG(type,fmt, args...) fprintf(stderr,"file:%s: %d ""["type"]"fmt"\n",__FILE__,__LINE__,args) 23 | #else 24 | #define DEBUG_LOG(type,fmt, args...) 25 | #endif 26 | 27 | #define PERF_MAC_FMT " %02X:%02X:%02X:%02X:%02X:%02X" 28 | 29 | #define IP_ETHER_TYPE (0x800) 30 | #define PRINT_ON (1) 31 | #define PRINT_OFF (0) 32 | #define UDP_PROTOCOL (0x11) 33 | #define TCP_PROTOCOL (0x06) 34 | #define IP_HEADER_LEN (20) 35 | #define DEFAULT_TTL (128) 36 | 37 | struct raw_ethernet_info { 38 | uint8_t mac[6]; 39 | uint32_t ip; 40 | int port; 41 | }; 42 | 43 | 44 | /* gen_eth_header . 45 | * Description :create raw Ethernet header on buffer 46 | * 47 | * Parameters : 48 | * eth_header - Pointer to output 49 | * src_mac - source MAC address of the packet 50 | * dst_mac - destination MAC address of the packet 51 | * eth_type - IP/or size of ptk 52 | * 53 | */ 54 | 55 | struct ETH_header { 56 | uint8_t dst_mac[6]; 57 | uint8_t src_mac[6]; 58 | uint16_t eth_type; 59 | }__attribute__((packed)); 60 | 61 | struct IP_V4_header{ 62 | #if defined(__LITTLE_ENDIAN_BITFIELD) 63 | uint8_t ihl:4; 64 | uint8_t version:4; 65 | #elif defined(__BIG_ENDIAN_BITFIELD) 66 | uint8_t version:4; 67 | uint8_t ihl:4; 68 | #endif 69 | uint8_t tos; 70 | uint16_t tot_len; 71 | uint16_t id; 72 | uint16_t frag_off; 73 | uint8_t ttl; 74 | uint8_t protocol; 75 | uint16_t check; 76 | uint32_t saddr; 77 | uint32_t daddr; 78 | }__attribute__((packed)); 79 | 80 | struct UDP_header { 81 | u_short uh_sport; /* source port */ 82 | u_short uh_dport; /* destination port */ 83 | u_short uh_ulen; /* udp length */ 84 | u_short uh_sum; /* udp checksum */ 85 | }__attribute__((packed)); 86 | 87 | struct TCP_header { 88 | uint16_t th_sport; /* source port */ 89 | uint16_t th_dport; /* destination port */ 90 | uint32_t th_seq; 91 | uint32_t th_ack; 92 | uint8_t th_rsv:4; 93 | uint8_t th_doff:4; 94 | uint8_t th_falgs; 95 | uint16_t th_window; 96 | uint16_t th_check; 97 | uint16_t th_urgptr; 98 | }__attribute__((packed)); 99 | 100 | void gen_eth_header(struct ETH_header* eth_header,uint8_t* src_mac,uint8_t* dst_mac, uint16_t eth_type); 101 | #ifdef HAVE_RAW_ETH_EXP 102 | void print_spec(struct ibv_exp_flow_attr* flow_rules,struct perftest_parameters* user_param); 103 | #else 104 | void print_spec(struct ibv_flow_attr* flow_rules,struct perftest_parameters* user_param); 105 | #endif 106 | void print_ethernet_header(struct ETH_header* p_ethernet_header); 107 | void print_ip_header(struct IP_V4_header* ip_header); 108 | void print_udp_header(struct UDP_header* udp_header); 109 | void print_pkt(void* pkt,struct perftest_parameters *user_param); 110 | 111 | int check_flow_steering_support(char *dev_name); 112 | 113 | /* build_pkt_on_buffer 114 | * Description: build single Ethernet packet on ctx buffer 115 | * 116 | * Parameters: 117 | * eth_header - Pointer to output 118 | * my_dest_info - ethernet information of me 119 | * rem_dest_info - ethernet information of the remote 120 | * user_param - user_parameters struct for this test 121 | * eth_type - 122 | * ip_next_protocol - 123 | * print_flag - if print_flag == TRUE : print the packet after it's done 124 | * sizePkt - size of the requested packet 125 | */ 126 | void build_pkt_on_buffer(struct ETH_header* eth_header, 127 | struct raw_ethernet_info *my_dest_info, 128 | struct raw_ethernet_info *rem_dest_info, 129 | struct perftest_parameters *user_param, 130 | uint16_t eth_type, 131 | uint16_t ip_next_protocol, 132 | int print_flag, 133 | int sizePkt); 134 | 135 | /* create_raw_eth_pkt 136 | * Description: build raw Ethernet packet by user arguments 137 | * on bw test, build one packet and duplicate it on the buffer 138 | * on lat test, build only one packet on the buffer (for the ping pong method) 139 | * 140 | * Parameters: 141 | * user_param - user_parameters struct for this test 142 | * ctx - Test Context. 143 | * my_dest_info - ethernet information of me 144 | * rem_dest_info - ethernet information of the remote 145 | */ 146 | void create_raw_eth_pkt( struct perftest_parameters *user_param, 147 | struct pingpong_context *ctx , 148 | struct raw_ethernet_info *my_dest_info, 149 | struct raw_ethernet_info *rem_dest_info); 150 | 151 | /*calc_flow_rules_size 152 | * Description: calculate the size of the flow(size of headers - ib, ethernet and ip/udp if available) 153 | * Parameters: 154 | * is_ip_header - if ip header is exist, count the header's size 155 | * is_udp_header - if udp header is exist, count the header's size 156 | * 157 | */ 158 | int calc_flow_rules_size(int is_ip_header,int is_udp_header); 159 | 160 | /* send_set_up_connection 161 | * Description: init raw_ethernet_info and ibv_flow_spec to user args 162 | * 163 | * Parameters: 164 | * flow_rules - Pointer to output, is set to header buffer and specification information 165 | * ctx - Test Context. 166 | * user_param - user_parameters struct for this test 167 | * my_dest_info - ethernet information of me 168 | * rem_dest_info - ethernet information of the remote 169 | * 170 | */ 171 | 172 | int send_set_up_connection( 173 | #ifdef HAVE_RAW_ETH_EXP 174 | struct ibv_exp_flow_attr **flow_rules, 175 | #else 176 | struct ibv_flow_attr **flow_rules, 177 | #endif 178 | struct pingpong_context *ctx, 179 | struct perftest_parameters *user_param, 180 | struct raw_ethernet_info* my_dest_info, 181 | struct raw_ethernet_info* rem_dest_info); 182 | 183 | /* gen_ip_header . 184 | 185 | * Description :create IP header on buffer 186 | * 187 | * Parameters : 188 | * ip_header_buff - Pointer to output 189 | * saddr - source IP address of the packet(network order) 190 | * daddr - destination IP address of the packet(network order) 191 | * sizePkt - size of the packet 192 | */ 193 | void gen_ip_header(void* ip_header_buff,uint32_t* saddr ,uint32_t* daddr,uint8_t protocol,int sizePkt, int tos); 194 | 195 | /* gen_udp_header . 196 | 197 | * Description :create UDP header on buffer 198 | * 199 | * Parameters : 200 | * UDP_header_buffer - Pointer to output 201 | * sPort - source UDP port of the packet 202 | * dPort -destination UDP port of the packet 203 | * sadder -source IP address of the packet(using for UPD checksum)(network order) 204 | * dadder - source IP address of the packet(using for UPD checksum)(network order) 205 | * sizePkt - size of the packet 206 | */ 207 | void gen_udp_header(void* UDP_header_buffer,int* sPort ,int* dPort,uint32_t saddr,uint32_t daddr,int sizePkt); 208 | 209 | /* gen_udp_header . 210 | 211 | * Description :create UDP header on buffer 212 | * 213 | * Parameters : 214 | * TCP_header_buffer - Pointer to output 215 | * sPort - source TCP port of the packet 216 | * dPort -destination TCP port of the packet 217 | */ 218 | void gen_tcp_header(void* TCP_header_buffer,int* sPort ,int* dPort); 219 | 220 | /* run_iter_fw 221 | * 222 | * Description : 223 | * 224 | * In this method we receive packets and "turn them around" 225 | * this is done by changing the dmac with the smac 226 | * 227 | * Parameters : 228 | * 229 | * ctx - Test Context. 230 | * user_param - user_parameters struct for this test. 231 | */ 232 | int run_iter_fw(struct pingpong_context *ctx,struct perftest_parameters *user_param); 233 | 234 | /* switch_smac_dmac 235 | * 236 | * Description : In this method we receive buffer and change it's dmac and smac 237 | * 238 | * Parameters : 239 | * 240 | * sg - sg->addr is pointer to the buffer. 241 | */ 242 | static __inline void switch_smac_dmac(struct ibv_sge *sg) 243 | { 244 | struct ETH_header* eth_header; 245 | eth_header = (struct ETH_header*)sg->addr; 246 | uint8_t tmp_mac[6] = {0} ; 247 | memcpy(tmp_mac , (uint8_t *)eth_header + sizeof(eth_header->src_mac) ,sizeof(eth_header->src_mac)); 248 | memcpy((uint8_t *)eth_header->src_mac , (uint8_t *)eth_header->dst_mac ,sizeof(eth_header->src_mac)); 249 | memcpy((uint8_t *)eth_header->dst_mac , tmp_mac ,sizeof(tmp_mac)); 250 | } 251 | 252 | #endif /* RAW_ETHERNET_RESOURCES_H */ 253 | -------------------------------------------------------------------------------- /src/raw_ethernet_send_bw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 | * 6 | * This software is available to you under a choice of one of two 7 | * licenses. You may choose to be licensed under the terms of the GNU 8 | * General Public License (GPL) Version 2, available from the file 9 | * COPYING in the main directory of this source tree, or the 10 | * OpenIB.org BSD license below: 11 | * 12 | * Redistribution and use in source and binary forms, with or 13 | * without modification, are permitted provided that the following 14 | * conditions are met: 15 | * 16 | * - Redistributions of source code must retain the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer. 19 | * 20 | * - Redistributions in binary form must reproduce the above 21 | * copyright notice, this list of conditions and the following 22 | * disclaimer in the documentation and/or other materials 23 | * provided with the distribution. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | * SOFTWARE. 33 | * 34 | * $Id$ 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "perftest_parameters.h" 45 | #include "perftest_resources.h" 46 | #include "multicast_resources.h" 47 | #include "perftest_communication.h" 48 | #include "raw_ethernet_resources.h" 49 | 50 | 51 | 52 | /****************************************************************************** 53 | * 54 | ******************************************************************************/ 55 | int main(int argc, char *argv[]) 56 | { 57 | struct ibv_device *ib_dev = NULL; 58 | struct pingpong_context ctx; 59 | struct raw_ethernet_info my_dest_info,rem_dest_info; 60 | int ret_parser; 61 | struct perftest_parameters user_param; 62 | 63 | #ifdef HAVE_RAW_ETH_EXP 64 | struct ibv_exp_flow *flow_create_result = NULL; 65 | struct ibv_exp_flow_attr *flow_rules = NULL; 66 | struct ibv_exp_flow *flow_promisc = NULL; 67 | #else 68 | struct ibv_flow *flow_create_result = NULL; 69 | struct ibv_flow_attr *flow_rules = NULL; 70 | #endif 71 | 72 | union ibv_gid mgid; 73 | 74 | /* init default values to user's parameters */ 75 | memset(&ctx, 0,sizeof(struct pingpong_context)); 76 | memset(&user_param, 0 , sizeof(struct perftest_parameters)); 77 | memset(&my_dest_info, 0 , sizeof(struct raw_ethernet_info)); 78 | memset(&rem_dest_info, 0 , sizeof(struct raw_ethernet_info)); 79 | 80 | user_param.verb = SEND; 81 | user_param.tst = BW; 82 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 83 | user_param.connection_type = RawEth; 84 | 85 | ret_parser = parser(&user_param,argv,argc); 86 | 87 | if (ret_parser) { 88 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) { 89 | fprintf(stderr," Parser function exited with Error\n"); 90 | } 91 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 92 | return 1; 93 | } 94 | 95 | if (user_param.raw_mcast) { 96 | /* Transform IPv4 to Multicast MAC */ 97 | user_param.dest_mac[0] = 0x01; 98 | user_param.dest_mac[1] = 0x00; 99 | user_param.dest_mac[2] = 0x5e; 100 | user_param.dest_mac[3] = (user_param.server_ip >> 8) & 0x7f; 101 | user_param.dest_mac[4] = (user_param.server_ip >> 16) & 0xff; 102 | user_param.dest_mac[5] = (user_param.server_ip >> 24) & 0xff; 103 | 104 | /* Build up MGID (128bits, 16bytes) */ 105 | memset (&mgid, 0, sizeof (union ibv_gid)); 106 | memcpy (&mgid.raw[10], &user_param.dest_mac[0], 6); 107 | 108 | /* Multicast send so no response UDP port */ 109 | user_param.client_port = 0; 110 | 111 | } 112 | 113 | if (user_param.use_rss) { 114 | /* if num_of_qps is not even, set it to 2. */ 115 | if (user_param.num_of_qps % 2) 116 | user_param.num_of_qps = 2; 117 | 118 | /* add another one for rss parent QP */ 119 | user_param.num_of_qps += 1; 120 | } 121 | 122 | /* Finding the IB device selected (or default if no selected). */ 123 | ib_dev = ctx_find_dev(user_param.ib_devname); 124 | if (!ib_dev) { 125 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 126 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 127 | return 1; 128 | } 129 | GET_STRING(user_param.ib_devname, ibv_get_device_name(ib_dev)); 130 | 131 | if (check_flow_steering_support(user_param.ib_devname)) { 132 | return 1; 133 | } 134 | 135 | /* Getting the relevant context from the device */ 136 | ctx.context = ibv_open_device(ib_dev); 137 | if (!ctx.context) { 138 | fprintf(stderr, " Couldn't get context for the device\n"); 139 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 140 | return 1; 141 | } 142 | 143 | /* See if MTU and link type are valid and supported. */ 144 | if (check_link_and_mtu(ctx.context,&user_param)) { 145 | fprintf(stderr, " Couldn't get context for the device\n"); 146 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 147 | return FAILURE; 148 | } 149 | 150 | /* Allocating arrays needed for the test. */ 151 | alloc_ctx(&ctx,&user_param); 152 | 153 | /* Print basic test information. */ 154 | ctx_print_test_info(&user_param); 155 | 156 | /* set mac address by user choose */ 157 | if (send_set_up_connection(&flow_rules,&ctx,&user_param,&my_dest_info,&rem_dest_info)) { 158 | fprintf(stderr," Unable to set up socket connection\n"); 159 | return 1; 160 | } 161 | 162 | if ( !user_param.raw_mcast && (user_param.machine == SERVER || user_param.duplex)) { 163 | print_spec(flow_rules,&user_param); 164 | } 165 | 166 | /* Create (if necessary) the rdma_cm ids and channel. */ 167 | if (user_param.work_rdma_cm == ON) { 168 | 169 | if (create_rdma_resources(&ctx,&user_param)) { 170 | fprintf(stderr," Unable to create the rdma_resources\n"); 171 | return FAILURE; 172 | } 173 | 174 | if (user_param.machine == CLIENT) { 175 | if (rdma_client_connect(&ctx,&user_param)) { 176 | fprintf(stderr,"Unable to perform rdma_client function\n"); 177 | return FAILURE; 178 | } 179 | 180 | } else if (rdma_server_connect(&ctx,&user_param)) { 181 | fprintf(stderr,"Unable to perform rdma_client function\n"); 182 | return FAILURE; 183 | } 184 | 185 | } else { 186 | 187 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 188 | if (ctx_init(&ctx,&user_param)) { 189 | fprintf(stderr, " Couldn't create IB resources\n"); 190 | return FAILURE; 191 | } 192 | } 193 | 194 | /* build raw Ethernet packets on ctx buffer */ 195 | if((user_param.machine == CLIENT || user_param.duplex) && !user_param.mac_fwd) { 196 | create_raw_eth_pkt(&user_param,&ctx, &my_dest_info , &rem_dest_info); 197 | } 198 | 199 | /* Prepare IB resources for rtr/rts. */ 200 | if (user_param.work_rdma_cm == OFF) { 201 | if (ctx_connect(&ctx,NULL,&user_param,NULL)) { 202 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 203 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 204 | return 1; 205 | } 206 | } 207 | 208 | if (user_param.raw_mcast) { 209 | if (user_param.machine == SERVER) { 210 | /* join Multicast group by MGID */ 211 | ibv_attach_mcast(ctx.qp[0], &mgid, 0); 212 | printf(PERF_RAW_MGID_FMT,"MGID", 213 | mgid.raw[0], mgid.raw[1], 214 | mgid.raw[2], mgid.raw[3], 215 | mgid.raw[4], mgid.raw[5], 216 | mgid.raw[6], mgid.raw[7], 217 | mgid.raw[8], mgid.raw[9], 218 | mgid.raw[10],mgid.raw[11], 219 | mgid.raw[12],mgid.raw[13], 220 | mgid.raw[14],mgid.raw[15]); 221 | } 222 | } 223 | else { 224 | /* attaching the qp to the spec */ 225 | if(user_param.machine == SERVER || user_param.duplex) { 226 | #ifdef HAVE_RAW_ETH_EXP 227 | flow_create_result = ibv_exp_create_flow(ctx.qp[0], flow_rules); 228 | #else 229 | flow_create_result = ibv_create_flow(ctx.qp[0], flow_rules); 230 | #endif 231 | if (!flow_create_result){ 232 | perror("error"); 233 | fprintf(stderr, "Couldn't attach QP\n"); 234 | return FAILURE; 235 | } 236 | 237 | #ifdef HAVE_RAW_ETH_EXP 238 | if (user_param.use_promiscuous) { 239 | struct ibv_exp_flow_attr attr = { 240 | .type = IBV_EXP_FLOW_ATTR_ALL_DEFAULT, 241 | .num_of_specs = 0, 242 | .port = user_param.ib_port, 243 | .flags = 0 244 | }; 245 | 246 | if ((flow_promisc = ibv_exp_create_flow(ctx.qp[0], &attr)) == NULL) { 247 | perror("error"); 248 | fprintf(stderr, "Couldn't attach promiscous rule QP\n"); 249 | } 250 | } 251 | #endif 252 | 253 | } 254 | } 255 | 256 | if (user_param.output == FULL_VERBOSITY) { 257 | printf(RESULT_LINE); 258 | if (user_param.raw_qos) 259 | printf((user_param.report_fmt == MBS ? RESULT_FMT_QOS : RESULT_FMT_G_QOS)); 260 | else 261 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 262 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 263 | } 264 | 265 | if (user_param.test_method == RUN_REGULAR) { 266 | if (user_param.machine == CLIENT || user_param.duplex) { 267 | ctx_set_send_wqes(&ctx,&user_param,NULL); 268 | } 269 | 270 | if (user_param.machine == SERVER || user_param.duplex) { 271 | if (ctx_set_recv_wqes(&ctx,&user_param)) { 272 | fprintf(stderr," Failed to post receive recv_wqes\n"); 273 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 274 | return 1; 275 | } 276 | } 277 | 278 | if (user_param.mac_fwd) { 279 | 280 | if(run_iter_fw(&ctx,&user_param)) { 281 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 282 | return FAILURE; 283 | } 284 | 285 | } else if (user_param.duplex) { 286 | 287 | if(run_iter_bi(&ctx,&user_param)) { 288 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 289 | return FAILURE; 290 | } 291 | 292 | } else if (user_param.machine == CLIENT) { 293 | 294 | if(run_iter_bw(&ctx,&user_param)) { 295 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 296 | return FAILURE; 297 | } 298 | 299 | } else { 300 | 301 | if(run_iter_bw_server(&ctx,&user_param)) { 302 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 303 | return 17; 304 | } 305 | } 306 | 307 | print_report_bw(&user_param,NULL); 308 | } else if (user_param.test_method == RUN_INFINITELY) { 309 | 310 | if (user_param.machine == CLIENT) 311 | ctx_set_send_wqes(&ctx,&user_param,NULL); 312 | 313 | else if (user_param.machine == SERVER) { 314 | 315 | if (ctx_set_recv_wqes(&ctx,&user_param)) { 316 | fprintf(stderr," Failed to post receive recv_wqes\n"); 317 | return 1; 318 | } 319 | } 320 | 321 | if (user_param.machine == CLIENT) { 322 | 323 | if(run_iter_bw_infinitely(&ctx,&user_param)) { 324 | fprintf(stderr," Error occured while running infinitely! aborting ...\n"); 325 | return 1; 326 | } 327 | 328 | } else if (user_param.machine == SERVER) { 329 | 330 | if(run_iter_bw_infinitely_server(&ctx,&user_param)) { 331 | fprintf(stderr," Error occured while running infinitely on server! aborting ...\n"); 332 | return 1; 333 | } 334 | } 335 | } 336 | 337 | if(user_param.machine == SERVER || user_param.duplex) { 338 | 339 | if (user_param.raw_mcast) { 340 | if (ibv_detach_mcast(ctx.qp[0], &mgid,0)) { 341 | perror("error"); 342 | fprintf(stderr,"Couldn't leave multicast group\n"); 343 | } 344 | } else { 345 | #ifdef HAVE_RAW_ETH_EXP 346 | if (user_param.use_promiscuous) { 347 | if (ibv_exp_destroy_flow(flow_promisc)) { 348 | perror("error"); 349 | fprintf(stderr, "Couldn't Destory promisc flow\n"); 350 | return FAILURE; 351 | } 352 | } 353 | #endif 354 | 355 | #ifdef HAVE_RAW_ETH_EXP 356 | if (ibv_exp_destroy_flow(flow_create_result)) { 357 | #else 358 | if (ibv_destroy_flow(flow_create_result)) { 359 | #endif 360 | perror("error"); 361 | fprintf(stderr, "Couldn't Destory flow\n"); 362 | return FAILURE; 363 | } 364 | free(flow_rules); 365 | } 366 | } 367 | 368 | if (destroy_ctx(&ctx, &user_param)) { 369 | fprintf(stderr,"Failed to destroy_ctx\n"); 370 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 371 | return 1; 372 | } 373 | 374 | /* limit verifier */ 375 | if (!user_param.is_bw_limit_passed && (user_param.is_limit_bw == ON ) ) { 376 | fprintf(stderr,"Error: BW result is below bw limit\n"); 377 | return 1; 378 | } 379 | 380 | if (user_param.output == FULL_VERBOSITY) 381 | printf(RESULT_LINE); 382 | 383 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 384 | return 0; 385 | } 386 | -------------------------------------------------------------------------------- /src/raw_ethernet_send_lat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 | * 6 | * This software is available to you under a choice of one of two 7 | * licenses. You may choose to be licensed under the terms of the GNU 8 | * General Public License (GPL) Version 2, available from the file 9 | * COPYING in the main directory of this source tree, or the 10 | * OpenIB.org BSD license below: 11 | * 12 | * Redistribution and use in source and binary forms, with or 13 | * without modification, are permitted provided that the following 14 | * conditions are met: 15 | * 16 | * - Redistributions of source code must retain the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer. 19 | * 20 | * - Redistributions in binary form must reproduce the above 21 | * copyright notice, this list of conditions and the following 22 | * disclaimer in the documentation and/or other materials 23 | * provided with the distribution. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | * SOFTWARE. 33 | * 34 | * $Id$ 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "perftest_parameters.h" 45 | #include "perftest_resources.h" 46 | #include "multicast_resources.h" 47 | #include "perftest_communication.h" 48 | #include "raw_ethernet_resources.h" 49 | 50 | 51 | /* 52 | * Main function. implements raw_ethernet_send_lat 53 | */ 54 | int main(int argc, char *argv[]) 55 | { 56 | 57 | struct ibv_device *ib_dev = NULL; 58 | struct pingpong_context ctx; 59 | struct raw_ethernet_info my_dest_info,rem_dest_info; 60 | int ret_parser; 61 | struct perftest_parameters user_param; 62 | #ifdef HAVE_RAW_ETH_EXP 63 | struct ibv_exp_flow *flow_create_result = NULL; 64 | struct ibv_exp_flow_attr *flow_rules = NULL; 65 | struct ibv_exp_flow *flow_promisc = NULL; 66 | #else 67 | struct ibv_flow *flow_create_result = NULL; 68 | struct ibv_flow_attr *flow_rules = NULL; 69 | #endif 70 | struct report_options report; 71 | 72 | /* allocate memory space for user parameters &*/ 73 | memset(&ctx, 0, sizeof(struct pingpong_context)); 74 | memset(&user_param, 0, sizeof(struct perftest_parameters)); 75 | memset(&my_dest_info, 0 , sizeof(struct raw_ethernet_info)); 76 | memset(&rem_dest_info, 0 , sizeof(struct raw_ethernet_info)); 77 | 78 | /* init default values to user's parameters that's relvant for this test: 79 | * Raw Ethernet Send Latency Test 80 | */ 81 | user_param.verb = SEND; 82 | user_param.tst = LAT; 83 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 84 | user_param.connection_type = RawEth; 85 | user_param.r_flag = &report; 86 | 87 | 88 | /* Configure the parameters values according to user 89 | arguments or default values. */ 90 | ret_parser = parser(&user_param, argv,argc); 91 | 92 | /* check for parsing errors */ 93 | if (ret_parser) { 94 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 95 | fprintf(stderr," Parser function exited with Error\n"); 96 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 97 | return 1; 98 | } 99 | 100 | /*this is a bidirectional test, so we need to let the init functions 101 | * think we are in duplex mode 102 | */ 103 | user_param.duplex = 1; 104 | 105 | 106 | /* Find the selected IB device (or default if the user didn't select one). */ 107 | ib_dev = ctx_find_dev(user_param.ib_devname); 108 | if (!ib_dev) { 109 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 110 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 111 | return 1; 112 | } 113 | GET_STRING(user_param.ib_devname, ibv_get_device_name(ib_dev)); 114 | 115 | if (check_flow_steering_support(user_param.ib_devname)) { 116 | return 1; 117 | } 118 | 119 | /* Getting the relevant context from the device */ 120 | ctx.context = ibv_open_device(ib_dev); 121 | if (!ctx.context) { 122 | fprintf(stderr, " Couldn't get context for the device\n"); 123 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 124 | return 1; 125 | } 126 | 127 | /* See if MTU and link type are valid and supported. */ 128 | if (check_link_and_mtu(ctx.context, &user_param)) { 129 | fprintf(stderr, " Couldn't get context for the device\n"); 130 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 131 | return FAILURE; 132 | } 133 | 134 | /* Allocating arrays needed for the test. */ 135 | alloc_ctx(&ctx, &user_param); 136 | 137 | /* Print basic test information. */ 138 | ctx_print_test_info(&user_param); 139 | 140 | /*set up the connection, return the required flow rules (notice that user_param->duplex == TRUE) 141 | * so the function will setup like it's a bidirectional test 142 | */ 143 | if (send_set_up_connection(&flow_rules, &ctx, &user_param, &my_dest_info, &rem_dest_info)) { 144 | fprintf(stderr," Unable to set up socket connection\n"); 145 | return 1; 146 | } 147 | 148 | print_spec(flow_rules,&user_param); 149 | 150 | /* Create (if necessary) the rdma_cm ids and channel. */ 151 | if (user_param.work_rdma_cm == ON) { 152 | 153 | if (create_rdma_resources(&ctx, &user_param)) { 154 | fprintf(stderr," Unable to create the rdma_resources\n"); 155 | return FAILURE; 156 | } 157 | 158 | if (user_param.machine == CLIENT) { 159 | 160 | /* Connects the client to a QP on the other machine with rdma_cm */ 161 | if (rdma_client_connect(&ctx, &user_param)) { 162 | fprintf(stderr,"Unable to perform rdma_client function\n"); 163 | return FAILURE; 164 | } 165 | 166 | } else if (rdma_server_connect(&ctx, &user_param)) { 167 | /* Assigning a server to listen on rdma_cm port and connect to it. */ 168 | fprintf(stderr,"Unable to perform rdma_server function\n"); 169 | return FAILURE; 170 | } 171 | 172 | } else { 173 | 174 | /* initalize IB resources (data buffer, PD, MR, CQ and events channel) */ 175 | if (ctx_init(&ctx, &user_param)) { 176 | fprintf(stderr, " Couldn't create IB resources\n"); 177 | return FAILURE; 178 | } 179 | } 180 | 181 | 182 | /* attaching the qp to the spec */ 183 | #ifdef HAVE_RAW_ETH_EXP 184 | flow_create_result = ibv_exp_create_flow(ctx.qp[0], flow_rules); 185 | #else 186 | flow_create_result = ibv_create_flow(ctx.qp[0], flow_rules); 187 | #endif 188 | 189 | if (!flow_create_result){ 190 | perror("error"); 191 | fprintf(stderr, "Couldn't attach QP\n"); 192 | return FAILURE; 193 | } 194 | 195 | #ifdef HAVE_RAW_ETH_EXP 196 | if (user_param.use_promiscuous) { 197 | struct ibv_exp_flow_attr attr = { 198 | .type = IBV_EXP_FLOW_ATTR_ALL_DEFAULT, 199 | .num_of_specs = 0, 200 | .port = user_param.ib_port, 201 | .flags = 0 202 | }; 203 | 204 | if ((flow_promisc = ibv_exp_create_flow(ctx.qp[0], &attr)) == NULL) { 205 | perror("error"); 206 | fprintf(stderr, "Couldn't attach promiscous rule QP\n"); 207 | } 208 | } 209 | #endif 210 | 211 | /* build ONE Raw Ethernet packets on ctx buffer */ 212 | create_raw_eth_pkt(&user_param,&ctx, &my_dest_info , &rem_dest_info); 213 | 214 | if (user_param.output == FULL_VERBOSITY) { 215 | printf(RESULT_LINE); 216 | printf("%s",(user_param.test_type == ITERATIONS) ? RESULT_FMT_LAT : RESULT_FMT_LAT_DUR); 217 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 218 | } 219 | 220 | /* modify QPs to rtr/rts */ 221 | if (user_param.work_rdma_cm == OFF) { 222 | if (ctx_connect(&ctx, NULL, &user_param, NULL)) { 223 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 224 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 225 | return 1; 226 | } 227 | } 228 | 229 | ctx_set_send_wqes(&ctx,&user_param,NULL); 230 | 231 | if (ctx_set_recv_wqes(&ctx,&user_param)) { 232 | fprintf(stderr," Failed to post receive recv_wqes\n"); 233 | return 1; 234 | } 235 | 236 | /* latency test function for SEND verb latency test. */ 237 | if (run_iter_lat_send(&ctx, &user_param)) { 238 | return 17; 239 | } 240 | 241 | /* print report (like print_report_bw) in the correct format 242 | * (as set before: FMT_LAT or FMT_LAT_DUR) 243 | */ 244 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : 245 | print_report_lat_duration(&user_param); 246 | 247 | /* destory promisc flow */ 248 | #ifdef HAVE_RAW_ETH_EXP 249 | if (user_param.use_promiscuous) { 250 | if (ibv_exp_destroy_flow(flow_promisc)) { 251 | perror("error"); 252 | fprintf(stderr, "Couldn't Destory promisc flow\n"); 253 | return FAILURE; 254 | } 255 | } 256 | #endif 257 | 258 | 259 | /* destroy flow */ 260 | #ifdef HAVE_RAW_ETH_EXP 261 | if (ibv_exp_destroy_flow(flow_create_result)) { 262 | #else 263 | if (ibv_destroy_flow(flow_create_result)) { 264 | #endif 265 | perror("error"); 266 | fprintf(stderr, "Couldn't Destory flow\n"); 267 | return FAILURE; 268 | } 269 | 270 | free(flow_rules); 271 | 272 | /* Deallocate all perftest resources. */ 273 | if (destroy_ctx(&ctx, &user_param)) { 274 | fprintf(stderr,"Failed to destroy_ctx\n"); 275 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 276 | return 1; 277 | } 278 | 279 | if (user_param.output == FULL_VERBOSITY) 280 | printf(RESULT_LINE); 281 | 282 | DEBUG_LOG(TRACE,"<<<<<<%s",__FUNCTION__); 283 | return 0; 284 | 285 | } 286 | -------------------------------------------------------------------------------- /src/read_bw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 | * 6 | * This software is available to you under a choice of one of two 7 | * licenses. You may choose to be licensed under the terms of the GNU 8 | * General Public License (GPL) Version 2, available from the file 9 | * COPYING in the main directory of this source tree, or the 10 | * OpenIB.org BSD license below: 11 | * 12 | * Redistribution and use in source and binary forms, with or 13 | * without modification, are permitted provided that the following 14 | * conditions are met: 15 | * 16 | * - Redistributions of source code must retain the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer. 19 | * 20 | * - Redistributions in binary form must reproduce the above 21 | * copyright notice, this list of conditions and the following 22 | * disclaimer in the documentation and/or other materials 23 | * provided with the distribution. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | * SOFTWARE. 33 | * 34 | * $Id$ 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "perftest_resources.h" 42 | #include "perftest_parameters.h" 43 | #include "perftest_communication.h" 44 | 45 | /****************************************************************************** 46 | * 47 | ******************************************************************************/ 48 | int main(int argc, char *argv[]) 49 | { 50 | int ret_parser,i = 0; 51 | struct ibv_device *ib_dev = NULL; 52 | struct pingpong_context ctx; 53 | struct pingpong_dest *my_dest = NULL; 54 | struct pingpong_dest *rem_dest = NULL; 55 | struct perftest_parameters user_param; 56 | struct perftest_comm user_comm; 57 | struct bw_report_data my_bw_rep, rem_bw_rep; 58 | 59 | /* init default values to user's parameters */ 60 | memset(&ctx,0,sizeof(struct pingpong_context)); 61 | memset(&user_param , 0 , sizeof(struct perftest_parameters)); 62 | memset(&user_comm,0,sizeof(struct perftest_comm)); 63 | 64 | user_param.verb = READ; 65 | user_param.tst = BW; 66 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 67 | 68 | ret_parser = parser(&user_param,argv,argc); 69 | if (ret_parser) { 70 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 71 | fprintf(stderr," Parser function exited with Error\n"); 72 | return 1; 73 | } 74 | 75 | if((user_param.connection_type == DC || user_param.use_xrc) && user_param.duplex) { 76 | user_param.num_of_qps *= 2; 77 | } 78 | 79 | ib_dev =ctx_find_dev(user_param.ib_devname); 80 | if (!ib_dev) 81 | return 7; 82 | 83 | /* Getting the relevant context from the device */ 84 | ctx.context = ibv_open_device(ib_dev); 85 | if (!ctx.context) { 86 | fprintf(stderr, " Couldn't get context for the device\n"); 87 | return 1; 88 | } 89 | 90 | /* See if MTU and link type are valid and supported. */ 91 | if (check_link(ctx.context,&user_param)) { 92 | fprintf(stderr, " Couldn't get context for the device\n"); 93 | return FAILURE; 94 | } 95 | 96 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 97 | if (create_comm_struct(&user_comm,&user_param)) { 98 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 99 | return 1; 100 | } 101 | 102 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 103 | printf("\n************************************\n"); 104 | printf("* Waiting for client to connect... *\n"); 105 | printf("************************************\n"); 106 | } 107 | 108 | /* Initialize the connection and print the local data. */ 109 | if (establish_connection(&user_comm)) { 110 | fprintf(stderr," Unable to init the socket connection\n"); 111 | return FAILURE; 112 | } 113 | 114 | exchange_versions(&user_comm, &user_param); 115 | 116 | check_sys_data(&user_comm, &user_param); 117 | 118 | /* See if MTU and link type are valid and supported. */ 119 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 120 | fprintf(stderr, " Couldn't get context for the device\n"); 121 | return FAILURE; 122 | } 123 | 124 | /* Print basic test information. */ 125 | ctx_print_test_info(&user_param); 126 | 127 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 128 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 129 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 130 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 131 | 132 | /* Allocating arrays needed for the test. */ 133 | alloc_ctx(&ctx,&user_param); 134 | 135 | /* Create (if nessacery) the rdma_cm ids and channel. */ 136 | if (user_param.work_rdma_cm == ON) { 137 | 138 | if (user_param.machine == CLIENT) { 139 | if (retry_rdma_connect(&ctx,&user_param)) { 140 | fprintf(stderr,"Unable to perform rdma_client function\n"); 141 | return FAILURE; 142 | } 143 | 144 | } else { 145 | if (create_rdma_resources(&ctx,&user_param)) { 146 | fprintf(stderr," Unable to create the rdma_resources\n"); 147 | return FAILURE; 148 | } 149 | if (rdma_server_connect(&ctx,&user_param)) { 150 | fprintf(stderr,"Unable to perform rdma_client function\n"); 151 | return FAILURE; 152 | } 153 | } 154 | 155 | } else { 156 | /* create all the basic IB resources. */ 157 | if (ctx_init(&ctx,&user_param)) { 158 | fprintf(stderr, " Couldn't create IB resources\n"); 159 | return FAILURE; 160 | } 161 | } 162 | 163 | /* Set up the Connection. */ 164 | if (set_up_connection(&ctx,&user_param,my_dest)) { 165 | fprintf(stderr," Unable to set up socket connection\n"); 166 | return FAILURE; 167 | } 168 | 169 | /* Print this machine QP information */ 170 | for (i=0; i < user_param.num_of_qps; i++) 171 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 172 | 173 | user_comm.rdma_params->side = REMOTE; 174 | 175 | for (i=0; i < user_param.num_of_qps; i++) { 176 | 177 | /* shaking hands and gather the other side info. */ 178 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 179 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 180 | return 1; 181 | } 182 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 183 | } 184 | 185 | if (user_param.work_rdma_cm == OFF) { 186 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 187 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 188 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 189 | return 1; 190 | } 191 | } 192 | 193 | if (user_param.work_rdma_cm == OFF) { 194 | 195 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 196 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 197 | return 1; 198 | } 199 | } 200 | 201 | /* An additional handshake is required after moving qp to RTR. */ 202 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 203 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 204 | return 1; 205 | } 206 | 207 | if (user_param.output == FULL_VERBOSITY) { 208 | if (user_param.report_per_port) { 209 | printf(RESULT_LINE_PER_PORT); 210 | printf((user_param.report_fmt == MBS ? RESULT_FMT_PER_PORT : RESULT_FMT_G_PER_PORT)); 211 | } 212 | else { 213 | printf(RESULT_LINE); 214 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 215 | } 216 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 217 | } 218 | 219 | /* For half duplex tests, server just waits for client to exit */ 220 | if (user_param.machine == SERVER && !user_param.duplex) { 221 | 222 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 223 | fprintf(stderr," Failed to exchange data between server and clients\n"); 224 | return FAILURE; 225 | } 226 | 227 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 228 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 229 | 230 | if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { 231 | fprintf(stderr,"Failed to close connection between server and client\n"); 232 | return 1; 233 | } 234 | if (user_param.output == FULL_VERBOSITY) { 235 | if (user_param.report_per_port) 236 | printf(RESULT_LINE_PER_PORT); 237 | else 238 | printf(RESULT_LINE); 239 | } 240 | 241 | if (user_param.work_rdma_cm == ON) { 242 | if (destroy_ctx(&ctx,&user_param)) { 243 | fprintf(stderr, "Failed to destroy resources\n"); 244 | return 1; 245 | } 246 | user_comm.rdma_params->work_rdma_cm = ON; 247 | return destroy_ctx(user_comm.rdma_ctx,user_comm.rdma_params); 248 | } 249 | 250 | return destroy_ctx(&ctx,&user_param); 251 | 252 | } 253 | 254 | if (user_param.use_event) { 255 | if (ibv_req_notify_cq(ctx.send_cq, 0)) { 256 | fprintf(stderr, "Couldn't request CQ notification\n"); 257 | return 1; 258 | } 259 | } 260 | 261 | if (user_param.test_method == RUN_ALL) { 262 | 263 | for (i = 1; i < 24 ; ++i) { 264 | 265 | user_param.size = (uint64_t)1 << i; 266 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 267 | 268 | if(perform_warm_up(&ctx,&user_param)) { 269 | fprintf(stderr,"Problems with warm up\n"); 270 | return 1; 271 | } 272 | 273 | if(user_param.duplex) { 274 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 275 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 276 | return 1; 277 | } 278 | } 279 | 280 | if(run_iter_bw(&ctx,&user_param)) 281 | return 17; 282 | 283 | if (user_param.duplex && (atof(user_param.version) >= 4.6)) { 284 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 285 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 286 | return 1; 287 | } 288 | } 289 | 290 | print_report_bw(&user_param,&my_bw_rep); 291 | 292 | if (user_param.duplex) { 293 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 294 | print_full_bw_report(&user_param, &my_bw_rep, &rem_bw_rep); 295 | } 296 | } 297 | 298 | } else if (user_param.test_method == RUN_REGULAR) { 299 | 300 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 301 | 302 | if(perform_warm_up(&ctx,&user_param)) { 303 | fprintf(stderr,"Problems with warm up\n"); 304 | return 1; 305 | } 306 | 307 | if(user_param.duplex) { 308 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 309 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 310 | return 1; 311 | } 312 | } 313 | 314 | if(run_iter_bw(&ctx,&user_param)) { 315 | fprintf(stderr," Failed to complete run_iter_bw function successfully\n"); 316 | return 1; 317 | } 318 | 319 | print_report_bw(&user_param,&my_bw_rep); 320 | 321 | if (user_param.duplex) { 322 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 323 | print_full_bw_report(&user_param, &my_bw_rep, &rem_bw_rep); 324 | } 325 | 326 | if (user_param.report_both && user_param.duplex) { 327 | printf(RESULT_LINE); 328 | printf("\n Local results: \n"); 329 | printf(RESULT_LINE); 330 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 331 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 332 | print_full_bw_report(&user_param, &my_bw_rep, NULL); 333 | printf(RESULT_LINE); 334 | 335 | printf("\n Remote results: \n"); 336 | printf(RESULT_LINE); 337 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 338 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 339 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 340 | } 341 | } else if (user_param.test_method == RUN_INFINITELY) { 342 | 343 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 344 | 345 | if(run_iter_bw_infinitely(&ctx,&user_param)) { 346 | fprintf(stderr," Error occured while running! aborting ...\n"); 347 | return 1; 348 | } 349 | } 350 | 351 | if (user_param.output == FULL_VERBOSITY) { 352 | if (user_param.report_per_port) 353 | printf(RESULT_LINE_PER_PORT); 354 | else 355 | printf(RESULT_LINE); 356 | } 357 | 358 | /* For half duplex tests, server just waits for client to exit */ 359 | if (user_param.machine == CLIENT && !user_param.duplex) { 360 | 361 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 362 | fprintf(stderr," Failed to exchange data between server and clients\n"); 363 | return FAILURE; 364 | } 365 | 366 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 367 | } 368 | 369 | if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { 370 | fprintf(stderr,"Failed to close connection between server and client\n"); 371 | return 1; 372 | } 373 | 374 | if (!user_param.is_bw_limit_passed && (user_param.is_limit_bw == ON ) ) { 375 | fprintf(stderr,"Error: BW result is below bw limit\n"); 376 | return 1; 377 | } 378 | 379 | if (!user_param.is_msgrate_limit_passed && (user_param.is_limit_bw == ON )) { 380 | fprintf(stderr,"Error: Msg rate is below msg_rate limit\n"); 381 | return 1; 382 | } 383 | 384 | if (user_param.work_rdma_cm == ON) { 385 | if (destroy_ctx(&ctx,&user_param)) { 386 | fprintf(stderr, "Failed to destroy resources\n"); 387 | return 1; 388 | } 389 | user_comm.rdma_params->work_rdma_cm = ON; 390 | return destroy_ctx(user_comm.rdma_ctx,user_comm.rdma_params); 391 | } 392 | 393 | return destroy_ctx(&ctx,&user_param); 394 | } 395 | -------------------------------------------------------------------------------- /src/read_lat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2005 Hewlett Packard, Inc (Grant Grundler) 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 | * 7 | * This software is available to you under a choice of one of two 8 | * licenses. You may choose to be licensed under the terms of the GNU 9 | * General Public License (GPL) Version 2, available from the file 10 | * COPYING in the main directory of this source tree, or the 11 | * OpenIB.org BSD license below: 12 | * 13 | * Redistribution and use in source and binary forms, with or 14 | * without modification, are permitted provided that the following 15 | * conditions are met: 16 | * 17 | * - Redistributions of source code must retain the above 18 | * copyright notice, this list of conditions and the following 19 | * disclaimer. 20 | * 21 | * - Redistributions in binary form must reproduce the above 22 | * copyright notice, this list of conditions and the following 23 | * disclaimer in the documentation and/or other materials 24 | * provided with the distribution. 25 | * 26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | * SOFTWARE. 34 | * 35 | * $Id$ 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "get_clock.h" 45 | #include "perftest_resources.h" 46 | #include "perftest_parameters.h" 47 | #include "perftest_communication.h" 48 | 49 | /****************************************************************************** 50 | * 51 | ******************************************************************************/ 52 | int main(int argc, char *argv[]) 53 | { 54 | int ret_parser,i = 0; 55 | struct report_options report; 56 | struct pingpong_context ctx; 57 | struct ibv_device *ib_dev; 58 | struct perftest_parameters user_param; 59 | struct pingpong_dest *my_dest = NULL; 60 | struct pingpong_dest *rem_dest = NULL; 61 | struct perftest_comm user_comm; 62 | 63 | /* init default values to user's parameters */ 64 | memset(&ctx,0,sizeof(struct pingpong_context)); 65 | memset(&user_param,0,sizeof(struct perftest_parameters)); 66 | memset(&user_comm,0,sizeof(struct perftest_comm)); 67 | 68 | user_param.verb = READ; 69 | user_param.tst = LAT; 70 | user_param.r_flag = &report; 71 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 72 | 73 | /* Configure the parameters values according to user arguments or defalut values. */ 74 | ret_parser = parser(&user_param,argv,argc); 75 | if (ret_parser) { 76 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 77 | fprintf(stderr," Parser function exited with Error\n"); 78 | return FAILURE; 79 | } 80 | 81 | if(user_param.use_xrc || user_param.connection_type == DC) { 82 | user_param.num_of_qps *= 2; 83 | } 84 | 85 | /* Finding the IB device selected (or defalut if no selected). */ 86 | ib_dev = ctx_find_dev(user_param.ib_devname); 87 | if (!ib_dev) { 88 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 89 | return FAILURE; 90 | } 91 | 92 | /* Getting the relevant context from the device */ 93 | ctx.context = ibv_open_device(ib_dev); 94 | if (!ctx.context) { 95 | fprintf(stderr, " Couldn't get context for the device\n"); 96 | return 1; 97 | } 98 | 99 | /* See if MTU and link type are valid and supported. */ 100 | if (check_link(ctx.context,&user_param)) { 101 | fprintf(stderr, " Couldn't get context for the device\n"); 102 | return FAILURE; 103 | } 104 | 105 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 106 | if (create_comm_struct(&user_comm,&user_param)) { 107 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 108 | return 1; 109 | } 110 | 111 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 112 | printf("\n************************************\n"); 113 | printf("* Waiting for client to connect... *\n"); 114 | printf("************************************\n"); 115 | } 116 | 117 | /* Initialize the connection and print the local data. */ 118 | if (establish_connection(&user_comm)) { 119 | fprintf(stderr," Unable to init the socket connection\n"); 120 | return FAILURE; 121 | } 122 | 123 | exchange_versions(&user_comm, &user_param); 124 | 125 | check_sys_data(&user_comm, &user_param); 126 | 127 | /* See if MTU and link type are valid and supported. */ 128 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 129 | fprintf(stderr, " Couldn't get context for the device\n"); 130 | return FAILURE; 131 | } 132 | 133 | /* Print basic test information. */ 134 | ctx_print_test_info(&user_param); 135 | 136 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 137 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 138 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 139 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 140 | 141 | /* Allocate arrays */ 142 | alloc_ctx(&ctx,&user_param); 143 | 144 | /* Create (if nessacery) the rdma_cm ids and channel. */ 145 | if (user_param.work_rdma_cm == ON) { 146 | 147 | if (user_param.machine == CLIENT) { 148 | if (retry_rdma_connect(&ctx,&user_param)) { 149 | fprintf(stderr,"Unable to perform rdma_client function\n"); 150 | return FAILURE; 151 | } 152 | 153 | } else { 154 | if (create_rdma_resources(&ctx,&user_param)) { 155 | fprintf(stderr," Unable to create the rdma_resources\n"); 156 | return FAILURE; 157 | } 158 | if (rdma_server_connect(&ctx,&user_param)) { 159 | fprintf(stderr,"Unable to perform rdma_client function\n"); 160 | return FAILURE; 161 | } 162 | } 163 | 164 | } else { 165 | 166 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 167 | if (ctx_init(&ctx,&user_param)) { 168 | fprintf(stderr, " Couldn't create IB resources\n"); 169 | return FAILURE; 170 | } 171 | } 172 | 173 | /* Set up the Connection. */ 174 | if (set_up_connection(&ctx,&user_param,my_dest)) { 175 | fprintf(stderr," Unable to set up socket connection\n"); 176 | return 1; 177 | } 178 | 179 | for (i=0; i < user_param.num_of_qps; i++) 180 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 181 | 182 | /* shaking hands and gather the other side info. */ 183 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 184 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 185 | return 1; 186 | } 187 | 188 | user_comm.rdma_params->side = REMOTE; 189 | for (i=0; i < user_param.num_of_qps; i++) { 190 | 191 | /* shaking hands and gather the other side info. */ 192 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 193 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 194 | return 1; 195 | } 196 | 197 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 198 | } 199 | 200 | if (user_param.work_rdma_cm == OFF) { 201 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 202 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 203 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 204 | return 1; 205 | } 206 | } 207 | 208 | if (user_param.work_rdma_cm == OFF) { 209 | 210 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 211 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 212 | return 1; 213 | } 214 | } 215 | 216 | /* An additional handshake is required after moving qp to RTR. */ 217 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 218 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 219 | return 1; 220 | } 221 | 222 | /* Only Client post read request. */ 223 | if (user_param.machine == SERVER) { 224 | 225 | if (ctx_close_connection(&user_comm,my_dest,rem_dest)) { 226 | fprintf(stderr,"Failed to close connection between server and client\n"); 227 | return 1; 228 | } 229 | if (user_param.output == FULL_VERBOSITY) { 230 | printf(RESULT_LINE); 231 | } 232 | return 0; 233 | 234 | } 235 | 236 | if (user_param.use_event) { 237 | if (ibv_req_notify_cq(ctx.send_cq, 0)) { 238 | fprintf(stderr, "Couldn't request CQ notification\n"); 239 | return 1; 240 | } 241 | } 242 | 243 | if (user_param.output == FULL_VERBOSITY) { 244 | printf(RESULT_LINE); 245 | printf("%s",(user_param.test_type == ITERATIONS) ? RESULT_FMT_LAT : RESULT_FMT_LAT_DUR); 246 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 247 | } 248 | 249 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 250 | 251 | if (user_param.test_method == RUN_ALL) { 252 | for (i = 1; i < 24 ; ++i) { 253 | user_param.size = (uint64_t)1 << i; 254 | if(run_iter_lat(&ctx,&user_param)) 255 | return 17; 256 | 257 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 258 | } 259 | } else { 260 | if(run_iter_lat(&ctx,&user_param)) 261 | return 18; 262 | 263 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 264 | } 265 | 266 | if (ctx_close_connection(&user_comm,my_dest,rem_dest)) { 267 | fprintf(stderr,"Failed to close connection between server and client\n"); 268 | return 1; 269 | } 270 | 271 | if (user_param.output == FULL_VERBOSITY) { 272 | printf(RESULT_LINE); 273 | } 274 | return 0; 275 | } 276 | -------------------------------------------------------------------------------- /src/send_lat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2005 Hewlett Packard, Inc (Grant Grundler) 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 | * 7 | * This software is available to you under a choice of one of two 8 | * licenses. You may choose to be licensed under the terms of the GNU 9 | * General Public License (GPL) Version 2, available from the file 10 | * COPYING in the main directory of this source tree, or the 11 | * OpenIB.org BSD license below: 12 | * 13 | * Redistribution and use in source and binary forms, with or 14 | * without modification, are permitted provided that the following 15 | * conditions are met: 16 | * 17 | * - Redistributions of source code must retain the above 18 | * copyright notice, this list of conditions and the following 19 | * disclaimer. 20 | * 21 | * - Redistributions in binary form must reproduce the above 22 | * copyright notice, this list of conditions and the following 23 | * disclaimer in the documentation and/or other materials 24 | * provided with the distribution. 25 | * 26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | * SOFTWARE. 34 | * 35 | * $Id$ 36 | */ 37 | 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "get_clock.h" 46 | #include "perftest_parameters.h" 47 | #include "perftest_resources.h" 48 | #include "multicast_resources.h" 49 | #include "perftest_communication.h" 50 | 51 | /****************************************************************************** 52 | * 53 | ******************************************************************************/ 54 | static int set_mcast_group(struct pingpong_context *ctx, 55 | struct perftest_parameters *user_param, 56 | struct mcast_parameters *mcg_params) 57 | { 58 | int i; 59 | struct ibv_port_attr port_attr; 60 | 61 | if (ibv_query_gid(ctx->context,user_param->ib_port,user_param->gid_index,&mcg_params->port_gid)) { 62 | return 1; 63 | } 64 | 65 | if (ibv_query_pkey(ctx->context,user_param->ib_port,DEF_PKEY_IDX,&mcg_params->pkey)) { 66 | return 1; 67 | } 68 | 69 | if (ibv_query_port(ctx->context,user_param->ib_port,&port_attr)) { 70 | return 1; 71 | } 72 | mcg_params->sm_lid = port_attr.sm_lid; 73 | mcg_params->sm_sl = port_attr.sm_sl; 74 | mcg_params->ib_port = user_param->ib_port; 75 | mcg_params->user_mgid = user_param->user_mgid; 76 | set_multicast_gid(mcg_params,ctx->qp[0]->qp_num,(int)user_param->machine); 77 | 78 | if (!strcmp(link_layer_str(user_param->link_type),"IB")) { 79 | /* Request for Mcast group create registery in SM. */ 80 | if (join_multicast_group(SUBN_ADM_METHOD_SET,mcg_params)) { 81 | fprintf(stderr," Failed to Join Mcast request\n"); 82 | return 1; 83 | } 84 | } 85 | 86 | for (i=0; i < user_param->num_of_qps; i++) { 87 | 88 | if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { 89 | fprintf(stderr, "Couldn't attach QP to MultiCast group"); 90 | return 1; 91 | } 92 | } 93 | mcg_params->mcast_state |= MCAST_IS_ATTACHED; 94 | 95 | return 0; 96 | } 97 | 98 | /****************************************************************************** 99 | * 100 | ******************************************************************************/ 101 | static int send_set_up_connection(struct pingpong_context *ctx, 102 | struct perftest_parameters *user_param, 103 | struct pingpong_dest *my_dest, 104 | struct mcast_parameters *mcg_params, 105 | struct perftest_comm *comm) 106 | { 107 | int i; 108 | 109 | if (set_up_connection(ctx,user_param,my_dest)) { 110 | fprintf(stderr," Unable to set up my IB connection parameters\n"); 111 | return FAILURE; 112 | } 113 | 114 | if (user_param->use_mcg && (user_param->duplex || user_param->machine == SERVER)) { 115 | 116 | mcg_params->user_mgid = user_param->user_mgid; 117 | set_multicast_gid(mcg_params,ctx->qp[0]->qp_num,(int)user_param->machine); 118 | if (set_mcast_group(ctx,user_param,mcg_params)) { 119 | return 1; 120 | } 121 | 122 | for (i=0; i < user_param->num_of_qps; i++) { 123 | if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { 124 | fprintf(stderr, "Couldn't attach QP to MultiCast group"); 125 | return 1; 126 | } 127 | } 128 | 129 | mcg_params->mcast_state |= MCAST_IS_ATTACHED; 130 | my_dest->gid = mcg_params->mgid; 131 | my_dest->lid = mcg_params->mlid; 132 | my_dest->qpn = QPNUM_MCAST; 133 | } 134 | 135 | return 0; 136 | } 137 | 138 | /****************************************************************************** 139 | * 140 | ******************************************************************************/ 141 | static int send_destroy_ctx(struct pingpong_context *ctx, 142 | struct perftest_parameters *user_param, 143 | struct mcast_parameters *mcg_params) 144 | { 145 | int i; 146 | if (user_param->use_mcg) { 147 | 148 | for (i=0; i < user_param->num_of_qps; i++) { 149 | if (ibv_detach_mcast(ctx->qp[i],&mcg_params->base_mgid,mcg_params->base_mlid)) { 150 | fprintf(stderr, "Couldn't dettach QP to MultiCast group\n"); 151 | return FAILURE; 152 | } 153 | } 154 | 155 | if (!strcmp(link_layer_str(user_param->link_type),"IB")) { 156 | 157 | if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { 158 | fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); 159 | return FAILURE; 160 | } 161 | 162 | memcpy(mcg_params->mgid.raw,mcg_params->base_mgid.raw,16); 163 | 164 | if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { 165 | fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); 166 | return FAILURE; 167 | } 168 | } 169 | } 170 | return destroy_ctx(ctx,user_param); 171 | } 172 | 173 | /****************************************************************************** 174 | * 175 | ******************************************************************************/ 176 | int main(int argc, char *argv[]) 177 | { 178 | int i = 0; 179 | int size_max_pow = 24; 180 | int ret_val; 181 | struct report_options report; 182 | struct pingpong_context ctx; 183 | struct pingpong_dest *my_dest = NULL; 184 | struct pingpong_dest *rem_dest = NULL; 185 | struct mcast_parameters mcg_params; 186 | struct ibv_device *ib_dev = NULL; 187 | struct perftest_parameters user_param; 188 | struct perftest_comm user_comm; 189 | 190 | /* init default values to user's parameters */ 191 | memset(&ctx, 0, sizeof(struct pingpong_context)); 192 | memset(&user_param, 0, sizeof(struct perftest_parameters)); 193 | memset(&user_comm , 0, sizeof(struct perftest_comm)); 194 | memset(&mcg_params, 0, sizeof(struct mcast_parameters)); 195 | 196 | user_param.verb = SEND; 197 | user_param.tst = LAT; 198 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 199 | user_param.r_flag = &report; 200 | 201 | /* Configure the parameters values according to user arguments or defalut values. */ 202 | ret_val = parser(&user_param,argv,argc); 203 | if (ret_val) { 204 | if (ret_val != VERSION_EXIT && ret_val != HELP_EXIT) 205 | fprintf(stderr," Parser function exited with Error\n"); 206 | return 1; 207 | } 208 | 209 | if(user_param.use_xrc || user_param.connection_type == DC) { 210 | user_param.num_of_qps *= 2; 211 | } 212 | 213 | /* Checking that the user did not run with RawEth. for this we have raw_etherent_bw test. */ 214 | if (user_param.connection_type == RawEth) { 215 | fprintf(stderr," This test cannot run Raw Ethernet QPs (you have chosen RawEth as connection type\n"); 216 | return FAILURE; 217 | } 218 | 219 | /* Finding the IB device selected (or defalut if no selected). */ 220 | ib_dev = ctx_find_dev(user_param.ib_devname); 221 | if (!ib_dev) { 222 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 223 | return 1; 224 | } 225 | 226 | if (user_param.use_mcg) 227 | GET_STRING(mcg_params.ib_devname,ibv_get_device_name(ib_dev)); 228 | 229 | /* Getting the relevant context from the device */ 230 | ctx.context = ibv_open_device(ib_dev); 231 | if (!ctx.context) { 232 | fprintf(stderr, " Couldn't get context for the device\n"); 233 | return 1; 234 | } 235 | 236 | /* See if MTU and link type are valid and supported. */ 237 | if (check_link(ctx.context,&user_param)) { 238 | fprintf(stderr, " Couldn't get context for the device\n"); 239 | return FAILURE; 240 | } 241 | 242 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 243 | if (create_comm_struct(&user_comm,&user_param)) { 244 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 245 | return 1; 246 | } 247 | 248 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 249 | printf("\n************************************\n"); 250 | printf("* Waiting for client to connect... *\n"); 251 | printf("************************************\n"); 252 | } 253 | 254 | /* Initialize the connection and print the local data. */ 255 | if (establish_connection(&user_comm)) { 256 | fprintf(stderr," Unable to init the socket connection\n"); 257 | return FAILURE; 258 | } 259 | 260 | exchange_versions(&user_comm, &user_param); 261 | 262 | check_sys_data(&user_comm, &user_param); 263 | 264 | /* See if MTU and link type are valid and supported. */ 265 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 266 | fprintf(stderr, " Couldn't get context for the device\n"); 267 | return FAILURE; 268 | } 269 | 270 | /* Print basic test information. */ 271 | ctx_print_test_info(&user_param); 272 | 273 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 274 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 275 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 276 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 277 | 278 | /* Allocating arrays needed for the test. */ 279 | alloc_ctx(&ctx,&user_param); 280 | 281 | /* Create (if nessacery) the rdma_cm ids and channel. */ 282 | if (user_param.work_rdma_cm == ON) { 283 | 284 | if (user_param.machine == CLIENT) { 285 | if (retry_rdma_connect(&ctx,&user_param)) { 286 | fprintf(stderr,"Unable to perform rdma_client function\n"); 287 | return FAILURE; 288 | } 289 | 290 | } else { 291 | if (create_rdma_resources(&ctx,&user_param)) { 292 | fprintf(stderr," Unable to create the rdma_resources\n"); 293 | return FAILURE; 294 | } 295 | if (rdma_server_connect(&ctx,&user_param)) { 296 | fprintf(stderr,"Unable to perform rdma_client function\n"); 297 | return FAILURE; 298 | } 299 | } 300 | 301 | } else { 302 | 303 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 304 | if (ctx_init(&ctx,&user_param)) { 305 | fprintf(stderr, " Couldn't create IB resources\n"); 306 | return FAILURE; 307 | } 308 | } 309 | 310 | /* Set up the Connection. */ 311 | if (send_set_up_connection(&ctx,&user_param,my_dest,&mcg_params,&user_comm)) { 312 | fprintf(stderr," Unable to set up socket connection\n"); 313 | return 1; 314 | } 315 | 316 | for (i=0; i < user_param.num_of_qps; i++) 317 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 318 | 319 | user_comm.rdma_params->side = REMOTE; 320 | for (i=0; i < user_param.num_of_qps; i++) { 321 | 322 | /* shaking hands and gather the other side info. */ 323 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 324 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 325 | return 1; 326 | } 327 | 328 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 329 | } 330 | 331 | if (user_param.work_rdma_cm == OFF) { 332 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 333 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 334 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 335 | return 1; 336 | } 337 | } 338 | 339 | if (user_param.use_mcg) { 340 | 341 | memcpy(mcg_params.base_mgid.raw,mcg_params.mgid.raw,16); 342 | memcpy(mcg_params.mgid.raw,rem_dest[0].gid.raw,16); 343 | mcg_params.base_mlid = mcg_params.mlid; 344 | mcg_params.is_2nd_mgid_used = ON; 345 | if (!strcmp(link_layer_str(user_param.link_type),"IB")) { 346 | /* Request for Mcast group create registery in SM. */ 347 | if (join_multicast_group(SUBN_ADM_METHOD_SET,&mcg_params)) { 348 | fprintf(stderr," Failed to Join Mcast request\n"); 349 | return 1; 350 | } 351 | } 352 | 353 | /* 354 | * The next stall in code (50 ms sleep) is a work around for fixing the 355 | * the bug this test had in Multicast for the past 1 year. 356 | * It appears, that when a switch involved, it takes ~ 10 ms for the join 357 | * request to propogate on the IB fabric, thus we need to wait for it. 358 | * what happened before this fix was reaching the post_send 359 | * code segment in about 350 ns from here, and the switch(es) dropped 360 | * the packet because join request wasn't finished. 361 | */ 362 | usleep(50000); 363 | } 364 | 365 | if (user_param.work_rdma_cm == OFF) { 366 | 367 | /* Prepare IB resources for rtr/rts. */ 368 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 369 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 370 | return 1; 371 | } 372 | } 373 | 374 | /* shaking hands and gather the other side info. */ 375 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 376 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 377 | return 1; 378 | } 379 | 380 | if (user_param.use_event) { 381 | 382 | if (ibv_req_notify_cq(ctx.send_cq, 0)) { 383 | fprintf(stderr, "Couldn't request RCQ notification\n"); 384 | return 1; 385 | } 386 | 387 | if (ibv_req_notify_cq(ctx.recv_cq, 0)) { 388 | fprintf(stderr, "Couldn't request RCQ notification\n"); 389 | return 1; 390 | } 391 | } 392 | if (user_param.output == FULL_VERBOSITY) { 393 | printf(RESULT_LINE); 394 | printf("%s",(user_param.test_type == ITERATIONS) ? RESULT_FMT_LAT : RESULT_FMT_LAT_DUR); 395 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 396 | } 397 | 398 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 399 | 400 | if (user_param.test_method == RUN_ALL) { 401 | 402 | if (user_param.connection_type == UD) 403 | size_max_pow = (int)UD_MSG_2_EXP(MTU_SIZE(user_param.curr_mtu)) + 1; 404 | 405 | for (i = 1; i < size_max_pow ; ++i) { 406 | 407 | user_param.size = (uint64_t)1 << i; 408 | 409 | /* Post receive recv_wqes fo current message size */ 410 | if (ctx_set_recv_wqes(&ctx,&user_param)) { 411 | fprintf(stderr," Failed to post receive recv_wqes\n"); 412 | return 1; 413 | } 414 | 415 | /* Sync between the client and server so the client won't send packets 416 | * Before the server has posted his receive wqes (in UC/UD it will result in a deadlock). 417 | */ 418 | 419 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 420 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 421 | return 1; 422 | } 423 | 424 | if(run_iter_lat_send(&ctx, &user_param)) 425 | return 17; 426 | 427 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 428 | } 429 | 430 | } else { 431 | 432 | /* Post recevie recv_wqes fo current message size */ 433 | if (ctx_set_recv_wqes(&ctx,&user_param)) { 434 | fprintf(stderr," Failed to post receive recv_wqes\n"); 435 | return 1; 436 | } 437 | 438 | /* Sync between the client and server so the client won't send packets 439 | * Before the server has posted his receive wqes (in UC/UD it will result in a deadlock). 440 | */ 441 | 442 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 443 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 444 | return 1; 445 | } 446 | 447 | if(run_iter_lat_send(&ctx, &user_param)) 448 | return 17; 449 | 450 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 451 | } 452 | 453 | if (user_param.output == FULL_VERBOSITY) { 454 | printf(RESULT_LINE); 455 | } 456 | 457 | if (ctx_close_connection(&user_comm,my_dest,rem_dest)) { 458 | fprintf(stderr,"Failed to close connection between server and client\n"); 459 | fprintf(stderr," Trying to close this side resources\n"); 460 | } 461 | 462 | return send_destroy_ctx(&ctx,&user_param,&mcg_params); 463 | } 464 | -------------------------------------------------------------------------------- /src/write_bw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 | * 6 | * This software is available to you under a choice of one of two 7 | * licenses. You may choose to be licensed under the terms of the GNU 8 | * General Public License (GPL) Version 2, available from the file 9 | * COPYING in the main directory of this source tree, or the 10 | * OpenIB.org BSD license below: 11 | * 12 | * Redistribution and use in source and binary forms, with or 13 | * without modification, are permitted provided that the following 14 | * conditions are met: 15 | * 16 | * - Redistributions of source code must retain the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer. 19 | * 20 | * - Redistributions in binary form must reproduce the above 21 | * copyright notice, this list of conditions and the following 22 | * disclaimer in the documentation and/or other materials 23 | * provided with the distribution. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | * SOFTWARE. 33 | * 34 | * $Id$ 35 | */ 36 | 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include "perftest_parameters.h" 43 | #include "perftest_resources.h" 44 | #include "perftest_communication.h" 45 | 46 | /****************************************************************************** 47 | ******************************************************************************/ 48 | int main(int argc, char *argv[]) 49 | { 50 | int ret_parser,i = 0; 51 | struct ibv_device *ib_dev = NULL; 52 | struct pingpong_context ctx; 53 | struct pingpong_dest *my_dest,*rem_dest; 54 | struct perftest_parameters user_param; 55 | struct perftest_comm user_comm; 56 | struct bw_report_data my_bw_rep, rem_bw_rep; 57 | 58 | /* init default values to user's parameters */ 59 | memset(&user_param,0,sizeof(struct perftest_parameters)); 60 | memset(&user_comm,0,sizeof(struct perftest_comm)); 61 | memset(&ctx,0,sizeof(struct pingpong_context)); 62 | 63 | user_param.verb = WRITE; 64 | user_param.tst = BW; 65 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 66 | 67 | /* Configure the parameters values according to user arguments or default values. */ 68 | ret_parser = parser(&user_param,argv,argc); 69 | if (ret_parser) { 70 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 71 | fprintf(stderr," Parser function exited with Error\n"); 72 | return 1; 73 | } 74 | 75 | if((user_param.connection_type == DC || user_param.use_xrc) && user_param.duplex) { 76 | user_param.num_of_qps *= 2; 77 | } 78 | 79 | /* Finding the IB device selected (or default if none is selected). */ 80 | ib_dev = ctx_find_dev(user_param.ib_devname); 81 | if (!ib_dev) { 82 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 83 | return 1; 84 | } 85 | 86 | /* Getting the relevant context from the device */ 87 | ctx.context = ibv_open_device(ib_dev); 88 | if (!ctx.context) { 89 | fprintf(stderr, " Couldn't get context for the device\n"); 90 | return 1; 91 | } 92 | 93 | /* See if MTU and link type are valid and supported. */ 94 | if (check_link(ctx.context,&user_param)) { 95 | fprintf(stderr, " Couldn't get context for the device\n"); 96 | return FAILURE; 97 | } 98 | 99 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 100 | if (create_comm_struct(&user_comm,&user_param)) { 101 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 102 | return 1; 103 | } 104 | 105 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 106 | printf("\n************************************\n"); 107 | printf("* Waiting for client to connect... *\n"); 108 | printf("************************************\n"); 109 | } 110 | 111 | /* Initialize the connection and print the local data. */ 112 | if (establish_connection(&user_comm)) { 113 | fprintf(stderr," Unable to init the socket connection\n"); 114 | return FAILURE; 115 | } 116 | sleep(1); 117 | exchange_versions(&user_comm, &user_param); 118 | 119 | check_sys_data(&user_comm, &user_param); 120 | 121 | /* See if MTU and link type are valid and supported. */ 122 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 123 | fprintf(stderr, " Couldn't get context for the device\n"); 124 | return FAILURE; 125 | } 126 | 127 | /* Print basic test information. */ 128 | ctx_print_test_info(&user_param); 129 | 130 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 131 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 132 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 133 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 134 | 135 | /* Allocating arrays needed for the test. */ 136 | alloc_ctx(&ctx,&user_param); 137 | 138 | /* Create (if necessary) the rdma_cm ids and channel. */ 139 | if (user_param.work_rdma_cm == ON) { 140 | 141 | if (user_param.machine == CLIENT) { 142 | if (retry_rdma_connect(&ctx,&user_param)) { 143 | fprintf(stderr,"Unable to perform rdma_client function\n"); 144 | return FAILURE; 145 | } 146 | 147 | } else { 148 | if (create_rdma_resources(&ctx,&user_param)) { 149 | fprintf(stderr," Unable to create the rdma_resources\n"); 150 | return FAILURE; 151 | } 152 | if (rdma_server_connect(&ctx,&user_param)) { 153 | fprintf(stderr,"Unable to perform rdma_client function\n"); 154 | return FAILURE; 155 | } 156 | } 157 | 158 | } else { 159 | 160 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 161 | if (ctx_init(&ctx, &user_param)) { 162 | fprintf(stderr, " Couldn't create IB resources\n"); 163 | return FAILURE; 164 | } 165 | } 166 | 167 | /* Set up the Connection. */ 168 | if (set_up_connection(&ctx,&user_param,my_dest)) { 169 | fprintf(stderr," Unable to set up socket connection\n"); 170 | return FAILURE; 171 | } 172 | 173 | /* Print this machine QP information */ 174 | for (i=0; i < user_param.num_of_qps; i++) 175 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 176 | 177 | 178 | user_comm.rdma_params->side = REMOTE; 179 | for (i=0; i < user_param.num_of_qps; i++) { 180 | 181 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 182 | fprintf(stderr," Failed to exchange data between server and clients\n"); 183 | return 1; 184 | } 185 | 186 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 187 | } 188 | 189 | if (user_param.work_rdma_cm == OFF) { 190 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 191 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 192 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 193 | return 1; 194 | } 195 | } 196 | 197 | if (user_param.work_rdma_cm == OFF) { 198 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 199 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 200 | return FAILURE; 201 | } 202 | } 203 | 204 | /* An additional handshake is required after moving qp to RTR. */ 205 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 206 | fprintf(stderr," Failed to exchange data between server and clients\n"); 207 | return FAILURE; 208 | } 209 | 210 | if (user_param.output == FULL_VERBOSITY) { 211 | if (user_param.report_per_port) { 212 | printf(RESULT_LINE_PER_PORT); 213 | printf((user_param.report_fmt == MBS ? RESULT_FMT_PER_PORT : RESULT_FMT_G_PER_PORT)); 214 | } 215 | else { 216 | printf(RESULT_LINE); 217 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 218 | } 219 | 220 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 221 | } 222 | 223 | /* For half duplex tests, server just waits for client to exit */ 224 | if (user_param.machine == SERVER && !user_param.duplex) { 225 | 226 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 227 | fprintf(stderr," Failed to exchange data between server and clients\n"); 228 | return FAILURE; 229 | } 230 | 231 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 232 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 233 | 234 | if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { 235 | fprintf(stderr,"Failed to close connection between server and client\n"); 236 | return 1; 237 | } 238 | 239 | if (user_param.output == FULL_VERBOSITY) { 240 | if (user_param.report_per_port) 241 | printf(RESULT_LINE_PER_PORT); 242 | else 243 | printf(RESULT_LINE); 244 | } 245 | 246 | if (user_param.work_rdma_cm == ON) { 247 | if (destroy_ctx(&ctx,&user_param)) { 248 | fprintf(stderr, "Failed to destroy resources\n"); 249 | return 1; 250 | } 251 | user_comm.rdma_params->work_rdma_cm = ON; 252 | return destroy_ctx(user_comm.rdma_ctx,user_comm.rdma_params); 253 | } 254 | 255 | return destroy_ctx(&ctx,&user_param); 256 | } 257 | 258 | if (user_param.test_method == RUN_ALL) { 259 | 260 | for (i = 1; i < 24 ; ++i) { 261 | 262 | user_param.size = (uint64_t)1 << i; 263 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 264 | 265 | if(perform_warm_up(&ctx,&user_param)) { 266 | fprintf(stderr,"Problems with warm up\n"); 267 | return 1; 268 | } 269 | 270 | if(user_param.duplex) { 271 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 272 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 273 | return 1; 274 | } 275 | } 276 | 277 | if(run_iter_bw(&ctx,&user_param)) { 278 | fprintf(stderr," Failed to complete run_iter_bw function successfully\n"); 279 | return 1; 280 | } 281 | 282 | if (user_param.duplex && (atof(user_param.version) >= 4.6)) { 283 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 284 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 285 | return 1; 286 | } 287 | } 288 | 289 | print_report_bw(&user_param,&my_bw_rep); 290 | 291 | if (user_param.duplex) { 292 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 293 | print_full_bw_report(&user_param, &my_bw_rep, &rem_bw_rep); 294 | } 295 | } 296 | 297 | } else if (user_param.test_method == RUN_REGULAR) { 298 | 299 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 300 | 301 | if (user_param.verb != SEND) { 302 | if(perform_warm_up(&ctx,&user_param)) { 303 | fprintf(stderr,"Problems with warm up\n"); 304 | return 1; 305 | } 306 | } 307 | 308 | if(user_param.duplex) { 309 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 310 | fprintf(stderr,"Failed to sync between server and client between different msg sizes\n"); 311 | return 1; 312 | } 313 | } 314 | 315 | if(run_iter_bw(&ctx,&user_param)) { 316 | fprintf(stderr," Failed to complete run_iter_bw function successfully\n"); 317 | return 1; 318 | } 319 | 320 | print_report_bw(&user_param,&my_bw_rep); 321 | 322 | if (user_param.duplex) { 323 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 324 | print_full_bw_report(&user_param, &my_bw_rep, &rem_bw_rep); 325 | } 326 | 327 | if (user_param.report_both && user_param.duplex) { 328 | printf(RESULT_LINE); 329 | printf("\n Local results: \n"); 330 | printf(RESULT_LINE); 331 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 332 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 333 | print_full_bw_report(&user_param, &my_bw_rep, NULL); 334 | printf(RESULT_LINE); 335 | 336 | printf("\n Remote results: \n"); 337 | printf(RESULT_LINE); 338 | printf((user_param.report_fmt == MBS ? RESULT_FMT : RESULT_FMT_G)); 339 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 340 | print_full_bw_report(&user_param, &rem_bw_rep, NULL); 341 | } 342 | } else if (user_param.test_method == RUN_INFINITELY) { 343 | 344 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 345 | 346 | if(run_iter_bw_infinitely(&ctx,&user_param)) { 347 | fprintf(stderr," Error occured while running infinitely! aborting ...\n"); 348 | return 1; 349 | } 350 | } 351 | 352 | if (user_param.output == FULL_VERBOSITY) { 353 | if (user_param.report_per_port) 354 | printf(RESULT_LINE_PER_PORT); 355 | else 356 | printf(RESULT_LINE); 357 | } 358 | 359 | /* For half duplex tests, server just waits for client to exit */ 360 | if (user_param.machine == CLIENT && !user_param.duplex) { 361 | 362 | if (ctx_hand_shake(&user_comm,&my_dest[0],&rem_dest[0])) { 363 | fprintf(stderr," Failed to exchange data between server and clients\n"); 364 | return FAILURE; 365 | } 366 | 367 | xchg_bw_reports(&user_comm, &my_bw_rep,&rem_bw_rep,atof(user_param.rem_version)); 368 | } 369 | 370 | /* Closing connection. */ 371 | if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { 372 | fprintf(stderr,"Failed to close connection between server and client\n"); 373 | return 1; 374 | } 375 | 376 | if (!user_param.is_bw_limit_passed && (user_param.is_limit_bw == ON ) ) { 377 | fprintf(stderr,"Error: BW result is below bw limit\n"); 378 | return 1; 379 | } 380 | 381 | if (!user_param.is_msgrate_limit_passed && (user_param.is_limit_bw == ON )) { 382 | fprintf(stderr,"Error: Msg rate is below msg_rate limit\n"); 383 | return 1; 384 | } 385 | 386 | free(my_dest); 387 | free(rem_dest); 388 | 389 | if (user_param.work_rdma_cm == ON) { 390 | if (destroy_ctx(&ctx,&user_param)) { 391 | fprintf(stderr, "Failed to destroy resources\n"); 392 | return 1; 393 | } 394 | user_comm.rdma_params->work_rdma_cm = ON; 395 | return destroy_ctx(user_comm.rdma_ctx,user_comm.rdma_params); 396 | } 397 | 398 | return destroy_ctx(&ctx,&user_param); 399 | } 400 | -------------------------------------------------------------------------------- /src/write_lat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4 | * Copyright (c) 2005 Hewlett Packard, Inc (Grant Grundler) 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 | * 7 | * This software is available to you under a choice of one of two 8 | * licenses. You may choose to be licensed under the terms of the GNU 9 | * General Public License (GPL) Version 2, available from the file 10 | * COPYING in the main directory of this source tree, or the 11 | * OpenIB.org BSD license below: 12 | * 13 | * Redistribution and use in source and binary forms, with or 14 | * without modification, are permitted provided that the following 15 | * conditions are met: 16 | * 17 | * - Redistributions of source code must retain the above 18 | * copyright notice, this list of conditions and the following 19 | * disclaimer. 20 | * 21 | * - Redistributions in binary form must reproduce the above 22 | * copyright notice, this list of conditions and the following 23 | * disclaimer in the documentation and/or other materials 24 | * provided with the distribution. 25 | * 26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | * SOFTWARE. 34 | * 35 | * $Id$ 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "get_clock.h" 45 | #include "perftest_parameters.h" 46 | #include "perftest_resources.h" 47 | #include "perftest_communication.h" 48 | 49 | /****************************************************************************** 50 | * 51 | ******************************************************************************/ 52 | int main(int argc, char *argv[]) 53 | { 54 | int ret_parser,i = 0; 55 | struct report_options report; 56 | struct pingpong_context ctx; 57 | struct pingpong_dest *my_dest = NULL; 58 | struct pingpong_dest *rem_dest = NULL; 59 | struct ibv_device *ib_dev; 60 | struct perftest_parameters user_param; 61 | struct perftest_comm user_comm; 62 | 63 | /* init default values to user's parameters */ 64 | memset(&ctx,0,sizeof(struct pingpong_context)); 65 | memset(&user_param, 0, sizeof(struct perftest_parameters)); 66 | memset(&user_comm,0,sizeof(struct perftest_comm)); 67 | 68 | user_param.verb = WRITE; 69 | user_param.tst = LAT; 70 | user_param.r_flag = &report; 71 | strncpy(user_param.version, VERSION, sizeof(user_param.version)); 72 | 73 | /* Configure the parameters values according to user arguments or defalut values. */ 74 | ret_parser = parser(&user_param,argv,argc); 75 | if (ret_parser) { 76 | if (ret_parser != VERSION_EXIT && ret_parser != HELP_EXIT) 77 | fprintf(stderr," Parser function exited with Error\n"); 78 | return FAILURE; 79 | } 80 | 81 | if(user_param.use_xrc || user_param.connection_type == DC) { 82 | user_param.num_of_qps *= 2; 83 | } 84 | 85 | /* Finding the IB device selected (or defalut if no selected). */ 86 | ib_dev = ctx_find_dev(user_param.ib_devname); 87 | if (!ib_dev) { 88 | fprintf(stderr," Unable to find the Infiniband/RoCE device\n"); 89 | return FAILURE; 90 | } 91 | 92 | /* Getting the relevant context from the device */ 93 | ctx.context = ibv_open_device(ib_dev); 94 | if (!ctx.context) { 95 | fprintf(stderr, " Couldn't get context for the device\n"); 96 | return 1; 97 | } 98 | 99 | /* See if MTU and link type are valid and supported. */ 100 | if (check_link(ctx.context,&user_param)) { 101 | fprintf(stderr, " Couldn't get context for the device\n"); 102 | return FAILURE; 103 | } 104 | 105 | /* copy the relevant user parameters to the comm struct + creating rdma_cm resources. */ 106 | if (create_comm_struct(&user_comm,&user_param)) { 107 | fprintf(stderr," Unable to create RDMA_CM resources\n"); 108 | return 1; 109 | } 110 | 111 | if (user_param.output == FULL_VERBOSITY && user_param.machine == SERVER) { 112 | printf("\n************************************\n"); 113 | printf("* Waiting for client to connect... *\n"); 114 | printf("************************************\n"); 115 | } 116 | 117 | /* Initialize the connection and print the local data. */ 118 | if (establish_connection(&user_comm)) { 119 | fprintf(stderr," Unable to init the socket connection\n"); 120 | return FAILURE; 121 | } 122 | 123 | exchange_versions(&user_comm, &user_param); 124 | 125 | check_sys_data(&user_comm, &user_param); 126 | 127 | /* See if MTU and link type are valid and supported. */ 128 | if (check_mtu(ctx.context,&user_param, &user_comm)) { 129 | fprintf(stderr, " Couldn't get context for the device\n"); 130 | return FAILURE; 131 | } 132 | 133 | /* Print basic test information. */ 134 | ctx_print_test_info(&user_param); 135 | 136 | ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); 137 | memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 138 | ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); 139 | memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); 140 | 141 | /* Allocating arrays needed for the test. */ 142 | alloc_ctx(&ctx,&user_param); 143 | 144 | /* Create (if nessacery) the rdma_cm ids and channel. */ 145 | if (user_param.work_rdma_cm == ON) { 146 | 147 | if (user_param.machine == CLIENT) { 148 | if (retry_rdma_connect(&ctx,&user_param)) { 149 | fprintf(stderr,"Unable to perform rdma_client function\n"); 150 | return FAILURE; 151 | } 152 | 153 | } else { 154 | if (create_rdma_resources(&ctx,&user_param)) { 155 | fprintf(stderr," Unable to create the rdma_resources\n"); 156 | return FAILURE; 157 | } 158 | if (rdma_server_connect(&ctx,&user_param)) { 159 | fprintf(stderr,"Unable to perform rdma_client function\n"); 160 | return FAILURE; 161 | } 162 | } 163 | 164 | } else { 165 | 166 | /* create all the basic IB resources (data buffer, PD, MR, CQ and events channel) */ 167 | if (ctx_init(&ctx,&user_param)) { 168 | fprintf(stderr, " Couldn't create IB resources\n"); 169 | return FAILURE; 170 | } 171 | } 172 | 173 | /* Set up the Connection. */ 174 | if (set_up_connection(&ctx,&user_param,my_dest)) { 175 | fprintf(stderr," Unable to set up socket connection\n"); 176 | return 1; 177 | } 178 | 179 | for (i=0; i < user_param.num_of_qps; i++) 180 | ctx_print_pingpong_data(&my_dest[i],&user_comm); 181 | 182 | /* shaking hands and gather the other side info. */ 183 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 184 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 185 | return 1; 186 | } 187 | 188 | user_comm.rdma_params->side = REMOTE; 189 | for (i=0; i < user_param.num_of_qps; i++) { 190 | 191 | /* shaking hands and gather the other side info. */ 192 | if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { 193 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 194 | return 1; 195 | } 196 | 197 | ctx_print_pingpong_data(&rem_dest[i],&user_comm); 198 | }; 199 | 200 | if (user_param.work_rdma_cm == OFF) { 201 | if (ctx_check_gid_compatibility(&my_dest[0], &rem_dest[0])) { 202 | fprintf(stderr,"\n Found Incompatibility issue with GID types.\n"); 203 | fprintf(stderr," Please Try to use a different IP version.\n\n"); 204 | return 1; 205 | } 206 | } 207 | 208 | if (user_param.work_rdma_cm == OFF) { 209 | if (ctx_connect(&ctx,rem_dest,&user_param,my_dest)) { 210 | fprintf(stderr," Unable to Connect the HCA's through the link\n"); 211 | return 1; 212 | } 213 | } 214 | 215 | /* An additional handshake is required after moving qp to RTR. */ 216 | if (ctx_hand_shake(&user_comm,my_dest,rem_dest)) { 217 | fprintf(stderr,"Failed to exchange data between server and clients\n"); 218 | return 1; 219 | } 220 | 221 | ctx_set_send_wqes(&ctx,&user_param,rem_dest); 222 | 223 | if (user_param.output == FULL_VERBOSITY) { 224 | printf(RESULT_LINE); 225 | printf("%s",(user_param.test_type == ITERATIONS) ? RESULT_FMT_LAT : RESULT_FMT_LAT_DUR); 226 | printf((user_param.cpu_util_data.enable ? RESULT_EXT_CPU_UTIL : RESULT_EXT)); 227 | } 228 | 229 | if (user_param.test_method == RUN_ALL) { 230 | 231 | for (i = 1; i < 24 ; ++i) { 232 | user_param.size = (uint64_t)1 << i; 233 | if(run_iter_lat_write(&ctx,&user_param)) { 234 | fprintf(stderr,"Test exited with Error\n"); 235 | return FAILURE; 236 | } 237 | 238 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 239 | } 240 | 241 | } else { 242 | 243 | if(run_iter_lat_write(&ctx,&user_param)) { 244 | fprintf(stderr,"Test exited with Error\n"); 245 | return FAILURE; 246 | } 247 | user_param.test_type == ITERATIONS ? print_report_lat(&user_param) : print_report_lat_duration(&user_param); 248 | } 249 | 250 | if (user_param.output == FULL_VERBOSITY) { 251 | printf(RESULT_LINE); 252 | } 253 | return 0; 254 | } 255 | --------------------------------------------------------------------------------