diff --git a/cray-libcxi.spec b/cray-libcxi.spec index 18e87eb..bc07be7 100644 --- a/cray-libcxi.spec +++ b/cray-libcxi.spec @@ -7,7 +7,7 @@ %endif Name: cray-libcxi -Version: 1.0.1 +Version: 1.0.2 Release: %(echo ${BUILD_METADATA}) Summary: Cassini userspace library License: Dual LGPL-2.1/BSD-3-Clause diff --git a/utils/atomic_bw.c b/utils/atomic_bw.c index e797b68..c7dbde2 100644 --- a/utils/atomic_bw.c +++ b/utils/atomic_bw.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI Atomic Memory Operation bandwidth benchmark */ @@ -35,7 +35,7 @@ #define NONFETCH_U32_HRP_DISABLE_MAX_REV 2 static const char *name = "cxi_atomic_bw"; -static const char *version = "2.1.0"; +static const char *version = "2.2.0"; /* Allocate INI resources */ int atomic_bw_alloc_ini(struct util_context *util) @@ -470,7 +470,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/atomic_lat.c b/utils/atomic_lat.c index 1364fd3..3816cae 100644 --- a/utils/atomic_lat.c +++ b/utils/atomic_lat.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI Atomic Memory Operation latency benchmark */ @@ -31,7 +31,7 @@ #define TYPE_DFLT C_AMO_TYPE_UINT64_T static const char *name = "cxi_atomic_lat"; -static const char *version = "2.1.0"; +static const char *version = "2.2.0"; /* Allocate INI resources */ int atomic_lat_alloc_ini(struct util_context *util) @@ -417,7 +417,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/ctrl_connection.c b/utils/ctrl_connection.c index f3abcb5..6d56d28 100644 --- a/utils/ctrl_connection.c +++ b/utils/ctrl_connection.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* IP/TCP control messaging for CXI benchmarks */ @@ -213,6 +213,7 @@ static int ctrl_init(struct ctrl_connection *ctrl) rc = ctrl_set_rcvtmo(ctrl, &dflt_tmo); if (rc) goto done; + rc = setsockopt(ctrl->fd, SOL_SOCKET, SO_SNDTIMEO, &dflt_tmo, sizeof(dflt_tmo)); if (rc == -1) { @@ -250,10 +251,10 @@ static int ctrl_exchange_config(struct ctrl_connection *ctrl, const char *name, /* Verify names match */ buf_len = strlen(name) + 1; rc = ctrl_exchange_data(ctrl, name, buf_len, peer_buf, - MAX_CTRL_DATA_BYTES); + sizeof(peer_buf)); if (rc < 0) return rc; - if (rc != buf_len || strncmp(name, peer_buf, buf_len)) { + if (rc != buf_len || strcmp(name, peer_buf)) { fprintf(stderr, "Client and server program names do not match!\n"); return -EINVAL; @@ -262,7 +263,7 @@ static int ctrl_exchange_config(struct ctrl_connection *ctrl, const char *name, /* Verify MAJ.MIN versions match */ buf_len = strlen(ver) + 1; rc = ctrl_exchange_data(ctrl, ver, buf_len, peer_buf, - MAX_CTRL_DATA_BYTES); + sizeof(peer_buf)); if (rc < 0) return rc; vers_match = false; @@ -281,27 +282,24 @@ static int ctrl_exchange_config(struct ctrl_connection *ctrl, const char *name, /* Exchange config options */ rc = ctrl_exchange_data(ctrl, opts, sizeof(*opts), peer_buf, - MAX_CTRL_DATA_BYTES); + sizeof(peer_buf)); if (rc < 0) return rc; - if ((size_t)rc != sizeof(*opts)) { - fprintf(stderr, "Bad opts size (exp %lu got %d)\n", + fprintf(stderr, "Bad opts size (exp %zu got %d)\n", sizeof(*opts), rc); - rc = -EINVAL; - } else { - if (ctrl->is_server) - memcpy(opts, peer_buf, - (sizeof(*opts) - sizeof(opts->loc_opts) - - sizeof(opts->rmt_opts))); - - peer_opts = (struct util_opts *)peer_buf; - memcpy(&opts->rmt_opts, &peer_opts->loc_opts, - sizeof(opts->rmt_opts)); - rc = 0; + return -EINVAL; } - return rc; + peer_opts = (struct util_opts *)peer_buf; + if (ctrl->is_server) + memcpy(opts, peer_opts, + (sizeof(*opts) - sizeof(opts->loc_opts) + - sizeof(opts->rmt_opts))); + + opts->rmt_opts = peer_opts->loc_opts; + + return 0; } /* Exchange client/server NIC fabric addresses */ @@ -378,45 +376,89 @@ int ctrl_close(struct ctrl_connection *ctrl) return rc; } +/* Helper function for ctrl_send */ +static ssize_t __ctrl_send(int fd, const void *buf, size_t len) +{ + ssize_t bytes; + + bytes = send(fd, buf, len, 0); + if (bytes < 0) { + int rc = -errno; + + fprintf(stderr, "send() failed: %s\n", strerror(-rc)); + return rc; + } else if (bytes == 0) { + fprintf(stderr, "No data sent or remote connection closed\n"); + return -ECONNABORTED; + } else if (bytes != len) { + fprintf(stderr, "Bad send size (exp %zu got %zu)\n", len, bytes); + return -EIO; + } + + return bytes; +} + /* Encapsulate and send a control message * returns -errno on error, 0 on success */ -int ctrl_send(struct ctrl_connection *ctrl, const void *buf, size_t size) +static int ctrl_send(struct ctrl_connection *ctrl, const void *buf, size_t size) { - int rc; - struct ctrl_msg *msg = (struct ctrl_msg *)ctrl->buf; + struct ctrl_msg msg = {}; + ssize_t bytes; if (!ctrl || (!buf && size > 0)) return -EINVAL; - if (size > MAX_CTRL_DATA_BYTES) - return -EMSGSIZE; - msg->pyld_len = size; - if (size > 0) - memcpy(msg->pyld, buf, size); - rc = send(ctrl->fd, ctrl->buf, (size + sizeof(*msg)), 0); - if (rc < 0) { - rc = -errno; - fprintf(stderr, "send() failed: %s\n", strerror(-rc)); - } else if (rc == 0) { - rc = -ECONNABORTED; - fprintf(stderr, - "No data sent or no data received at remote connection\n"); - } else { - rc = 0; + msg.pyld_len = size; + + bytes = __ctrl_send(ctrl->fd, &msg, sizeof(msg)); + if (bytes < 0) + return bytes; + + if (size) { + bytes = __ctrl_send(ctrl->fd, buf, size); + if (bytes < 0) + return bytes; } - return rc; + return 0; +} + +/* Helper function for ctrl_recv */ +static ssize_t __ctrl_recv(int fd, void *buf, size_t len) +{ + ssize_t bytes; + + bytes = recv(fd, buf, len, 0); + if (bytes < 0) { + int rc = -errno; + + /* recv will return EAGAIN when a timeout is set */ + if (rc == -EAGAIN) + rc = -ETIMEDOUT; + + fprintf(stderr, "recv() failed: %s\n", strerror(-rc)); + return rc; + } else if (bytes == 0) { + fprintf(stderr, "No data received or remote connection closed\n"); + return -ECONNABORTED; + } else if (bytes != len) { + fprintf(stderr, "Bad recv size (exp %zu got %zu)\n", len, bytes); + return -EIO; + } + + return bytes; } /* Attempt to receive and de-encapsulate a control message * returns -errno on error, number of bytes received on success */ -int ctrl_recv(struct ctrl_connection *ctrl, void *buf, size_t size, - struct timeval *tmo_tv) +static int ctrl_recv(struct ctrl_connection *ctrl, void *buf, size_t size, + struct timeval *tmo_tv) { int rc; - struct ctrl_msg *msg = (struct ctrl_msg *)ctrl->buf; + struct ctrl_msg msg = {}; + ssize_t bytes; if (!ctrl || (!buf && size > 0)) return -EINVAL; @@ -425,56 +467,45 @@ int ctrl_recv(struct ctrl_connection *ctrl, void *buf, size_t size, if (rc) return rc; - rc = recv(ctrl->fd, ctrl->buf, CTRL_MSG_BUF_SZ, 0); - if (rc < 0) { - rc = -errno; - - /* recv will return EAGAIN when a timeout is set */ - if (rc == -EAGAIN) - rc = -ETIMEDOUT; + bytes = __ctrl_recv(ctrl->fd, &msg, sizeof(msg)); + if (bytes < 0) + return bytes; - fprintf(stderr, "recv() failed: %s\n", strerror(-rc)); - } else if (rc == 0) { - rc = -ECONNABORTED; - fprintf(stderr, - "No data received or remote connection closed\n"); - } else if (msg->pyld_len > size) { - rc = -EMSGSIZE; - fprintf(stderr, "Received message (%u) larger than buf (%lu)\n", - msg->pyld_len, size); - } + if (msg.pyld_len) { + if (msg.pyld_len > size) { + fprintf(stderr, "Received message (%u) larger than buf (%zu)\n", + msg.pyld_len, size); + return -EMSGSIZE; + } - if (rc > 0) { - if (msg->pyld_len > 0) - memcpy(buf, msg->pyld, msg->pyld_len); - rc = msg->pyld_len; + bytes = __ctrl_recv(ctrl->fd, buf, msg.pyld_len); + if (bytes < 0) + return bytes; } - return rc; + return msg.pyld_len; } -/* Exchange client/server data - * returns -errno on error, number of bytes received on success - */ -int ctrl_exchange_data(struct ctrl_connection *ctrl, const void *client_buf, - size_t cbuf_size, void *server_buf, size_t sbuf_size) +/* Helper function for ctrl_exchange_data and ctrl_barrier */ +static int __ctrl_exchange_data(struct ctrl_connection *ctrl, + const void *cbuf, size_t clen, void *sbuf, size_t slen, + struct timeval *tmo) { int rc; int rc_recv; - if (!ctrl || !client_buf || !server_buf) - return -EINVAL; - if (ctrl->is_server) { - rc = ctrl_send(ctrl, client_buf, cbuf_size); + rc = ctrl_send(ctrl, cbuf, clen); if (rc < 0) return rc; } - rc_recv = ctrl_recv(ctrl, server_buf, sbuf_size, &dflt_tmo); + + rc_recv = ctrl_recv(ctrl, sbuf, slen, tmo); if (rc_recv < 0) return rc_recv; + if (!ctrl->is_server) { - rc = ctrl_send(ctrl, client_buf, cbuf_size); + rc = ctrl_send(ctrl, cbuf, clen); if (rc < 0) return rc; } @@ -482,6 +513,23 @@ int ctrl_exchange_data(struct ctrl_connection *ctrl, const void *client_buf, return rc_recv; } +/* Exchange client/server data + * returns -errno on error, number of bytes received on success + */ +int ctrl_exchange_data(struct ctrl_connection *ctrl, const void *client_buf, + size_t cbuf_size, void *server_buf, size_t sbuf_size) +{ + int rc; + + if (!ctrl || !client_buf || !server_buf) + return -EINVAL; + + rc = __ctrl_exchange_data(ctrl, client_buf, cbuf_size, + server_buf, sbuf_size, &dflt_tmo); + + return rc; +} + /* Sync client and server */ int ctrl_barrier(struct ctrl_connection *ctrl, uint64_t tmo_usec, char *label) { @@ -493,23 +541,11 @@ int ctrl_barrier(struct ctrl_connection *ctrl, uint64_t tmo_usec, char *label) tmo_tv.tv_sec = tmo_usec / SEC2USEC; tmo_tv.tv_usec = tmo_usec % SEC2USEC; - if (!ctrl->is_server) { - rc = ctrl_send(ctrl, NULL, 0); - if (rc < 0) - goto done; - } - rc = ctrl_recv(ctrl, NULL, 0, &tmo_tv); - if (rc < 0) - goto done; - if (ctrl->is_server) { - rc = ctrl_send(ctrl, NULL, 0); - if (rc < 0) - goto done; - } -done: - if (rc) - fprintf(stderr, "%shandshake failed: %s\n", label, + rc = __ctrl_exchange_data(ctrl, NULL, 0, NULL, 0, &tmo_tv); + if (rc < 0) + fprintf(stderr, "%s handshake failed: %s\n", label, strerror(-rc)); + return rc; } diff --git a/utils/read_bw.c b/utils/read_bw.c index abbba3d..55a2bd7 100644 --- a/utils/read_bw.c +++ b/utils/read_bw.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI RDMA read bandwidth benchmark */ @@ -366,7 +366,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/read_lat.c b/utils/read_lat.c index 8a9edf3..1a3ef93 100644 --- a/utils/read_lat.c +++ b/utils/read_lat.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI RDMA read latency benchmark */ @@ -347,7 +347,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/send_bw.c b/utils/send_bw.c index 30a1da0..12ac59e 100644 --- a/utils/send_bw.c +++ b/utils/send_bw.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI send bandwidth benchmark */ @@ -577,7 +577,7 @@ int wait_for_rdzv_done(struct util_context *util) * be cleared. Only retry once. */ rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, - "RDZV cleanup "); + "RDZV cleanup"); if (retries++ ||(rc != -EAGAIN && rc != -ETIMEDOUT)) break; fprintf(stderr, "Retrying...\n"); @@ -798,7 +798,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/send_lat.c b/utils/send_lat.c index 150594d..fee14e6 100644 --- a/utils/send_lat.c +++ b/utils/send_lat.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI RDMA send latency benchmark */ @@ -360,7 +360,7 @@ int do_single_iteration(struct util_context *util) util->dma_cmd.full_dma.request_len = util->size; - rc = ctrl_barrier(ctrl, NO_TIMEOUT, "sync"); + rc = ctrl_barrier(ctrl, NO_TIMEOUT, "Sync"); if (rc) return rc; @@ -617,7 +617,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/utils_common.c b/utils/utils_common.c index 616c8ff..f197276 100644 --- a/utils/utils_common.c +++ b/utils/utils_common.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2024 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI benchmark common functions */ @@ -551,7 +551,6 @@ int run_bw_active(struct util_context *util, uint64_t start_time; uint64_t elapsed; uint64_t duration_usec; - uint64_t postrun_timeout; if (!util || !do_iter) return -EINVAL; @@ -566,47 +565,33 @@ int run_bw_active(struct util_context *util, * when running for a duration rather than a number of iterations. */ duration_usec = opts->duration * SEC2USEC; + + rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, "Pre-run"); + if (rc) + return rc; + start_time = get_time_usec(util->cxi.dev); - if (ctrl->connected && opts->bidirectional) { - rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, "Pre-run "); - if (rc) - return rc; - } util->count = 0; elapsed = 0; - while (((!opts->duration && util->count < opts->iters) || - (opts->duration && elapsed < duration_usec))) { + while ((!opts->duration && util->count < opts->iters) || + (opts->duration && elapsed < duration_usec)) { rc = do_iter(util); - if (rc != 0) { - if (rc != EAGAIN) { - fprintf(stderr, "Iteration failed: %s\n", - strerror(abs(rc))); - return rc; - } - } else { + if (!rc) util->count++; + else if (rc != EAGAIN) { + fprintf(stderr, "Iteration failed: %s\n", + strerror(abs(rc))); + return rc; } if (opts->duration) elapsed = get_time_usec(util->cxi.dev) - start_time; } - if (!opts->duration) - elapsed = get_time_usec(util->cxi.dev) - start_time; - - if (ctrl->connected) { - postrun_timeout = get_post_run_timeout(elapsed); - rc = ctrl_barrier(ctrl, postrun_timeout, "Post-run "); - if (rc) { - if (rc == -ETIMEDOUT) { - fprintf(stderr, - "Post-run peer did not respond within %ld usec\n", - postrun_timeout); - } - return rc; - } - } + rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, "Post-run"); + if (rc) + return rc; /* Final elapsed time update */ elapsed = get_time_usec(util->cxi.dev) - start_time; @@ -624,7 +609,11 @@ int run_bw_passive(struct util_context *util) if (!util) return -EINVAL; - rc = ctrl_barrier(&util->ctrl, NO_TIMEOUT, "Post-run "); + rc = ctrl_barrier(&util->ctrl, NO_TIMEOUT, "Pre-run"); + if (rc) + return rc; + + rc = ctrl_barrier(&util->ctrl, NO_TIMEOUT, "Post-run"); if (rc) return rc; @@ -717,7 +706,7 @@ int run_lat_active(struct util_context *util, } if (ctrl->connected) { - rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, "Post-run "); + rc = ctrl_barrier(ctrl, DFLT_HANDSHAKE_TIMEOUT, "Post-run"); if (rc) goto done; } @@ -769,7 +758,7 @@ int run_lat_passive(struct util_context *util) if (!util) return -EINVAL; - rc = ctrl_barrier(&util->ctrl, NO_TIMEOUT, "Post-run "); + rc = ctrl_barrier(&util->ctrl, NO_TIMEOUT, "Post-run"); if (rc) return rc; print_separator(strlen(util->header)); diff --git a/utils/utils_common.h b/utils/utils_common.h index e94872f..37279ea 100644 --- a/utils/utils_common.h +++ b/utils/utils_common.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI benchmark common structures and functions */ @@ -71,7 +71,7 @@ /* Simple control message header to verify sizes */ struct ctrl_msg { uint32_t pyld_len; - uint8_t pyld[0]; + /* payload follows */ } __attribute__((packed)); #define MAX_CTRL_DATA_BYTES (CTRL_MSG_BUF_SZ - sizeof(struct ctrl_msg)) @@ -92,7 +92,7 @@ struct ctrl_connection { struct timeval last_rcvtmo; int fd; - char buf[CTRL_MSG_BUF_SZ]; + char buf[CTRL_MSG_BUF_SZ]; /* unused */ }; /* Combined buffer and associated CXI Memory Descriptor */ @@ -354,9 +354,6 @@ int ctrl_connect(struct ctrl_connection *ctrl, const char *name, const char *version, struct util_opts *opts, struct cxi_ep_addr *loc_addr, struct cxi_ep_addr *rmt_addr); int ctrl_close(struct ctrl_connection *ctrl); -int ctrl_send(struct ctrl_connection *ctrl, const void *buf, size_t size); -int ctrl_recv(struct ctrl_connection *ctrl, void *buf, size_t size, - struct timeval *tmo_tv); int ctrl_exchange_data(struct ctrl_connection *ctrl, const void *client_buf, size_t cbuf_size, void *server_buf, size_t sbuf_size); int ctrl_barrier(struct ctrl_connection *ctrl, uint64_t tmo_usec, char *label); diff --git a/utils/write_bw.c b/utils/write_bw.c index 2bbbe21..0df7142 100644 --- a/utils/write_bw.c +++ b/utils/write_bw.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI RDMA write bandwidth benchmark */ @@ -440,7 +440,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup; diff --git a/utils/write_lat.c b/utils/write_lat.c index a390064..59e8de3 100644 --- a/utils/write_lat.c +++ b/utils/write_lat.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause - * Copyright 2021-2023 Hewlett Packard Enterprise Development LP + * Copyright 2021-2025 Hewlett Packard Enterprise Development LP */ /* CXI RDMA write latency benchmark */ @@ -394,7 +394,7 @@ int main(int argc, char **argv) /* Signal ready */ rc = ctrl_barrier(ctrl, NO_TIMEOUT, - ctrl->is_server ? "Client " : "Server "); + ctrl->is_server ? "Client" : "Server"); if (rc) goto cleanup;