Files
mckernel/test/rusage/verbs/ud.c
2017-09-20 19:48:32 +09:00

256 lines
9.6 KiB
C
Executable File

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>
#include "ibcomm.h"
#include "debug.h"
#include "mtype.h"
#include "mm_ib_test.h"
//#define DEBUG_UD
#ifdef DEBUG_UD
#define dprintf printf
#else
#define dprintf(...)
#endif
#define MAX2(x,y) ((x) > (y) ? (x) : (y))
#define SERVER_BUF_NUM TEST_SERVER_BUF_NUM
#define NTRIAL 120
#define PPOLLS 10 /* sweet spot is around 10 */
#define NSKIPS (PPOLLS*1)
#define PPOLLR 10 /* sweet spot is around 10 */
#define NSKIPR (PPOLLR*1)
static unsigned long rdtsc() {
unsigned long x;
__asm__ __volatile__("xorl %%eax, %%eax; cpuid;" : : : "%rax", "%rbx", "%rcx", "%rdx"); /* rdtsc cannot be executed earlier than this */
__asm__ __volatile__("rdtsc; shl $32, %%rdx; or %%rdx, %%rax" : "=a"(x) : : "memory"); /* rdtsc cannot be executed earlier than here */
__asm__ __volatile__("xorl %%eax, %%eax; cpuid;" : : : "%rax", "%rbx", "%rcx", "%rdx"); /* following instructions cannot be executed earlier than this */
return x;
}
int main(int argc, char **argv) {
config_t config;
int i, j, k;
char sync_res;
resource_t res;
pdinfo_t pdinfo;
qpinfo_t qpinfo;
mrinfo_t *mrinfo_send_list = NULL, *mrinfo_recv_list = NULL;
int ibv_errno, ibcom_errno, verbs_errno = 0;
unsigned long tscs, tsce, tscs2, tsce2;
FILE* fp;
fp = popen("cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
if(!fp) { printf("popen failed\n"); goto fn_fail; }
char freq_str[256];
int nread = fread(freq_str, sizeof(char), 256, fp);
if(!nread) { printf("popen failed"); goto fn_fail; }
freq_str[nread] = 0;
long int freq = strtol(freq_str, NULL, 10) * 1000;
printf("freq=%ld\n", freq);
pclose(fp);
ibcom_errno = read_config(&config, argc, argv);
if(ibcom_errno) { printf("read_config\n"); goto fn_fail; }
ibcom_errno = resource_create(config, &res);
if(ibcom_errno) { printf("resource_create\n"); goto fn_fail; }
ibcom_errno = pd_create(&res, &pdinfo);
if(ibcom_errno) { printf("pd_create\n"); goto fn_fail; }
ibcom_errno = qp_create_ud(&res, &pdinfo, &qpinfo);
if(ibcom_errno) { printf("qp_create_ud\n"); goto fn_fail; }
ibcom_errno = init_qp_ud(config, &qpinfo);
if(ibcom_errno) { printf("init_qp_ud\n"); goto fn_fail; }
/* prepare local lid, gid, qpn, qkey */
qp_conn_info_ud_t local_conn_info, remote_conn_info;
struct ibv_port_attr port_attr; /* IB port attributes */
ibv_errno = ibv_query_port(res.ib_ctx, config.ib_port, &port_attr);
VERBS_ERR_CHKANDJUMP(ibv_errno, -1, printf("ibv_query_port on port %u failed\n", config.ib_port));
local_conn_info.lid = port_attr.lid;
ibv_errno = ibv_query_gid(res.ib_ctx, config.ib_port, 0, (union ibv_gid*)&local_conn_info.gid);
VERBS_ERR_CHKANDJUMP(ibv_errno, -1, printf("could not get gid for port %d, index 0\n", config.ib_port));
local_conn_info.qp_num = qpinfo.qp->qp_num;
local_conn_info.qkey = 0x11111111;
/* send local connection info and obtain remote one */
int listenfd = config.server_flg ? -1 : 0;
int fd = sock_connect(config.server_name, config.tcp_port, &listenfd);
if(fd < 0) { error_perror("sock_connect"); goto fn_fail; }
if(config.server_flg) {
dprintf("server,fd=%d\n", fd);
} else {
dprintf("client,fd=%d\n", fd);
}
ibcom_errno = sock_sync_data(fd, sizeof(qp_conn_info_ud_t), (char*)&local_conn_info, (char*)&remote_conn_info);
if(ibcom_errno) { error_perror("sock_sync_data"); goto fn_fail; }
/* print local and remote connection info */
dprintf("local lid=%08x,qpn=%08x,qkey=%08x\n", local_conn_info.lid, local_conn_info.qp_num, local_conn_info.qkey);
dprintf("local gid=");
for(i = 0; i < 16; i++) { dprintf("%02x", local_conn_info.gid.raw[i]); }
dprintf("\n");
dprintf("remote lid=%08x,qpn=%08x,qkey=%08x\n", remote_conn_info.lid, remote_conn_info.qp_num, remote_conn_info.qkey);
dprintf("remote gid=");
for(i = 0; i < 16; i++) { dprintf("%02x", remote_conn_info.gid.raw[i]); }
dprintf("\n");
/* ibv_reg_mr */
mrinfo_recv_list = malloc(sizeof(mrinfo_t) * SERVER_BUF_NUM);
for (i = 0; i < SERVER_BUF_NUM; i++) {
char *buf = malloc(config.buf_size * sizeof(char));
if(!buf) { fprintf(stderr, "cannot malloc %dth buf\n", i); goto fn_fail; }
for(j = 0; j < config.buf_size; j++) {
buf[j] = -j & 0xff;
}
ibcom_errno = mr_create(&res, &pdinfo, config.buf_size, buf, &mrinfo_recv_list[i]);
VERBS_ERR_CHKANDJUMP(ibcom_errno, -1, printf("mr_create\n"));
}
mrinfo_send_list = malloc(sizeof(mrinfo_t) * NTRIAL);
for (i = 0; i < NTRIAL; i++) {
char *buf = malloc(config.buf_size * sizeof(char));
if (!buf) { printf("cannot malloc %dth buf\n", i); goto fn_fail; }
for(j = 0; j < config.buf_size; j++) {
buf[j] = j & 0xff;
}
ibcom_errno = mr_create(&res, &pdinfo, config.buf_size, buf, &mrinfo_send_list[i]);
if(ibcom_errno) { printf("mr_create\n"); goto fn_fail; }
}
/* ibv_modify_qp */
ibcom_errno = rtr_qp_ud(config, &qpinfo);
if(ibcom_errno) { printf("rtr\n"); goto fn_fail; }
ibcom_errno = rts_qp_ud(config, &qpinfo);
if(ibcom_errno) { printf("rts\n"); goto fn_fail; }
print_qp_status(&qpinfo);
/* prepare address header (1/2, ibv_ah_attr) */
struct ibv_ah_attr ah_attr;
memset(&ah_attr, 0, sizeof(struct ibv_ah_attr));
ah_attr.dlid = remote_conn_info.lid;
ah_attr.sl = 0;
ah_attr.src_path_bits = 0;
ah_attr.static_rate = 0; /* not limit on static rate (100% port speed) */
ah_attr.is_global = 0;
ah_attr.port_num = config.ib_port;
#if 0
ah_attr.is_global = 1;
ah_attr.grh.dgid = remote_conn_info.gid;
ah_attr.grh.flow_label = 0;
ah_attr.grh.sgid_index = 0; /* what is this? */
ah_attr.grh.hop_limit = 1;
ah_attr.grh.traffic_class = 0;
#endif
/* prepare address header (2/2, ibv_ah) */
struct ibv_ah *ah;
ah = ibv_create_ah(pdinfo.pd, &ah_attr);
if(!ah) { printf("ibv_crate_ah\n"); goto fn_fail; }
/* pre-post receive commands */
VERBS_ERR_CHKANDJUMP(_MAX_RQ_CAPACITY < NTRIAL, -1, printf("Increase _MAX_RQ_CAPACITY,_MAX_RQ_CAPACITY=%d,NTRIAL=%d\n", _MAX_RQ_CAPACITY, NTRIAL));
if(!config.server_flg) {
for(i = 0; i < NTRIAL; i++){
ibcom_errno = post_recv_req_ud(&qpinfo, &mrinfo_recv_list[0], 0x1234ULL);
if(ibcom_errno) { printf("post_recv_req_ud\n"); goto fn_fail; }
}
}
/* barrier */
for(i = 0; i < (config.server_flg ? config.nremote : 1); i++) {
sock_sync_data(qpinfo.sock[i], 1, "R", &sync_res);
}
/* barrier */
for(i = 0; i < (config.server_flg ? config.nremote : 1); i++) {
sock_sync_data(qpinfo.sock[i], 1, "R", &sync_res);
}
if(config.server_flg) { // sender side
usleep(1000000);
if(NTRIAL % PPOLLS != 0) { printf("set NTRIAL multiple of PPOLLS\n"); goto fn_fail; }
if(NTRIAL <= NSKIPS) { printf("set NTRIAL > NSKIP\n"); goto fn_fail; }
for(i = 0; i < NTRIAL; i++) {
if(i == NSKIPS) { tscs = rdtsc(); }
ibcom_errno = post_send_req_ud(&qpinfo, &mrinfo_send_list[0], IBV_WR_SEND, &remote_conn_info, ah);
if(ibcom_errno) { printf("post_send_req_ud\n"); goto fn_fail; }
#if 1
int nfound = 0;
if(i % PPOLLS == PPOLLS - 1) {
k = 0;
while(1) {
int result;
struct ibv_wc cqe[PPOLLS];
result = ibv_poll_cq(qpinfo.scq, PPOLLS, &cqe[0]);
if(result < 0) { printf("ibv_poll_cq"); goto fn_fail; }
if(result > 0) {
for(j = 0; j < result; j++) {
if(cqe[j].status != IBV_WC_SUCCESS) { printf("cqe status\n"); goto fn_fail; }
}
//debug_print_mem((unsigned long long)mrinfo_send_list[i].buf, config.buf_size);
nfound += result;
if(nfound == PPOLLS) { break; }
}
k++;
}
}
#endif
}
tsce = rdtsc(); printf("send,%.0f\n", (tsce-tscs)/(double)(NTRIAL-NSKIPS));
} else { // receiver side
if(NSKIPR % PPOLLR !=0) { printf("set NSKIP multiple of PPOLL\n"); goto fn_fail; }
for(i = 0; i< NTRIAL; i++){
if(i == NSKIPR) { tscs = rdtsc(); }
//tscs2 = rdtsc();
#if 0
ibv_errno = ibv_query_port(res.ib_ctx, config.ib_port, &port_attr);
VERBS_ERR_CHKANDJUMP(ibv_errno, -1, printf("ibv_query_port on port %u failed\n", config.ib_port));
printf("bad_pkey_cntr=%d,%d\n", port_attr.bad_pkey_cntr, port_attr.qkey_viol_cntr);
#endif
/* poll CQ */
int nfound = 0;
if(i % PPOLLR == PPOLLR - 1) {
k = 0;
while(1) {
int ib_errno, result;
struct ibv_wc cqe[PPOLLR];
result = ibv_poll_cq(qpinfo.rcq, 1, &cqe[0]);
if(result < 0) { printf("poll_cq\n"); goto fn_fail; }
if(result > 0) {
for(j = 0; j < result; j++) {
if(cqe[j].status != IBV_WC_SUCCESS) { printf("cqe.status"); goto fn_fail; }
}
printf("wr_id=%lx\n", cqe[0].wr_id);
//tsce2 = rdtsc(); printf("received,%ld\n", tsce2 - tscs2);
nfound += result;
if(nfound == PPOLLR) { break; }
}
k++;
}
}
}
tsce = rdtsc(); printf("recv,%.0f\n", (tsce-tscs)/(double)(NTRIAL-NSKIPR));
}
fn_exit:
return verbs_errno;
fn_fail:
goto fn_exit;
}