diff --git a/kernel/ibv.c b/kernel/ibv.c index 1ee41d3a7..7f4698131 100644 --- a/kernel/ibv.c +++ b/kernel/ibv.c @@ -987,7 +987,7 @@ typedef struct { void ibv_free_device_list(struct ibv_device ** list) { uhyve_ibv_free_device_list_t uhyve_args; - // TODO: Take care of ** parameter. + uhyve_args.list = list; uhyve_send(UHYVE_PORT_IBV_FREE_DEVICE_LIST, (unsigned) virt_to_phys((size_t) &uhyve_args)); } @@ -1560,10 +1560,10 @@ typedef struct { struct ibv_cq * ibv_create_cq(struct ibv_context * context, int cqe, void * cq_context, struct ibv_comp_channel * channel, int comp_vector) { uhyve_ibv_create_cq_t uhyve_args; - uhyve_args.context = context; - uhyve_args.cqe = cqe; - uhyve_args.cq_context = cq_context; - uhyve_args.channel = channel; + uhyve_args.context = context; + uhyve_args.cqe = cqe; + uhyve_args.cq_context = cq_context; + uhyve_args.channel = channel; uhyve_args.comp_vector = comp_vector; uhyve_send(UHYVE_PORT_IBV_CREATE_CQ, (unsigned) virt_to_phys((size_t) &uhyve_args)); @@ -1654,9 +1654,9 @@ typedef struct { int ibv_get_cq_event(struct ibv_comp_channel * channel, struct ibv_cq ** cq, void ** cq_context) { uhyve_ibv_get_cq_event_t uhyve_args; - uhyve_args.channel = channel; - // TODO: Take care of ** parameter. - // TODO: Take care of ** parameter. + uhyve_args.channel = channel; + uhyve_args.cq = (struct ibv_cq **) guest_to_host((size_t) cq); // created in user space + uhyve_args.cq_context = (void **) guest_to_host((size_t) cq_context); // created in user space uhyve_send(UHYVE_PORT_IBV_GET_CQ_EVENT, (unsigned) virt_to_phys((size_t) &uhyve_args)); diff --git a/tools/uhyve-ibv.c b/tools/uhyve-ibv.c index e829165df..5c91fd741 100644 --- a/tools/uhyve-ibv.c +++ b/tools/uhyve-ibv.c @@ -879,7 +879,7 @@ void call_ibv_destroy_cq(struct kvm_run * run, uint8_t * guest_mem) { */ void call_ibv_get_cq_event(struct kvm_run * run, uint8_t * guest_mem) { - printf("LOG: UHYVE - call_ibv_get_cq_event\n"); + printf("get_cq_event "); unsigned data = *((unsigned*) ((size_t) run + run->io.data_offset)); uhyve_ibv_get_cq_event_t * args = (uhyve_ibv_get_cq_event_t *) (guest_mem + data); @@ -925,7 +925,7 @@ void call_ibv_poll_cq(struct kvm_run * run, uint8_t * guest_mem) { */ void call_ibv_req_notify_cq(struct kvm_run * run, uint8_t * guest_mem) { - printf("LOG: UHYVE - call_ibv_req_notify_cq\n"); + printf("req_notify_cq "); unsigned data = *((unsigned*) ((size_t) run + run->io.data_offset)); uhyve_ibv_req_notify_cq_t * args = (uhyve_ibv_req_notify_cq_t *) (guest_mem + data); diff --git a/usr/benchmarks/ib/evaluation/config.py b/usr/benchmarks/ib/evaluation/config.py index bd29b1ccb..629ad7902 100644 --- a/usr/benchmarks/ib/evaluation/config.py +++ b/usr/benchmarks/ib/evaluation/config.py @@ -4,16 +4,16 @@ BENCHMARKS = ['ib_write_bw', 'ib_write_lat', 'ib_read_bw', 'ib_read_lat'] +OPTIONS = ['-a --post_list 1'] # BENCHMARKS = ['ib_write_lat', # 'ib_read_bw', # 'ib_read_lat'] -OPTIONS = ['-a --post_list 1'] -# BENCHMARKS = ['ib_write_bw'] # OPTIONS = ['-a --post_list 4', # '-a --post_list 16'] +# BENCHMARKS = ['ib_write_bw'] # OPTIONS = ['-a --post_list 1', # '-a --post_list 4', # '-a --post_list 16'] diff --git a/usr/benchmarks/ib/evaluation/final2/ib_read_bw-avg.pdf b/usr/benchmarks/ib/evaluation/final2/ib_read_bw-avg.pdf index 2f38962b9..edb49ebfe 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/ib_read_bw-avg.pdf and b/usr/benchmarks/ib/evaluation/final2/ib_read_bw-avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/ib_read_lat-t_typical.pdf b/usr/benchmarks/ib/evaluation/final2/ib_read_lat-t_typical.pdf index 9d0e942d4..962d69dd9 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/ib_read_lat-t_typical.pdf and b/usr/benchmarks/ib/evaluation/final2/ib_read_lat-t_typical.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/ib_write_bw-avg.pdf b/usr/benchmarks/ib/evaluation/final2/ib_write_bw-avg.pdf index d8bab41bc..c7c62ccbf 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/ib_write_bw-avg.pdf and b/usr/benchmarks/ib/evaluation/final2/ib_write_bw-avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/ib_write_lat-t_typical.pdf b/usr/benchmarks/ib/evaluation/final2/ib_write_lat-t_typical.pdf index 96e15e323..cb1f1db50 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/ib_write_lat-t_typical.pdf and b/usr/benchmarks/ib/evaluation/final2/ib_write_lat-t_typical.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-msg_rate.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-msg_rate.pdf index 998ba5253..926f42ece 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-msg_rate.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-msg_rate.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-peak.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-peak.pdf index 6ba2088c1..d062036b4 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-peak.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_bw-peak.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99.pdf index 9f11e9c60..c42fc7ffd 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99_9.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99_9.pdf index 99d7ef71f..18731fba7 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99_9.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-percentile_99_9.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-s_stddev.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-s_stddev.pdf index 184041638..3106a042f 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-s_stddev.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-s_stddev.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_avg.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_avg.pdf index 682c4d4cb..8b13b8b3c 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_avg.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_max.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_max.pdf index f7144a5a2..daa7ca1ca 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_max.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_max.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_min.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_min.pdf index 2cda134f1..bfcdd98d7 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_min.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_read_lat-t_min.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-msg_rate.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-msg_rate.pdf index fd6560cac..8f1bbba4e 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-msg_rate.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-msg_rate.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-peak.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-peak.pdf index 5af8be294..2f3099840 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-peak.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_bw-peak.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99.pdf index d9f0e3ea9..1441f80b9 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99_9.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99_9.pdf index 4c3bcea3d..7128f407b 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99_9.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-percentile_99_9.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-s_stddev.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-s_stddev.pdf index bff983d9c..751e50f24 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-s_stddev.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-s_stddev.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_avg.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_avg.pdf index 99f487485..b90ed1c5c 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_avg.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_max.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_max.pdf index 5be67225d..decd102c0 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_max.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_max.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_min.pdf b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_min.pdf index 87b4177a3..67d723d1b 100644 Binary files a/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_min.pdf and b/usr/benchmarks/ib/evaluation/final2/others/ib_write_lat-t_min.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-avg.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-avg.pdf new file mode 100644 index 000000000..bb2fbd93d Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-msg_rate.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-msg_rate.pdf new file mode 100644 index 000000000..1e465abc6 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-msg_rate.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-peak.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-peak.pdf new file mode 100644 index 000000000..5d2100622 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_bw-peak.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99.pdf new file mode 100644 index 000000000..412de9141 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99_9.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99_9.pdf new file mode 100644 index 000000000..3048540b9 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-percentile_99_9.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-s_stddev.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-s_stddev.pdf new file mode 100644 index 000000000..9cd2cdfc3 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-s_stddev.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_avg.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_avg.pdf new file mode 100644 index 000000000..b9e902635 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_max.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_max.pdf new file mode 100644 index 000000000..588c4f0a3 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_max.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_min.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_min.pdf new file mode 100644 index 000000000..fe2edce6e Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_min.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_typical.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_typical.pdf new file mode 100644 index 000000000..2f129968b Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_read_lat-t_typical.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg-MULTI.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg-MULTI.pdf new file mode 100644 index 000000000..126bf3250 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg-MULTI.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg.pdf new file mode 100644 index 000000000..891917dcd Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate-MULTI.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate-MULTI.pdf new file mode 100644 index 000000000..4b8266e4a Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate-MULTI.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate.pdf new file mode 100644 index 000000000..f7acae473 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-msg_rate.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak-MULTI.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak-MULTI.pdf new file mode 100644 index 000000000..45d042e71 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak-MULTI.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak.pdf new file mode 100644 index 000000000..75b5ccdcf Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_bw-peak.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99.pdf new file mode 100644 index 000000000..1682c34ca Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99_9.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99_9.pdf new file mode 100644 index 000000000..6cd3abb3f Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-percentile_99_9.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-s_stddev.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-s_stddev.pdf new file mode 100644 index 000000000..2501d5b45 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-s_stddev.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_avg.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_avg.pdf new file mode 100644 index 000000000..c18317485 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_avg.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_max.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_max.pdf new file mode 100644 index 000000000..ca1951ad5 Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_max.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_min.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_min.pdf new file mode 100644 index 000000000..f3b6d237b Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_min.pdf differ diff --git a/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_typical.pdf b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_typical.pdf new file mode 100644 index 000000000..44c5a1e7d Binary files /dev/null and b/usr/benchmarks/ib/evaluation/final2/plot_ib_write_lat-t_typical.pdf differ diff --git a/usr/benchmarks/ib/evaluation/parse_results.py b/usr/benchmarks/ib/evaluation/parse_results.py index 4d782bb0e..f4d4cb92b 100644 --- a/usr/benchmarks/ib/evaluation/parse_results.py +++ b/usr/benchmarks/ib/evaluation/parse_results.py @@ -9,8 +9,9 @@ from matplotlib import pyplot as plt from config import BENCHMARKS, TIMESTAMP, OPTIONS matplotlib.rcParams['font.family'] = 'serif' +matplotlib.rcParams['font.size'] = 15 matplotlib.rcParams['mathtext.default'] = 'regular' -matplotlib.rcParams['xtick.major.pad'] = '8' # TODO: do this separately +matplotlib.rcParams['xtick.major.pad'] = '12' # TODO: do this separately # matplotlib.rcParams['font.sans-serif'] = ['Tahoma'] # matplotlib.rcParams['figure.figsize'] = 30, 10 @@ -112,7 +113,7 @@ def plot_results(results, directory): for bm in BENCHMARKS: for metric in (bw_metrics[2:] if 'bw' in bm else lat_metrics[2:]): - file_name = bm + '-' + metric + ('-MULTI' if len(num_wrs_list) > 1 else '') + '.pdf' + file_name = 'plot_' + bm + '-' + metric + ('-MULTI' if len(num_wrs_list) > 1 else '') + '.pdf' file_path = os.path.join(directory, file_name) fig, ax = plt.subplots(figsize=(10, 5)) @@ -125,18 +126,21 @@ def plot_results(results, directory): # Axis ticks and scale (x: log2 / y: log2 for latency) ax.set_xscale('log', basex=2) - ax.set_xticks(np.power(2, range( - 1, len(results['native'][bm][num_wrs_list[0]]['num_bytes']) + 1))) + num_data_points = len(results['hermit'][bm][num_wrs_list[0]]['num_bytes']) + ax.set_xticks(np.power(2, range(1, num_data_points + 1))) if 'lat' in bm: + ax.set_ylim(bottom = 0.5, top = 256) + # y_ticks = np.power(2, range(-1, 8)) + # ax.set_yticks(y_ticks, [(str(int(tick)) if tick >= 1 else str(tick)) for tick in y_ticks]) ax.set_yscale('log', basey=2) ax.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) # Plot, save and then clear figure for num_wrs in num_wrs_list: - label_end = ' (' + num_wrs + ' work request' + \ + label_end = ' (' + num_wrs + ' WR' + \ (')' if num_wrs is '1' else 's)') if len(num_wrs_list) > 1 else "" - ax.plot(results['native'][bm][num_wrs]['num_bytes'], - results['native'][bm][num_wrs][metric], + ax.plot(results['native'][bm][num_wrs]['num_bytes'][:20], + results['native'][bm][num_wrs][metric][:20], 'o-', color = line_color['native'][num_wrs], label = 'Native' + label_end, linewidth = 2, markersize = 6) label = 'HermitCore (' + num_wrs + ' work requests)' @@ -145,7 +149,7 @@ def plot_results(results, directory): 'o-', color = line_color['hermit'][num_wrs], label = 'HermitCore' + label_end, linewidth = 2, markersize = 6) - plt.legend(fontsize = 10, ncol = 3, loc = 'lower right', + plt.legend(fontsize = 12, ncol = 3, loc = 'lower right', bbox_to_anchor = [1, 1.05]) plt.savefig(file_path, bbox_inches = 'tight') diff --git a/usr/tests/CMakeLists.txt b/usr/tests/CMakeLists.txt index dabc786c9..35aefb392 100644 --- a/usr/tests/CMakeLists.txt +++ b/usr/tests/CMakeLists.txt @@ -10,10 +10,8 @@ add_executable(hello++ hello++.cpp) add_executable(hellof hellof.f90) add_executable(pi pi.go) -add_executable(ib-test ib-test.c) #add_executable(ib-pingpong ib/pingpong.c ib/pingpong.h ib/pingpong-ud.c) -add_executable(ib-pingpong ib/pingpong.c ib/pingpong-ud.c) -#target_link_libraries(ib-test ibverbs) +add_executable(ib-rc-pingpong ib/pingpong.c ib/rc_pingpong.c) add_executable(test-malloc test-malloc.c) add_executable(test-malloc-mt test-malloc-mt.c) diff --git a/usr/tests/ib-test.c b/usr/tests/ib-test.c deleted file mode 100644 index 9d9e83033..000000000 --- a/usr/tests/ib-test.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017, Annika Wierichs, RWTH Aachen University - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include // Geht per cmake copy workaround - - -int main(int argc, char** argv) -{ - int i, random; - int num_devices; - - printf("\t\tib-test.c: before get dev list.\n"); - struct ibv_device ** dev_list = ibv_get_device_list(&num_devices); - printf("\t\tib-test.c: after get device list -- ib-test.c: num devices: %d \n", num_devices); - printf("\t\tib-test.c: dev_list ptr: %p\n", dev_list); - /* printf("after get device list -- ib-test.c: ptr 1: %p\n", dev_list[0]); */ - /* printf("after get device list -- ib-test.c: ptr 2: %p\n", dev_list[1]); */ - /* printf("\t\tafter get device list -- ib-test.c: name 1: %s\n", dev_list[0]->name); */ - /* printf("\t\tafter get device list -- ib-test.c: name 2: %s\n", dev_list[1]->name); */ - - printf("\t\tib-test.c: before get device name loop.\n"); - for (int i=0; i < num_devices; i++) { - const char* dev_name = ibv_get_device_name(dev_list[i]); - printf("\t\tib-test.c: after get device name -- Device name %d: %s\n", i, dev_name); - } - - printf("\t\tib-test.c: before open_device\n"); - struct ibv_context * context = ibv_open_device(dev_list[0]); - printf("\t\tib-test.c: after open device\n"); - - return 0; -} - diff --git a/usr/tests/ib/pingpong-ud.c b/usr/tests/ib/pingpong-ud.c deleted file mode 100644 index 70a02809c..000000000 --- a/usr/tests/ib/pingpong-ud.c +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright (c) 2005 Topspin Communications. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define _GNU_SOURCE -/*#include */ - -// #include -// #include -/* #include */ -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#include - -#include "pingpong.h" - -enum { - PINGPONG_RECV_WRID = 1, - PINGPONG_SEND_WRID = 2, -}; - -static int page_size; - -struct pingpong_context { - struct ibv_context *context; - struct ibv_comp_channel *channel; - struct ibv_pd *pd; - struct ibv_mr *mr; - struct ibv_cq *cq; - struct ibv_qp *qp; - struct ibv_ah *ah; - void *buf; - int size; - int send_flags; - int rx_depth; - int pending; - struct ibv_port_attr portinfo; -}; - -struct pingpong_dest { - int lid; - int qpn; - int psn; - union ibv_gid gid; -}; - -/*static int pp_connect_ctx(struct pingpong_context *ctx, int port, int my_psn,*/ - /*int sl, struct pingpong_dest *dest, int sgid_idx)*/ -/*{*/ - /*struct ibv_ah_attr ah_attr = {*/ - /*.is_global = 0,*/ - /*.dlid = dest->lid,*/ - /*.sl = sl,*/ - /*.src_path_bits = 0,*/ - /*.port_num = port*/ - /*};*/ - /*struct ibv_qp_attr attr = {*/ - /*.qp_state = IBV_QPS_RTR*/ - /*};*/ - - /*if (ibv_modify_qp(ctx->qp, &attr, IBV_QP_STATE)) {*/ - /*fprintf(stderr, "Failed to modify QP to RTR\n");*/ - /*return 1;*/ - /*}*/ - - /*attr.qp_state = IBV_QPS_RTS;*/ - /*attr.sq_psn = my_psn;*/ - - /*if (ibv_modify_qp(ctx->qp, &attr,*/ - /*IBV_QP_STATE |*/ - /*IBV_QP_SQ_PSN)) {*/ - /*fprintf(stderr, "Failed to modify QP to RTS\n");*/ - /*return 1;*/ - /*}*/ - - /*if (dest->gid.global.interface_id) {*/ - /*ah_attr.is_global = 1;*/ - /*ah_attr.grh.hop_limit = 1;*/ - /*ah_attr.grh.dgid = dest->gid;*/ - /*ah_attr.grh.sgid_index = sgid_idx;*/ - /*}*/ - - /*ctx->ah = ibv_create_ah(ctx->pd, &ah_attr);*/ - /*if (!ctx->ah) {*/ - /*fprintf(stderr, "Failed to create AH\n");*/ - /*return 1;*/ - /*}*/ - - /*return 0;*/ -/*}*/ - -/*static struct pingpong_dest *pp_client_exch_dest(const char *servername, int port,*/ - /*const struct pingpong_dest *my_dest)*/ -/*{*/ - /*struct addrinfo *res, *t;*/ - /*struct addrinfo hints = {*/ - /*.ai_family = AF_UNSPEC,*/ - /*.ai_socktype = SOCK_STREAM*/ - /*};*/ - /*char *service;*/ - /*char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"];*/ - /*int n;*/ - /*int sockfd = -1;*/ - /*struct pingpong_dest *rem_dest = NULL;*/ - /*char gid[33];*/ - - /*if (asprintf(&service, "%d", port) < 0)*/ - /*return NULL;*/ - - /*n = getaddrinfo(servername, service, &hints, &res);*/ - - /*if (n < 0) {*/ - /*fprintf(stderr, "%s for %s:%d\n", gai_strerror(n), servername, port);*/ - /*free(service);*/ - /*return NULL;*/ - /*}*/ - - /*for (t = res; t; t = t->ai_next) {*/ - /*sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);*/ - /*if (sockfd >= 0) {*/ - /*if (!connect(sockfd, t->ai_addr, t->ai_addrlen))*/ - /*break;*/ - /*close(sockfd);*/ - /*sockfd = -1;*/ - /*}*/ - /*}*/ - - /*freeaddrinfo(res);*/ - /*free(service);*/ - - /*if (sockfd < 0) {*/ - /*fprintf(stderr, "Couldn't connect to %s:%d\n", servername, port);*/ - /*return NULL;*/ - /*}*/ - - /*gid_to_wire_gid(&my_dest->gid, gid);*/ - /*sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn,*/ - /*my_dest->psn, gid);*/ - /*if (write(sockfd, msg, sizeof msg) != sizeof msg) {*/ - /*fprintf(stderr, "Couldn't send local address\n");*/ - /*goto out;*/ - /*}*/ - - /*if (read(sockfd, msg, sizeof msg) != sizeof msg ||*/ - /*write(sockfd, "done", sizeof "done") != sizeof "done") {*/ - /*perror("client read/write");*/ - /*fprintf(stderr, "Couldn't read/write remote address\n");*/ - /*goto out;*/ - /*}*/ - - /*rem_dest = malloc(sizeof *rem_dest);*/ - /*if (!rem_dest)*/ - /*goto out;*/ - - /*sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn,*/ - /*&rem_dest->psn, gid);*/ - /*wire_gid_to_gid(gid, &rem_dest->gid);*/ - -/*out:*/ - /*close(sockfd);*/ - /*return rem_dest;*/ -/*}*/ - -/*static struct pingpong_dest *pp_server_exch_dest(struct pingpong_context *ctx,*/ - /*int ib_port, int port, int sl,*/ - /*const struct pingpong_dest *my_dest,*/ - /*int sgid_idx)*/ -/*{*/ - /*struct addrinfo *res, *t;*/ - /*struct addrinfo hints = {*/ - /*.ai_flags = AI_PASSIVE,*/ - /*.ai_family = AF_UNSPEC,*/ - /*.ai_socktype = SOCK_STREAM*/ - /*};*/ - /*char *service;*/ - /*char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"];*/ - /*int n;*/ - /*int sockfd = -1, connfd;*/ - /*struct pingpong_dest *rem_dest = NULL;*/ - /*char gid[33];*/ - - /*if (asprintf(&service, "%d", port) < 0)*/ - /*return NULL;*/ - - /*n = getaddrinfo(NULL, service, &hints, &res);*/ - - /*if (n < 0) {*/ - /*fprintf(stderr, "%s for port %d\n", gai_strerror(n), port);*/ - /*free(service);*/ - /*return NULL;*/ - /*}*/ - - /*for (t = res; t; t = t->ai_next) {*/ - /*sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);*/ - /*if (sockfd >= 0) {*/ - /*n = 1;*/ - - /*setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n);*/ - - /*if (!bind(sockfd, t->ai_addr, t->ai_addrlen))*/ - /*break;*/ - /*close(sockfd);*/ - /*sockfd = -1;*/ - /*}*/ - /*}*/ - - /*freeaddrinfo(res);*/ - /*free(service);*/ - - /*if (sockfd < 0) {*/ - /*fprintf(stderr, "Couldn't listen to port %d\n", port);*/ - /*return NULL;*/ - /*}*/ - - /*listen(sockfd, 1);*/ - /*connfd = accept(sockfd, NULL, NULL);*/ - /*close(sockfd);*/ - /*if (connfd < 0) {*/ - /*fprintf(stderr, "accept() failed\n");*/ - /*return NULL;*/ - /*}*/ - - /*n = read(connfd, msg, sizeof msg);*/ - /*if (n != sizeof msg) {*/ - /*perror("server read");*/ - /*fprintf(stderr, "%d/%d: Couldn't read remote address\n", n, (int) sizeof msg);*/ - /*goto out;*/ - /*}*/ - - /*rem_dest = malloc(sizeof *rem_dest);*/ - /*if (!rem_dest)*/ - /*goto out;*/ - - /*sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn,*/ - /*&rem_dest->psn, gid);*/ - /*wire_gid_to_gid(gid, &rem_dest->gid);*/ - - /*if (pp_connect_ctx(ctx, ib_port, my_dest->psn, sl, rem_dest,*/ - /*sgid_idx)) {*/ - /*fprintf(stderr, "Couldn't connect to remote QP\n");*/ - /*free(rem_dest);*/ - /*rem_dest = NULL;*/ - /*goto out;*/ - /*}*/ - - /*gid_to_wire_gid(&my_dest->gid, gid);*/ - /*sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn,*/ - /*my_dest->psn, gid);*/ - /*if (write(connfd, msg, sizeof msg) != sizeof msg ||*/ - /*read(connfd, msg, sizeof msg) != sizeof "done") {*/ - /*fprintf(stderr, "Couldn't send/recv local address\n");*/ - /*free(rem_dest);*/ - /*rem_dest = NULL;*/ - /*goto out;*/ - /*}*/ -/*out:*/ - /*close(connfd);*/ - /*return rem_dest;*/ -/*}*/ - -static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, - int rx_depth, int port, - int use_event) -{ - printf("LOG: PINGPONG - pp_init_ctx\n"); - struct pingpong_context *ctx; - - printf("LOG: PINGPONG - pp_init_ctx\n"); - ctx = malloc(sizeof *ctx); - if (!ctx) - return NULL; - - ctx->size = size; - ctx->send_flags = IBV_SEND_SIGNALED; - ctx->rx_depth = rx_depth; - - printf("LOG: PINGPONG - pp_init_ctx\n"); - ctx->buf = memalign(page_size, size + 40); - if (!ctx->buf) { - fprintf(stderr, "Couldn't allocate work buf.\n"); - goto clean_ctx; - } - - /* FIXME memset(ctx->buf, 0, size + 40); */ - memset(ctx->buf, 0x7b, size + 40); - - printf("LOG: PINGPONG - pp_init_ctx\n"); - ctx->context = ibv_open_device(ib_dev); - if (!ctx->context) { - fprintf(stderr, "Couldn't get context for %s\n", - ibv_get_device_name(ib_dev)); - goto clean_buffer; - } - - printf("LOG: PINGPONG - pp_init_ctx\n"); - { - struct ibv_port_attr port_info = {}; - int mtu; - - if (ibv_query_port(ctx->context, port, &port_info)) { - fprintf(stderr, "Unable to query port info for port %d\n", port); - goto clean_device; - } - mtu = 1 << (port_info.active_mtu + 7); - if (size > mtu) { - fprintf(stderr, "Requested size larger than port MTU (%d)\n", mtu); - goto clean_device; - } - } - - printf("LOG: PINGPONG - pp_init_ctx\n"); - if (use_event) { - ctx->channel = ibv_create_comp_channel(ctx->context); - if (!ctx->channel) { - fprintf(stderr, "Couldn't create completion channel\n"); - goto clean_device; - } - } else - ctx->channel = NULL; - - /*ctx->pd = ibv_alloc_pd(ctx->context);*/ - /*if (!ctx->pd) {*/ - /*fprintf(stderr, "Couldn't allocate PD\n");*/ - /*goto clean_comp_channel;*/ - /*}*/ - - /*ctx->mr = ibv_reg_mr(ctx->pd, ctx->buf, size + 40, IBV_ACCESS_LOCAL_WRITE);*/ - /*if (!ctx->mr) {*/ - /*fprintf(stderr, "Couldn't register MR\n");*/ - /*goto clean_pd;*/ - /*}*/ - - /*ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL,*/ - /*ctx->channel, 0);*/ - /*if (!ctx->cq) {*/ - /*fprintf(stderr, "Couldn't create CQ\n");*/ - /*goto clean_mr;*/ - /*}*/ - - /*{*/ - /*struct ibv_qp_attr attr;*/ - /*struct ibv_qp_init_attr init_attr = {*/ - /*.send_cq = ctx->cq,*/ - /*.recv_cq = ctx->cq,*/ - /*.cap = {*/ - /*.max_send_wr = 1,*/ - /*.max_recv_wr = rx_depth,*/ - /*.max_send_sge = 1,*/ - /*.max_recv_sge = 1*/ - /*},*/ - /*.qp_type = IBV_QPT_UD,*/ - /*};*/ - - /*ctx->qp = ibv_create_qp(ctx->pd, &init_attr);*/ - /*if (!ctx->qp) {*/ - /*fprintf(stderr, "Couldn't create QP\n");*/ - /*goto clean_cq;*/ - /*}*/ - - /*ibv_query_qp(ctx->qp, &attr, IBV_QP_CAP, &init_attr);*/ - /*if (init_attr.cap.max_inline_data >= size) {*/ - /*ctx->send_flags |= IBV_SEND_INLINE;*/ - /*}*/ - /*}*/ - - /*{*/ - /*struct ibv_qp_attr attr = {*/ - /*.qp_state = IBV_QPS_INIT,*/ - /*.pkey_index = 0,*/ - /*.port_num = port,*/ - /*.qkey = 0x11111111*/ - /*};*/ - - /*if (ibv_modify_qp(ctx->qp, &attr,*/ - /*IBV_QP_STATE |*/ - /*IBV_QP_PKEY_INDEX |*/ - /*IBV_QP_PORT |*/ - /*IBV_QP_QKEY)) {*/ - /*fprintf(stderr, "Failed to modify QP to INIT\n");*/ - /*goto clean_qp;*/ - /*}*/ - /*}*/ - - /*return ctx;*/ - -clean_qp: - /*ibv_destroy_qp(ctx->qp);*/ - -clean_cq: - /*ibv_destroy_cq(ctx->cq);*/ - -clean_mr: - /*ibv_dereg_mr(ctx->mr);*/ - -clean_pd: - /*ibv_dealloc_pd(ctx->pd);*/ - -clean_comp_channel: - /*if (ctx->channel)*/ - /*ibv_destroy_comp_channel(ctx->channel);*/ - -clean_device: - /*ibv_close_device(ctx->context);*/ - -clean_buffer: - /*free(ctx->buf);*/ - -clean_ctx: - /*free(ctx);*/ - - return NULL; -} - -/*static int pp_close_ctx(struct pingpong_context *ctx)*/ -/*{*/ - /*if (ibv_destroy_qp(ctx->qp)) {*/ - /*fprintf(stderr, "Couldn't destroy QP\n");*/ - /*return 1;*/ - /*}*/ - - /*if (ibv_destroy_cq(ctx->cq)) {*/ - /*fprintf(stderr, "Couldn't destroy CQ\n");*/ - /*return 1;*/ - /*}*/ - - /*if (ibv_dereg_mr(ctx->mr)) {*/ - /*fprintf(stderr, "Couldn't deregister MR\n");*/ - /*return 1;*/ - /*}*/ - - /*if (ibv_destroy_ah(ctx->ah)) {*/ - /*fprintf(stderr, "Couldn't destroy AH\n");*/ - /*return 1;*/ - /*}*/ - - /*if (ibv_dealloc_pd(ctx->pd)) {*/ - /*fprintf(stderr, "Couldn't deallocate PD\n");*/ - /*return 1;*/ - /*}*/ - - /*if (ctx->channel) {*/ - /*if (ibv_destroy_comp_channel(ctx->channel)) {*/ - /*fprintf(stderr, "Couldn't destroy completion channel\n");*/ - /*return 1;*/ - /*}*/ - /*}*/ - - /*if (ibv_close_device(ctx->context)) {*/ - /*fprintf(stderr, "Couldn't release context\n");*/ - /*return 1;*/ - /*}*/ - - /*free(ctx->buf);*/ - /*free(ctx);*/ - - /*return 0;*/ -/*}*/ - -/*static int pp_post_recv(struct pingpong_context *ctx, int n)*/ -/*{*/ - /*struct ibv_sge list = {*/ - /*.addr = (uintptr_t) ctx->buf,*/ - /*.length = ctx->size + 40,*/ - /*.lkey = ctx->mr->lkey*/ - /*};*/ - /*struct ibv_recv_wr wr = {*/ - /*.wr_id = PINGPONG_RECV_WRID,*/ - /*.sg_list = &list,*/ - /*.num_sge = 1,*/ - /*};*/ - /*struct ibv_recv_wr *bad_wr;*/ - /*int i;*/ - - /*for (i = 0; i < n; ++i)*/ - /*if (ibv_post_recv(ctx->qp, &wr, &bad_wr))*/ - /*break;*/ - - /*return i;*/ -/*}*/ - -/*static int pp_post_send(struct pingpong_context *ctx, uint32_t qpn)*/ -/*{*/ - /*struct ibv_sge list = {*/ - /*.addr = (uintptr_t) ctx->buf + 40,*/ - /*.length = ctx->size,*/ - /*.lkey = ctx->mr->lkey*/ - /*};*/ - /*struct ibv_send_wr wr = {*/ - /*.wr_id = PINGPONG_SEND_WRID,*/ - /*.sg_list = &list,*/ - /*.num_sge = 1,*/ - /*.opcode = IBV_WR_SEND,*/ - /*.send_flags = ctx->send_flags,*/ - /*.wr = {*/ - /*.ud = {*/ - /*.ah = ctx->ah,*/ - /*.remote_qpn = qpn,*/ - /*.remote_qkey = 0x11111111*/ - /*}*/ - /*}*/ - /*};*/ - /*struct ibv_send_wr *bad_wr;*/ - - /*return ibv_post_send(ctx->qp, &wr, &bad_wr);*/ -/*}*/ - -static void usage(const char *argv0) -{ - printf("Usage:\n"); - printf(" %s start a server and wait for connection\n", argv0); - printf(" %s connect to server at \n", argv0); - printf("\n"); - printf("Options:\n"); - printf(" -p, --port= listen on/connect to port (default 18515)\n"); - printf(" -d, --ib-dev= use IB device (default first device found)\n"); - printf(" -i, --ib-port= use port of IB device (default 1)\n"); - printf(" -s, --size= size of message to exchange (default 2048)\n"); - printf(" -r, --rx-depth= number of receives to post at a time (default 500)\n"); - printf(" -n, --iters= number of exchanges (default 1000)\n"); - printf(" -l, --sl= send messages with service level (default 0)\n"); - printf(" -e, --events sleep on CQ events (default poll)\n"); - printf(" -g, --gid-idx= local port gid index\n"); -} - -int main(int argc, char *argv[]) -{ - printf("LOG: PINGPONG - main\n"); - struct ibv_device **dev_list; - struct ibv_device *ib_dev; - struct pingpong_context *ctx; - struct pingpong_dest my_dest; - struct pingpong_dest *rem_dest; - struct timeval start, end; - char *ib_devname = NULL; - char *servername = NULL; - unsigned int port = 18515; - int ib_port = 1; - unsigned int size = 2048; - unsigned int rx_depth = 500; - unsigned int iters = 1000; - int use_event = 0; - int routs; - int rcnt, scnt; - int num_cq_events = 0; - int sl = 0; - int gidx = -1; - char gid[33]; - - printf("LOG: PINGPONG - main\n"); - srand48(getpid() * time(NULL)); - - printf("LOG: PINGPONG - main\n"); - while (1) { - int c; - - printf("LOG: PINGPONG - main\n"); - static struct option long_options[] = { - { .name = "port", .has_arg = 1, .val = 'p' }, - { .name = "ib-dev", .has_arg = 1, .val = 'd' }, - { .name = "ib-port", .has_arg = 1, .val = 'i' }, - { .name = "size", .has_arg = 1, .val = 's' }, - { .name = "rx-depth", .has_arg = 1, .val = 'r' }, - { .name = "iters", .has_arg = 1, .val = 'n' }, - { .name = "sl", .has_arg = 1, .val = 'l' }, - { .name = "events", .has_arg = 0, .val = 'e' }, - { .name = "gid-idx", .has_arg = 1, .val = 'g' }, - {} - }; - - c = getopt_long(argc, argv, "p:d:i:s:r:n:l:eg:", - long_options, NULL); - if (c == -1) - break; - - switch (c) { - case 'p': - port = strtol(optarg, NULL, 0); - if (port > 65535) { - usage(argv[0]); - return 1; - } - break; - - case 'd': - ib_devname = strdupa(optarg); - break; - - case 'i': - ib_port = strtol(optarg, NULL, 0); - if (ib_port < 1) { - usage(argv[0]); - return 1; - } - break; - - case 's': - size = strtoul(optarg, NULL, 0); - break; - - case 'r': - rx_depth = strtoul(optarg, NULL, 0); - break; - - case 'n': - iters = strtoul(optarg, NULL, 0); - break; - - case 'l': - sl = strtol(optarg, NULL, 0); - break; - - case 'e': - ++use_event; - break; - - case 'g': - gidx = strtol(optarg, NULL, 0); - break; - - default: - usage(argv[0]); - return 1; - } - } - - if (optind == argc - 1) - servername = strdupa(argv[optind]); - else if (optind < argc) { - usage(argv[0]); - return 1; - } - - page_size = 4092; // TODO - - dev_list = ibv_get_device_list(NULL); - if (!dev_list) { - perror("Failed to get IB devices list"); - return 1; - } - - if (!ib_devname) { - ib_dev = *dev_list; - if (!ib_dev) { - fprintf(stderr, "No IB devices found\n"); - return 1; - } - } else { - int i; - for (i = 0; dev_list[i]; ++i) - if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname)) - break; - ib_dev = dev_list[i]; - if (!ib_dev) { - fprintf(stderr, "IB device %s not found\n", ib_devname); - return 1; - } - } - - ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); - if (!ctx) - return 1; - - /*routs = pp_post_recv(ctx, ctx->rx_depth);*/ - /*if (routs < ctx->rx_depth) {*/ - /*fprintf(stderr, "Couldn't post receive (%d)\n", routs);*/ - /*return 1;*/ - /*}*/ - - /*if (use_event)*/ - /*if (ibv_req_notify_cq(ctx->cq, 0)) {*/ - /*fprintf(stderr, "Couldn't request CQ notification\n");*/ - /*return 1;*/ - /*}*/ - - /*if (pp_get_port_info(ctx->context, ib_port, &ctx->portinfo)) {*/ - /*fprintf(stderr, "Couldn't get port info\n");*/ - /*return 1;*/ - /*}*/ - /*my_dest.lid = ctx->portinfo.lid;*/ - - /*my_dest.qpn = ctx->qp->qp_num;*/ - /*my_dest.psn = lrand48() & 0xffffff;*/ - - /*if (gidx >= 0) {*/ - /*if (ibv_query_gid(ctx->context, ib_port, gidx, &my_dest.gid)) {*/ - /*fprintf(stderr, "Could not get local gid for gid index "*/ - /*"%d\n", gidx);*/ - /*return 1;*/ - /*}*/ - /*} else*/ - /*memset(&my_dest.gid, 0, sizeof my_dest.gid);*/ - - /*inet_ntop(AF_INET6, &my_dest.gid, gid, sizeof gid);*/ - /*printf(" local address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x: GID %s\n",*/ - /*my_dest.lid, my_dest.qpn, my_dest.psn, gid);*/ - - /*if (servername)*/ - /*rem_dest = pp_client_exch_dest(servername, port, &my_dest);*/ - /*else*/ - /*rem_dest = pp_server_exch_dest(ctx, ib_port, port, sl,*/ - /*&my_dest, gidx);*/ - - /*if (!rem_dest)*/ - /*return 1;*/ - - /*inet_ntop(AF_INET6, &rem_dest->gid, gid, sizeof gid);*/ - /*printf(" remote address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x, GID %s\n",*/ - /*rem_dest->lid, rem_dest->qpn, rem_dest->psn, gid);*/ - - /*if (servername)*/ - /*if (pp_connect_ctx(ctx, ib_port, my_dest.psn, sl, rem_dest,*/ - /*gidx))*/ - /*return 1;*/ - - /*ctx->pending = PINGPONG_RECV_WRID;*/ - - /*if (servername) {*/ - /*if (pp_post_send(ctx, rem_dest->qpn)) {*/ - /*fprintf(stderr, "Couldn't post send\n");*/ - /*return 1;*/ - /*}*/ - /*ctx->pending |= PINGPONG_SEND_WRID;*/ - /*}*/ - - /*if (gettimeofday(&start, NULL)) {*/ - /*perror("gettimeofday");*/ - /*return 1;*/ - /*}*/ - - /*rcnt = scnt = 0;*/ - /*while (rcnt < iters || scnt < iters) {*/ - /*if (use_event) {*/ - /*struct ibv_cq *ev_cq;*/ - /*void *ev_ctx;*/ - - /*if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) {*/ - /*fprintf(stderr, "Failed to get cq_event\n");*/ - /*return 1;*/ - /*}*/ - - /*++num_cq_events;*/ - - /*if (ev_cq != ctx->cq) {*/ - /*fprintf(stderr, "CQ event for unknown CQ %p\n", ev_cq);*/ - /*return 1;*/ - /*}*/ - - /*if (ibv_req_notify_cq(ctx->cq, 0)) {*/ - /*fprintf(stderr, "Couldn't request CQ notification\n");*/ - /*return 1;*/ - /*}*/ - /*}*/ - - /*{*/ - /*struct ibv_wc wc[2];*/ - /*int ne, i;*/ - - /*do {*/ - /*ne = ibv_poll_cq(ctx->cq, 2, wc);*/ - /*if (ne < 0) {*/ - /*fprintf(stderr, "poll CQ failed %d\n", ne);*/ - /*return 1;*/ - /*}*/ - /*} while (!use_event && ne < 1);*/ - - /*for (i = 0; i < ne; ++i) {*/ - /*if (wc[i].status != IBV_WC_SUCCESS) {*/ - /*fprintf(stderr, "Failed status %s (%d) for wr_id %d\n",*/ - /*ibv_wc_status_str(wc[i].status),*/ - /*wc[i].status, (int) wc[i].wr_id);*/ - /*return 1;*/ - /*}*/ - - /*switch ((int) wc[i].wr_id) {*/ - /*case PINGPONG_SEND_WRID:*/ - /*++scnt;*/ - /*break;*/ - - /*case PINGPONG_RECV_WRID:*/ - /*if (--routs <= 1) {*/ - /*routs += pp_post_recv(ctx, ctx->rx_depth - routs);*/ - /*if (routs < ctx->rx_depth) {*/ - /*fprintf(stderr,*/ - /*"Couldn't post receive (%d)\n",*/ - /*routs);*/ - /*return 1;*/ - /*}*/ - /*}*/ - - /*++rcnt;*/ - /*break;*/ - - /*default:*/ - /*fprintf(stderr, "Completion for unknown wr_id %d\n",*/ - /*(int) wc[i].wr_id);*/ - /*return 1;*/ - /*}*/ - - /*ctx->pending &= ~(int) wc[i].wr_id;*/ - /*if (scnt < iters && !ctx->pending) {*/ - /*if (pp_post_send(ctx, rem_dest->qpn)) {*/ - /*fprintf(stderr, "Couldn't post send\n");*/ - /*return 1;*/ - /*}*/ - /*ctx->pending = PINGPONG_RECV_WRID |*/ - /*PINGPONG_SEND_WRID;*/ - /*}*/ - /*}*/ - /*}*/ - /*}*/ - - /*if (gettimeofday(&end, NULL)) {*/ - /*perror("gettimeofday");*/ - /*return 1;*/ - /*}*/ - - /*{*/ - /*float usec = (end.tv_sec - start.tv_sec) * 1000000 +*/ - /*(end.tv_usec - start.tv_usec);*/ - /*long long bytes = (long long) size * iters * 2;*/ - - /*printf("%lld bytes in %.2f seconds = %.2f Mbit/sec\n",*/ - /*bytes, usec / 1000000., bytes * 8. / usec);*/ - /*printf("%d iters in %.2f seconds = %.2f usec/iter\n",*/ - /*iters, usec / 1000000., usec / iters);*/ - /*}*/ - - /*ibv_ack_cq_events(ctx->cq, num_cq_events);*/ - - /*if (pp_close_ctx(ctx))*/ - /*return 1;*/ - - /*ibv_free_device_list(dev_list);*/ - /*free(rem_dest);*/ - - return 0; -} diff --git a/usr/tests/ib/pingpong.c b/usr/tests/ib/pingpong.c index fae8a78a3..468eddcbd 100644 --- a/usr/tests/ib/pingpong.c +++ b/usr/tests/ib/pingpong.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2006 Cisco Systems. All rights reserved. + * Copyright (c) 2006 Cisco Systems. All rights reserved. + * 2018 Annika Wierichs, RWTH Aachen. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -32,11 +33,24 @@ #include "pingpong.h" -/*#include // TODO*/ +/* #include */ #include #include #include + +uint32_t htonl(uint32_t x) { +#if BYTE_ORDER == BIG_ENDIAN + return x; +#else + return __bswap_32 (x); +#endif +} + +uint32_t ntohl(uint32_t x) { + return htonl(x); +} + enum ibv_mtu pp_mtu_to_enum(int mtu) { switch (mtu) { @@ -55,27 +69,28 @@ int pp_get_port_info(struct ibv_context *context, int port, return ibv_query_port(context, port, attr); } -/* void wire_gid_to_gid(const char *wgid, union ibv_gid *gid) */ -/* { */ - /* char tmp[9]; */ - /* __be32 v32; */ - /* int i; */ - /* uint32_t tmp_gid[4]; */ +void wire_gid_to_gid(const char *wgid, union ibv_gid *gid) +{ + char tmp[9]; + __be32 v32; + int i; + uint32_t tmp_gid[4]; - /* for (tmp[8] = 0, i = 0; i < 4; ++i) { */ - /* memcpy(tmp, wgid + i * 8, 8); */ - /* sscanf(tmp, "%x", &v32); */ - /* tmp_gid[i] = be32toh(v32); */ - /* } */ - /* memcpy(gid, tmp_gid, sizeof(*gid)); */ -/* } */ + for (tmp[8] = 0, i = 0; i < 4; ++i) { + memcpy(tmp, wgid + i * 8, 8); + sscanf(tmp, "%x", &v32); + tmp_gid[i] = ntohl(v32); // TODO: check if this works in every case. + } + memcpy(gid, tmp_gid, sizeof(*gid)); +} -/* void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) */ -/* { */ - /* uint32_t tmp_gid[4]; */ - /* int i; */ +void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) +{ + uint32_t tmp_gid[4]; + int i; + + memcpy(tmp_gid, gid, sizeof(tmp_gid)); + for (i = 0; i < 4; ++i) + sprintf(&wgid[i * 8], "%08x", htonl(tmp_gid[i])); // TODO: check if this works in every case. +} - /* memcpy(tmp_gid, gid, sizeof(tmp_gid)); */ - /* for (i = 0; i < 4; ++i) */ - /* sprintf(&wgid[i * 8], "%08x", htobe32(tmp_gid[i])); */ -/* } */ diff --git a/usr/tests/ib/pingpong.h b/usr/tests/ib/pingpong.h index 5749e8b07..f9a8f0b8d 100644 --- a/usr/tests/ib/pingpong.h +++ b/usr/tests/ib/pingpong.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2006 Cisco Systems. All rights reserved. + * Copyright (c) 2006 Cisco Systems. All rights reserved. + * 2018 Annika Wierichs, RWTH Aachen. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -30,10 +31,17 @@ * SOFTWARE. */ -#include +#ifndef IBV_PINGPONG_H +#define IBV_PINGPONG_H + +#define PAGE_SIZE 4092 + #include enum ibv_mtu pp_mtu_to_enum(int mtu); -int pp_get_port_info(struct ibv_context *context, int port, struct ibv_port_attr *attr); -// void wire_gid_to_gid(const char *wgid, union ibv_gid *gid); -// void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]); +int pp_get_port_info(struct ibv_context *context, int port, + struct ibv_port_attr *attr); +void wire_gid_to_gid(const char *wgid, union ibv_gid *gid); +void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]); + +#endif /* IBV_PINGPONG_H */ diff --git a/usr/tests/ib/rc_pingpong.c b/usr/tests/ib/rc_pingpong.c new file mode 100644 index 000000000..049df1eb2 --- /dev/null +++ b/usr/tests/ib/rc_pingpong.c @@ -0,0 +1,1051 @@ +/* + * Copyright (c) 2005 Topspin Communications. All rights reserved. + * 2018 Annika Wierichs, RWTH Aachen. All rights reserved. + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pingpong.h" + +enum { + PINGPONG_RECV_WRID = 1, + PINGPONG_SEND_WRID = 2, +}; + +static int page_size; +static int use_odp; +static int use_ts; +static int validate_buf; + +struct pingpong_context { + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + + union { + struct ibv_cq *cq; + struct ibv_cq_ex *cq_ex; + } cq_s; + + struct ibv_qp *qp; + char *buf; + int size; + int send_flags; + int rx_depth; + int pending; + struct ibv_port_attr portinfo; + uint64_t completion_timestamp_mask; +}; + +static struct ibv_cq *pp_cq(struct pingpong_context *ctx) +{ + return use_ts ? ibv_cq_ex_to_cq(ctx->cq_s.cq_ex) : + ctx->cq_s.cq; +} + +struct pingpong_dest { + int lid; + int qpn; + int psn; + union ibv_gid gid; +}; + +static int pp_connect_ctx(struct pingpong_context *ctx, int port, int my_psn, enum ibv_mtu mtu, + int sl, struct pingpong_dest *dest, int sgid_idx) +{ + struct ibv_qp_attr attr = { + .qp_state = IBV_QPS_RTR, + .path_mtu = mtu, + .dest_qp_num = dest->qpn, + .rq_psn = dest->psn, + .max_dest_rd_atomic = 1, + .min_rnr_timer = 12, + .ah_attr = { + .is_global = 0, + .dlid = dest->lid, + .sl = sl, + .src_path_bits = 0, + .port_num = port + } + }; + + if (dest->gid.global.interface_id) { + attr.ah_attr.is_global = 1; + attr.ah_attr.grh.hop_limit = 1; + attr.ah_attr.grh.dgid = dest->gid; + attr.ah_attr.grh.sgid_index = sgid_idx; + } + if (ibv_modify_qp(ctx->qp, &attr, + IBV_QP_STATE | + IBV_QP_AV | + IBV_QP_PATH_MTU | + IBV_QP_DEST_QPN | + IBV_QP_RQ_PSN | + IBV_QP_MAX_DEST_RD_ATOMIC | + IBV_QP_MIN_RNR_TIMER)) { + fprintf(stderr, "Failed to modify QP to RTR\n"); + return 1; + } + + attr.qp_state = IBV_QPS_RTS; + attr.timeout = 14; + attr.retry_cnt = 7; + attr.rnr_retry = 7; + attr.sq_psn = my_psn; + attr.max_rd_atomic = 1; + if (ibv_modify_qp(ctx->qp, &attr, + IBV_QP_STATE | + IBV_QP_TIMEOUT | + IBV_QP_RETRY_CNT | + IBV_QP_RNR_RETRY | + IBV_QP_SQ_PSN | + IBV_QP_MAX_QP_RD_ATOMIC)) { + fprintf(stderr, "Failed to modify QP to RTS\n"); + return 1; + } + + return 0; +} + +static struct pingpong_dest *pp_client_exch_dest(const char *servername, int port, + const struct pingpong_dest *my_dest) +{ + struct addrinfo *res, *t; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM + }; + char *service; + char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"]; + int n; + int sockfd = -1; + struct pingpong_dest *rem_dest = NULL; + char gid[33]; + + if (asprintf(&service, "%d", port) < 0) + return NULL; + + n = getaddrinfo(servername, service, &hints, &res); + + if (n < 0) { + fprintf(stderr, "Error for %s:%d\n", servername, port); + free(service); + return NULL; + } + + for (t = res; t; t = t->ai_next) { + sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); + if (sockfd >= 0) { + if (!connect(sockfd, t->ai_addr, t->ai_addrlen)) + break; + close(sockfd); + sockfd = -1; + } + } + + freeaddrinfo(res); + free(service); + + if (sockfd < 0) { + fprintf(stderr, "Couldn't connect to %s:%d\n", servername, port); + return NULL; + } + + gid_to_wire_gid(&my_dest->gid, gid); + sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn, + my_dest->psn, gid); + if (write(sockfd, msg, sizeof msg) != sizeof msg) { + fprintf(stderr, "Couldn't send local address\n"); + goto out; + } + + if (read(sockfd, msg, sizeof msg) != sizeof msg || + write(sockfd, "done", sizeof "done") != sizeof "done") { + perror("client read/write"); + fprintf(stderr, "Couldn't read/write remote address\n"); + goto out; + } + + rem_dest = malloc(sizeof *rem_dest); + if (!rem_dest) + goto out; + + sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn, &rem_dest->psn, gid); + wire_gid_to_gid(gid, &rem_dest->gid); + +out: + close(sockfd); + return rem_dest; +} + +static struct pingpong_dest *pp_server_exch_dest(struct pingpong_context *ctx, int ib_port, + enum ibv_mtu mtu, int port, int sl, const struct pingpong_dest *my_dest, int sgid_idx) +{ + struct addrinfo *res, *t; + struct addrinfo hints = { + .ai_flags = AI_PASSIVE, + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM + }; + char *service; + char msg[sizeof "0000:000000:000000:00000000000000000000000000000000"]; + int n; + int sockfd = -1, connfd; + struct pingpong_dest *rem_dest = NULL; + char gid[33]; + + if (asprintf(&service, "%d", port) < 0) + return NULL; + + n = getaddrinfo(NULL, service, &hints, &res); + + if (n < 0) { + fprintf(stderr, "Error for port %d\n", port); + free(service); + return NULL; + } + + for (t = res; t; t = t->ai_next) { + sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); + if (sockfd >= 0) { + n = 1; + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n); + + if (!bind(sockfd, t->ai_addr, t->ai_addrlen)) + break; + close(sockfd); + sockfd = -1; + } + } + + freeaddrinfo(res); + free(service); + + if (sockfd < 0) { + fprintf(stderr, "Couldn't listen to port %d\n", port); + return NULL; + } + + listen(sockfd, 1); + connfd = accept(sockfd, NULL, NULL); + close(sockfd); + if (connfd < 0) { + fprintf(stderr, "accept() failed\n"); + return NULL; + } + + n = read(connfd, msg, sizeof msg); + if (n != sizeof msg) { + perror("server read"); + fprintf(stderr, "%d/%d: Couldn't read remote address\n", n, (int) sizeof msg); + goto out; + } + + rem_dest = malloc(sizeof *rem_dest); + if (!rem_dest) + goto out; + + sscanf(msg, "%x:%x:%x:%s", &rem_dest->lid, &rem_dest->qpn, + &rem_dest->psn, gid); + wire_gid_to_gid(gid, &rem_dest->gid); + + if (pp_connect_ctx(ctx, ib_port, my_dest->psn, mtu, sl, rem_dest, + sgid_idx)) { + fprintf(stderr, "Couldn't connect to remote QP\n"); + free(rem_dest); + rem_dest = NULL; + goto out; + } + + + gid_to_wire_gid(&my_dest->gid, gid); + sprintf(msg, "%04x:%06x:%06x:%s", my_dest->lid, my_dest->qpn, + my_dest->psn, gid); + if (write(connfd, msg, sizeof msg) != sizeof msg || + read(connfd, msg, sizeof msg) != sizeof "done") { + fprintf(stderr, "Couldn't send/recv local address\n"); + free(rem_dest); + rem_dest = NULL; + goto out; + } + + +out: + close(connfd); + return rem_dest; +} + +static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, int rx_depth, + int port, int use_event) +{ + struct pingpong_context *ctx; + int access_flags = IBV_ACCESS_LOCAL_WRITE; + + ctx = calloc(1, sizeof *ctx); + if (!ctx) + return NULL; + + ctx->size = size; + ctx->send_flags = IBV_SEND_SIGNALED; + ctx->rx_depth = rx_depth; + + ctx->buf = memalign(page_size, size); + if (!ctx->buf) { + fprintf(stderr, "Couldn't allocate work buf.\n"); + goto clean_ctx; + } + + /* FIXME memset(ctx->buf, 0, size); */ + memset(ctx->buf, 0x7b, size); + + ctx->context = ibv_open_device(ib_dev); + if (!ctx->context) { + fprintf(stderr, "Couldn't get context for %s\n", + ibv_get_device_name(ib_dev)); + goto clean_buffer; + } + + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + goto clean_device; + } + } else + ctx->channel = NULL; + + ctx->pd = ibv_alloc_pd(ctx->context); + if (!ctx->pd) { + fprintf(stderr, "Couldn't allocate PD\n"); + goto clean_comp_channel; + } + + if (use_odp || use_ts) { + const uint32_t rc_caps_mask = IBV_ODP_SUPPORT_SEND | + IBV_ODP_SUPPORT_RECV; + struct ibv_device_attr_ex attrx; + + if (ibv_query_device_ex(ctx->context, NULL, &attrx)) { + fprintf(stderr, "Couldn't query device for its features\n"); + goto clean_comp_channel; + } + + if (use_odp) { + if (!(attrx.odp_caps.general_caps & IBV_ODP_SUPPORT) || + (attrx.odp_caps.per_transport_caps.rc_odp_caps & rc_caps_mask) != rc_caps_mask) { + fprintf(stderr, "The device isn't ODP capable or does not support RC send and receive with ODP\n"); + goto clean_comp_channel; + } + access_flags |= IBV_ACCESS_ON_DEMAND; + } + + if (use_ts) { + if (!attrx.completion_timestamp_mask) { + fprintf(stderr, "The device isn't completion timestamp capable\n"); + goto clean_comp_channel; + } + ctx->completion_timestamp_mask = attrx.completion_timestamp_mask; + } + } + ctx->mr = ibv_reg_mr(ctx->pd, ctx->buf, size, access_flags); + + if (!ctx->mr) { + fprintf(stderr, "Couldn't register MR\n"); + goto clean_pd; + } + + if (use_ts) { + struct ibv_cq_init_attr_ex attr_ex = { + .cqe = rx_depth + 1, + .cq_context = NULL, + .channel = ctx->channel, + .comp_vector = 0, + .wc_flags = IBV_WC_EX_WITH_COMPLETION_TIMESTAMP + }; + + ctx->cq_s.cq_ex = ibv_create_cq_ex(ctx->context, &attr_ex); + } else { + ctx->cq_s.cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, ctx->channel, 0); + } + + if (!pp_cq(ctx)) { + fprintf(stderr, "Couldn't create CQ\n"); + goto clean_mr; + } + + { + struct ibv_qp_attr attr; + struct ibv_qp_init_attr init_attr = { + .send_cq = pp_cq(ctx), + .recv_cq = pp_cq(ctx), + .cap = { + .max_send_wr = 1, + .max_recv_wr = rx_depth, + .max_send_sge = 1, + .max_recv_sge = 1 + }, + .qp_type = IBV_QPT_RC + }; + + ctx->qp = ibv_create_qp(ctx->pd, &init_attr); + if (!ctx->qp) { + fprintf(stderr, "Couldn't create QP\n"); + goto clean_cq; + } + + ibv_query_qp(ctx->qp, &attr, IBV_QP_CAP, &init_attr); + if (init_attr.cap.max_inline_data >= size) { + ctx->send_flags |= IBV_SEND_INLINE; + } + } + + { + struct ibv_qp_attr attr = { + .qp_state = IBV_QPS_INIT, + .pkey_index = 0, + .port_num = port, + .qp_access_flags = 0 + }; + + if (ibv_modify_qp(ctx->qp, &attr, + IBV_QP_STATE | + IBV_QP_PKEY_INDEX | + IBV_QP_PORT | + IBV_QP_ACCESS_FLAGS)) { + fprintf(stderr, "Failed to modify QP to INIT\n"); + goto clean_qp; + } + } + + return ctx; + +clean_qp: + ibv_destroy_qp(ctx->qp); + +clean_cq: + ibv_destroy_cq(pp_cq(ctx)); + +clean_mr: + ibv_dereg_mr(ctx->mr); + +clean_pd: + ibv_dealloc_pd(ctx->pd); + +clean_comp_channel: + if (ctx->channel) + ibv_destroy_comp_channel(ctx->channel); + +clean_device: + ibv_close_device(ctx->context); + +clean_buffer: + free(ctx->buf); + +clean_ctx: + free(ctx); + + return NULL; +} + +static int pp_close_ctx(struct pingpong_context *ctx) +{ + if (ibv_destroy_qp(ctx->qp)) { + fprintf(stderr, "Couldn't destroy QP\n"); + return 1; + } + + if (ibv_destroy_cq(pp_cq(ctx))) { + fprintf(stderr, "Couldn't destroy CQ\n"); + return 1; + } + + if (ibv_dereg_mr(ctx->mr)) { + fprintf(stderr, "Couldn't deregister MR\n"); + return 1; + } + + if (ibv_dealloc_pd(ctx->pd)) { + fprintf(stderr, "Couldn't deallocate PD\n"); + return 1; + } + + if (ctx->channel) { + if (ibv_destroy_comp_channel(ctx->channel)) { + fprintf(stderr, "Couldn't destroy completion channel\n"); + return 1; + } + } + + if (ibv_close_device(ctx->context)) { + fprintf(stderr, "Couldn't release context\n"); + return 1; + } + + free(ctx->buf); + free(ctx); + + return 0; +} + +static int pp_post_recv(struct pingpong_context *ctx, int n) +{ + struct ibv_sge list = { + .addr = (uintptr_t) ctx->buf, + .length = ctx->size, + .lkey = ctx->mr->lkey + }; + struct ibv_recv_wr wr = { + .wr_id = PINGPONG_RECV_WRID, + .sg_list = &list, + .num_sge = 1, + }; + struct ibv_recv_wr *bad_wr; + int i; + + for (i = 0; i < n; ++i) + if (ibv_post_recv(ctx->qp, &wr, &bad_wr)) + break; + + return i; +} + +static int pp_post_send(struct pingpong_context *ctx) +{ + struct ibv_sge list = { + .addr = (uintptr_t) ctx->buf, + .length = ctx->size, + .lkey = ctx->mr->lkey + }; + + struct ibv_send_wr wr = { + .wr_id = PINGPONG_SEND_WRID, + .sg_list = &list, + .num_sge = 1, + .opcode = IBV_WR_SEND, + .send_flags = ctx->send_flags, + }; + struct ibv_send_wr *bad_wr; + + return ibv_post_send(ctx->qp, &wr, &bad_wr); +} + +struct ts_params { + uint64_t comp_recv_max_time_delta; + uint64_t comp_recv_min_time_delta; + uint64_t comp_recv_total_time_delta; + uint64_t comp_recv_prev_time; + int last_comp_with_ts; + unsigned int comp_with_time_iters; +}; + +static inline int parse_single_wc(struct pingpong_context *ctx, int *scnt, + int *rcnt, int *routs, int iters, + uint64_t wr_id, enum ibv_wc_status status, + uint64_t completion_timestamp, + struct ts_params *ts) +{ + if (status != IBV_WC_SUCCESS) { + fprintf(stderr, "Failed status %s (%d) for wr_id %d\n", + ibv_wc_status_str(status), + status, (int)wr_id); + return 1; + } + + switch ((int)wr_id) { + case PINGPONG_SEND_WRID: + ++(*scnt); + break; + + case PINGPONG_RECV_WRID: + if (--(*routs) <= 1) { + *routs += pp_post_recv(ctx, ctx->rx_depth - *routs); + if (*routs < ctx->rx_depth) { + fprintf(stderr, + "Couldn't post receive (%d)\n", + *routs); + return 1; + } + } + + ++(*rcnt); + if (use_ts) { + if (ts->last_comp_with_ts) { + uint64_t delta; + + /* checking whether the clock was wrapped around */ + if (completion_timestamp >= ts->comp_recv_prev_time) + delta = completion_timestamp - ts->comp_recv_prev_time; + else + delta = ctx->completion_timestamp_mask - ts->comp_recv_prev_time + + completion_timestamp + 1; + + ts->comp_recv_max_time_delta = ts->comp_recv_max_time_delta > delta ? + ts->comp_recv_max_time_delta : delta; + ts->comp_recv_min_time_delta = ts->comp_recv_min_time_delta < delta ? + ts->comp_recv_min_time_delta : delta; + ts->comp_recv_total_time_delta += delta; + ts->comp_with_time_iters++; + } + + ts->comp_recv_prev_time = completion_timestamp; + ts->last_comp_with_ts = 1; + } else { + ts->last_comp_with_ts = 0; + } + + break; + + default: + fprintf(stderr, "Completion for unknown wr_id %d\n", + (int)wr_id); + return 1; + } + + ctx->pending &= ~(int)wr_id; + if (*scnt < iters && !ctx->pending) { + if (pp_post_send(ctx)) { + fprintf(stderr, "Couldn't post send\n"); + return 1; + } + ctx->pending = PINGPONG_RECV_WRID | + PINGPONG_SEND_WRID; + } + + return 0; +} + +static void usage(const char *argv0) +{ + printf("Usage:\n"); + printf(" %s start a server and wait for connection\n", argv0); + printf(" %s connect to server at \n", argv0); + printf("\n"); + printf("Options:\n"); + printf(" -p, --port= listen on/connect to port (default 18515)\n"); + printf(" -d, --ib-dev= use IB device (default first device found)\n"); + printf(" -i, --ib-port= use port of IB device (default 1)\n"); + printf(" -s, --size= size of message to exchange (default 4096)\n"); + printf(" -m, --mtu= path MTU (default 1024)\n"); + printf(" -r, --rx-depth= number of receives to post at a time (default 500)\n"); + printf(" -n, --iters= number of exchanges (default 1000)\n"); + printf(" -l, --sl= service level value\n"); + printf(" -e, --events sleep on CQ events (default poll)\n"); + printf(" -g, --gid-idx= local port gid index\n"); + printf(" -o, --odp use on demand paging\n"); + printf(" -t, --ts get CQE with timestamp\n"); + printf(" -c, --chk validate received buffer\n"); +} + +int main(int argc, char *argv[]) +{ + struct ibv_device **dev_list; + struct ibv_device *ib_dev; + struct pingpong_context *ctx; + struct pingpong_dest my_dest; + struct pingpong_dest *rem_dest; + struct timeval start, end; + char *ib_devname = NULL; + char *servername = NULL; + unsigned int port = 18515; + int ib_port = 1; + unsigned int size = 4096; + enum ibv_mtu mtu = IBV_MTU_1024; + unsigned int rx_depth = 500; + unsigned int iters = 1000; + int use_event = 0; + int num_cq_events = 0; + int sl = 0; + int gidx = -1; + int routs; + int rcnt, scnt; + char gid[33]; + struct ts_params ts; + + srand48(getpid() * time(NULL)); + + while (1) { + int c; + + static struct option long_options[] = { + { .name = "port", .has_arg = 1, .val = 'p' }, + { .name = "ib-dev", .has_arg = 1, .val = 'd' }, + { .name = "ib-port", .has_arg = 1, .val = 'i' }, + { .name = "size", .has_arg = 1, .val = 's' }, + { .name = "mtu", .has_arg = 1, .val = 'm' }, + { .name = "rx-depth", .has_arg = 1, .val = 'r' }, + { .name = "iters", .has_arg = 1, .val = 'n' }, + { .name = "sl", .has_arg = 1, .val = 'l' }, + { .name = "events", .has_arg = 0, .val = 'e' }, + { .name = "gid-idx", .has_arg = 1, .val = 'g' }, + { .name = "odp", .has_arg = 0, .val = 'o' }, + { .name = "ts", .has_arg = 0, .val = 't' }, + { .name = "chk", .has_arg = 0, .val = 'c' }, + {} + }; + + c = getopt_long(argc, argv, "p:d:i:s:m:r:n:l:eg:otc", + long_options, NULL); + + if (c == -1) + break; + + switch (c) { + case 'p': + port = strtoul(optarg, NULL, 0); + if (port > 65535) { + usage(argv[0]); + return 1; + } + break; + + case 'd': + ib_devname = strdupa(optarg); + break; + + case 'i': + ib_port = strtol(optarg, NULL, 0); + if (ib_port < 1) { + usage(argv[0]); + return 1; + } + break; + + case 's': + size = strtoul(optarg, NULL, 0); + break; + + case 'm': + mtu = pp_mtu_to_enum(strtol(optarg, NULL, 0)); + if (mtu == 0) { + usage(argv[0]); + return 1; + } + break; + + case 'r': + rx_depth = strtoul(optarg, NULL, 0); + break; + + case 'n': + iters = strtoul(optarg, NULL, 0); + break; + + case 'l': + sl = strtol(optarg, NULL, 0); + break; + + case 'e': + ++use_event; + break; + + case 'g': + gidx = strtol(optarg, NULL, 0); + break; + + case 'o': + use_odp = 1; + break; + case 't': + use_ts = 1; + break; + case 'c': + validate_buf = 1; + break; + + default: + usage(argv[0]); + return 1; + } + } + + if (optind == argc - 1) + servername = strdupa(argv[optind]); + else if (optind < argc) { + usage(argv[0]); + return 1; + } + + if (use_ts) { + ts.comp_recv_max_time_delta = 0; + ts.comp_recv_min_time_delta = 0xffffffff; + ts.comp_recv_total_time_delta = 0; + ts.comp_recv_prev_time = 0; + ts.last_comp_with_ts = 0; + ts.comp_with_time_iters = 0; + } + + page_size = PAGE_SIZE; + + dev_list = ibv_get_device_list(NULL); + if (!dev_list) { + perror("Failed to get IB devices list"); + return 1; + } + + if (!ib_devname) { + ib_dev = *dev_list; + if (!ib_dev) { + fprintf(stderr, "No IB devices found\n"); + return 1; + } + } else { + int i; + for (i = 0; dev_list[i]; ++i) + if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname)) + break; + ib_dev = dev_list[i]; + if (!ib_dev) { + fprintf(stderr, "IB device %s not found\n", ib_devname); + return 1; + } + } + + ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); + if (!ctx) + return 1; + + routs = pp_post_recv(ctx, ctx->rx_depth); + if (routs < ctx->rx_depth) { + fprintf(stderr, "Couldn't post receive (%d)\n", routs); + return 1; + } + + if (use_event) + if (ibv_req_notify_cq(pp_cq(ctx), 0)) { + fprintf(stderr, "Couldn't request CQ notification\n"); + return 1; + } + + + if (pp_get_port_info(ctx->context, ib_port, &ctx->portinfo)) { + fprintf(stderr, "Couldn't get port info\n"); + return 1; + } + + my_dest.lid = ctx->portinfo.lid; + if (ctx->portinfo.link_layer != IBV_LINK_LAYER_ETHERNET && + !my_dest.lid) { + fprintf(stderr, "Couldn't get local LID\n"); + return 1; + } + + if (gidx >= 0) { + if (ibv_query_gid(ctx->context, ib_port, gidx, &my_dest.gid)) { + fprintf(stderr, "can't read sgid of index %d\n", gidx); + return 1; + } + } else + memset(&my_dest.gid, 0, sizeof my_dest.gid); + + my_dest.qpn = ctx->qp->qp_num; + my_dest.psn = lrand48() & 0xffffff; + printf(" local address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x\n", + my_dest.lid, my_dest.qpn, my_dest.psn); + + + if (servername) + rem_dest = pp_client_exch_dest(servername, port, &my_dest); + else + rem_dest = pp_server_exch_dest(ctx, ib_port, mtu, port, sl, + &my_dest, gidx); + + if (!rem_dest) + return 1; + + printf(" remote address: LID 0x%04x, QPN 0x%06x, PSN 0x%06x\n", + rem_dest->lid, rem_dest->qpn, rem_dest->psn); + + if (servername) + if (pp_connect_ctx(ctx, ib_port, my_dest.psn, mtu, sl, rem_dest, + gidx)) + return 1; + + ctx->pending = PINGPONG_RECV_WRID; + + if (servername) { + if (validate_buf) + for (int i = 0; i < size; i += page_size) + ctx->buf[i] = i / page_size % sizeof(char); + if (pp_post_send(ctx)) { + fprintf(stderr, "Couldn't post send\n"); + return 1; + } + ctx->pending |= PINGPONG_SEND_WRID; + } + + if (gettimeofday(&start, NULL)) { + perror("gettimeofday"); + return 1; + } + + rcnt = scnt = 0; + while (rcnt < iters || scnt < iters) { + int ret; + + if (use_event) { + struct ibv_cq *ev_cq; + void *ev_ctx; + + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { + fprintf(stderr, "Failed to get cq_event\n"); + return 1; + } + + ++num_cq_events; + + if (ev_cq != pp_cq(ctx)) { + fprintf(stderr, "CQ event for unknown CQ %p\n", ev_cq); + return 1; + } + + if (ibv_req_notify_cq(pp_cq(ctx), 0)) { + fprintf(stderr, "Couldn't request CQ notification\n"); + return 1; + } + } + + if (use_ts) { + struct ibv_poll_cq_attr attr = {}; + + do { + ret = ibv_start_poll(ctx->cq_s.cq_ex, &attr); + } while (!use_event && ret == ENOENT); + + if (ret) { + fprintf(stderr, "poll CQ failed %d\n", ret); + return ret; + } + ret = parse_single_wc(ctx, &scnt, &rcnt, &routs, + iters, + ctx->cq_s.cq_ex->wr_id, + ctx->cq_s.cq_ex->status, + ibv_wc_read_completion_ts(ctx->cq_s.cq_ex), + &ts); + if (ret) { + ibv_end_poll(ctx->cq_s.cq_ex); + return ret; + } + ret = ibv_next_poll(ctx->cq_s.cq_ex); + if (!ret) + ret = parse_single_wc(ctx, &scnt, &rcnt, &routs, + iters, + ctx->cq_s.cq_ex->wr_id, + ctx->cq_s.cq_ex->status, + ibv_wc_read_completion_ts(ctx->cq_s.cq_ex), + &ts); + ibv_end_poll(ctx->cq_s.cq_ex); + if (ret && ret != ENOENT) { + fprintf(stderr, "poll CQ failed %d\n", ret); + return ret; + } + } else { + int ne, i; + struct ibv_wc wc[2]; + + do { + ne = ibv_poll_cq(pp_cq(ctx), 2, wc); + if (ne < 0) { + fprintf(stderr, "poll CQ failed %d\n", ne); + return 1; + } + } while (!use_event && ne < 1); + + for (i = 0; i < ne; ++i) { + ret = parse_single_wc(ctx, &scnt, &rcnt, &routs, + iters, + wc[i].wr_id, + wc[i].status, + 0, &ts); + if (ret) { + fprintf(stderr, "parse WC failed %d\n", ne); + return 1; + } + } + } + } + + if (gettimeofday(&end, NULL)) { + perror("gettimeofday"); + return 1; + } + + { + float usec = (end.tv_sec - start.tv_sec) * 1000000 + + (end.tv_usec - start.tv_usec); + long long bytes = (long long) size * iters * 2; + + printf("%lld bytes in %.2f seconds = %.2f Mbit/sec\n", + bytes, usec / 1000000., bytes * 8. / usec); + printf("%d iters in %.2f seconds = %.2f usec/iter\n", + iters, usec / 1000000., usec / iters); + + if (use_ts && ts.comp_with_time_iters) { + printf("Max receive completion clock cycles = %" PRIu64 "\n", + ts.comp_recv_max_time_delta); + printf("Min receive completion clock cycles = %" PRIu64 "\n", + ts.comp_recv_min_time_delta); + printf("Average receive completion clock cycles = %f\n", + (double)ts.comp_recv_total_time_delta / ts.comp_with_time_iters); + } + + if ((!servername) && (validate_buf)) { + for (int i = 0; i < size; i += page_size) + if (ctx->buf[i] != i / page_size % sizeof(char)) + printf("invalid data in page %d\n", + i / page_size); + } + } + + ibv_ack_cq_events(pp_cq(ctx), num_cq_events); + + if (pp_close_ctx(ctx)) + return 1; + + ibv_free_device_list(dev_list); + free(rem_dest); + + return 0; +}