fabtests/include/shared.h (422 lines of code) (raw):
/*
* Copyright (c) 2013-2017 Intel Corporation. All rights reserved.
* Copyright (c) 2014-2017, Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under the 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.
*/
#ifndef _SHARED_H_
#define _SHARED_H_
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <inttypes.h>
#include <netinet/tcp.h>
#include <sys/uio.h>
#include <stdbool.h>
#include <rdma/fabric.h>
#include <rdma/fi_rma.h>
#include <rdma/fi_domain.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FT_FIVERSION
#define FT_FIVERSION FI_VERSION(1,9)
#endif
#include "ft_osd.h"
#define OFI_UTIL_PREFIX "ofi_"
#define OFI_NAME_DELIM ';'
#define OFI_MR_BASIC_MAP (FI_MR_ALLOCATED | FI_MR_PROV_KEY | FI_MR_VIRT_ADDR)
/* exit codes must be 0-255 */
static inline int ft_exit_code(int ret)
{
int absret = ret < 0 ? -ret : ret;
return absret > 255 ? EXIT_FAILURE : absret;
}
#define ft_sa_family(addr) (((struct sockaddr *)(addr))->sa_family)
struct test_size_param {
size_t size;
int enable_flags;
};
extern struct test_size_param test_size[];
extern const unsigned int test_cnt;
#define TEST_CNT test_cnt
#define FT_ENABLE_ALL (~0)
#define FT_DEFAULT_SIZE (1 << 0)
enum precision {
NANO = 1,
MICRO = 1000,
MILLI = 1000000,
};
enum ft_comp_method {
FT_COMP_SPIN = 0,
FT_COMP_SREAD,
FT_COMP_WAITSET,
FT_COMP_WAIT_FD,
FT_COMP_YIELD,
};
enum {
FT_OPT_ACTIVE = 1 << 0,
FT_OPT_ITER = 1 << 1,
FT_OPT_SIZE = 1 << 2,
FT_OPT_RX_CQ = 1 << 3,
FT_OPT_TX_CQ = 1 << 4,
FT_OPT_RX_CNTR = 1 << 5,
FT_OPT_TX_CNTR = 1 << 6,
FT_OPT_VERIFY_DATA = 1 << 7,
FT_OPT_ALIGN = 1 << 8,
FT_OPT_BW = 1 << 9,
FT_OPT_CQ_SHARED = 1 << 10,
FT_OPT_OOB_SYNC = 1 << 11,
FT_OPT_SKIP_MSG_ALLOC = 1 << 12,
FT_OPT_SKIP_REG_MR = 1 << 13,
FT_OPT_OOB_ADDR_EXCH = 1 << 14,
FT_OPT_ALLOC_MULT_MR = 1 << 15,
FT_OPT_SERVER_PERSIST = 1 << 16,
FT_OPT_OOB_CTRL = FT_OPT_OOB_SYNC | FT_OPT_OOB_ADDR_EXCH,
};
/* for RMA tests --- we want to be able to select fi_writedata, but there is no
* constant in libfabric for this */
enum ft_rma_opcodes {
FT_RMA_READ = 1,
FT_RMA_WRITE,
FT_RMA_WRITEDATA,
};
enum ft_atomic_opcodes {
FT_ATOMIC_BASE,
FT_ATOMIC_FETCH,
FT_ATOMIC_COMPARE,
};
enum op_state {
OP_DONE = 0,
OP_PENDING
};
struct ft_context {
char *buf;
void *desc;
enum op_state state;
struct fid_mr *mr;
struct fi_context2 context;
};
struct ft_opts {
int iterations;
int warmup_iterations;
size_t transfer_size;
int window_size;
int av_size;
int verbose;
int tx_cq_size;
int rx_cq_size;
char *src_port;
char *dst_port;
char *src_addr;
char *dst_addr;
char *av_name;
int sizes_enabled;
int options;
enum ft_comp_method comp_method;
int machr;
enum ft_rma_opcodes rma_op;
char *oob_port;
int argc;
int num_connections;
uint64_t mr_mode;
/* Fail if the selected provider does not support FI_MSG_PREFIX. */
int force_prefix;
char **argv;
};
extern struct fi_info *fi_pep, *fi, *hints;
extern struct fid_fabric *fabric;
extern struct fid_wait *waitset;
extern struct fid_domain *domain;
extern struct fid_poll *pollset;
extern struct fid_pep *pep;
extern struct fid_ep *ep, *alias_ep;
extern struct fid_cq *txcq, *rxcq;
extern struct fid_cntr *txcntr, *rxcntr;
extern struct fid_mr *mr, no_mr;
extern void *mr_desc;
extern struct fid_av *av;
extern struct fid_eq *eq;
extern struct fid_mc *mc;
extern fi_addr_t remote_fi_addr;
extern char *buf, *tx_buf, *rx_buf;
extern struct ft_context *tx_ctx_arr, *rx_ctx_arr;
extern char **tx_mr_bufs, **rx_mr_bufs;
extern size_t buf_size, tx_size, rx_size, tx_mr_size, rx_mr_size;
extern int tx_fd, rx_fd;
extern int timeout;
extern struct fi_context tx_ctx, rx_ctx;
extern uint64_t remote_cq_data;
extern uint64_t tx_seq, rx_seq, tx_cq_cntr, rx_cq_cntr;
extern struct fi_av_attr av_attr;
extern struct fi_eq_attr eq_attr;
extern struct fi_cq_attr cq_attr;
extern struct fi_cntr_attr cntr_attr;
extern struct fi_rma_iov remote;
extern char test_name[50];
extern struct timespec start, end;
extern struct ft_opts opts;
void ft_parseinfo(int op, char *optarg, struct fi_info *hints,
struct ft_opts *opts);
void ft_parse_addr_opts(int op, char *optarg, struct ft_opts *opts);
void ft_parsecsopts(int op, char *optarg, struct ft_opts *opts);
int ft_parse_rma_opts(int op, char *optarg, struct fi_info *hints,
struct ft_opts *opts);
void ft_addr_usage();
void ft_usage(char *name, char *desc);
void ft_mcusage(char *name, char *desc);
void ft_csusage(char *name, char *desc);
void ft_fill_buf(void *buf, int size);
int ft_check_buf(void *buf, int size);
int ft_check_opts(uint64_t flags);
uint64_t ft_init_cq_data(struct fi_info *info);
int ft_sock_listen(char *node, char *service);
int ft_sock_connect(char *node, char *service);
int ft_sock_accept();
int ft_sock_send(int fd, void *msg, size_t len);
int ft_sock_recv(int fd, void *msg, size_t len);
int ft_sock_sync(int value);
void ft_sock_shutdown(int fd);
extern int (*ft_mr_alloc_func)(void);
extern uint64_t ft_tag;
extern int ft_parent_proc;
extern int ft_socket_pair[2];
extern int sock;
extern int listen_sock;
#define ADDR_OPTS "B:P:s:a:b::E::C:"
#define FAB_OPTS "f:d:p:"
#define INFO_OPTS FAB_OPTS "e:M:"
#define CS_OPTS ADDR_OPTS "I:S:mc:t:w:l"
#define NO_CQ_DATA 0
extern char default_port[8];
#define INIT_OPTS (struct ft_opts) \
{ .options = FT_OPT_RX_CQ | FT_OPT_TX_CQ, \
.iterations = 1000, \
.warmup_iterations = 10, \
.transfer_size = 1024, \
.window_size = 64, \
.av_size = 1, \
.tx_cq_size = 0, \
.rx_cq_size = 0, \
.verbose = 0, \
.sizes_enabled = FT_DEFAULT_SIZE, \
.rma_op = FT_RMA_WRITE, \
.oob_port = NULL, \
.mr_mode = FI_MR_LOCAL | OFI_MR_BASIC_MAP, \
.argc = argc, .argv = argv \
}
#define FT_STR_LEN 32
#define FT_MAX_CTRL_MSG 256
#define FT_MR_KEY 0xC0DE
#define FT_TX_MR_KEY (FT_MR_KEY + 1)
#define FT_RX_MR_KEY 0xFFFF
#define FT_MSG_MR_ACCESS (FI_SEND | FI_RECV)
#define FT_RMA_MR_ACCESS (FI_READ | FI_WRITE | FI_REMOTE_READ | FI_REMOTE_WRITE)
int ft_getsrcaddr(char *node, char *service, struct fi_info *hints);
int ft_read_addr_opts(char **node, char **service, struct fi_info *hints,
uint64_t *flags, struct ft_opts *opts);
char *size_str(char str[FT_STR_LEN], long long size);
char *cnt_str(char str[FT_STR_LEN], long long cnt);
int size_to_count(int size);
size_t datatype_to_size(enum fi_datatype datatype);
static inline int ft_use_size(int index, int enable_flags)
{
return test_size[index].size <= fi->ep_attr->max_msg_size &&
((enable_flags == FT_ENABLE_ALL) ||
(enable_flags & test_size[index].enable_flags));
}
#define FT_PRINTERR(call, retv) \
do { fprintf(stderr, call "(): %s:%d, ret=%d (%s)\n", __FILE__, __LINE__, \
(int) (retv), fi_strerror((int) -(retv))); } while (0)
#define FT_LOG(level, fmt, ...) \
do { fprintf(stderr, "[%s] fabtests:%s:%d: " fmt "\n", level, __FILE__, \
__LINE__, ##__VA_ARGS__); } while (0)
#define FT_ERR(fmt, ...) FT_LOG("error", fmt, ##__VA_ARGS__)
#define FT_WARN(fmt, ...) FT_LOG("warn", fmt, ##__VA_ARGS__)
#if ENABLE_DEBUG
#define FT_DEBUG(fmt, ...) FT_LOG("debug", fmt, ##__VA_ARGS__)
#else
#define FT_DEBUG(fmt, ...)
#endif
#define FT_EQ_ERR(eq, entry, buf, len) \
FT_ERR("eq_readerr (Provider errno: %d) : %s", \
entry.prov_errno, fi_eq_strerror(eq, entry.prov_errno, \
entry.err_data, \
buf, len)) \
#define FT_CQ_ERR(cq, entry, buf, len) \
FT_ERR("cq_readerr (Provider errno: %d) : %s", \
entry.prov_errno, fi_cq_strerror(cq, entry.prov_errno, \
entry.err_data, \
buf, len)) \
#define FT_CLOSE_FID(fd) \
do { \
int ret; \
if ((fd)) { \
ret = fi_close(&(fd)->fid); \
if (ret) \
FT_ERR("fi_close: %s(%d) fid %d", \
fi_strerror(-ret), \
ret, \
(int) (fd)->fid.fclass); \
fd = NULL; \
} \
} while (0)
#define FT_CLOSEV_FID(fd, cnt) \
do { \
int i; \
if (!(fd)) \
break; \
for (i = 0; i < (cnt); i++) { \
FT_CLOSE_FID((fd)[i]); \
} \
} while (0)
#define FT_EP_BIND(ep, fd, flags) \
do { \
int ret; \
if ((fd)) { \
ret = fi_ep_bind((ep), &(fd)->fid, (flags)); \
if (ret) { \
FT_PRINTERR("fi_ep_bind", ret); \
return ret; \
} \
} \
} while (0)
int ft_alloc_bufs();
int ft_open_fabric_res();
int ft_getinfo(struct fi_info *hints, struct fi_info **info);
int ft_init_fabric();
int ft_init_oob();
int ft_start_server();
int ft_server_connect();
int ft_client_connect();
int ft_init_fabric_cm(void);
int ft_complete_connect(struct fid_ep *ep, struct fid_eq *eq);
int ft_retrieve_conn_req(struct fid_eq *eq, struct fi_info **fi);
int ft_accept_connection(struct fid_ep *ep, struct fid_eq *eq);
int ft_connect_ep(struct fid_ep *ep,
struct fid_eq *eq, fi_addr_t *remote_addr);
int ft_alloc_ep_res(struct fi_info *fi);
int ft_alloc_active_res(struct fi_info *fi);
int ft_enable_ep_recv(void);
int ft_enable_ep(struct fid_ep *ep, struct fid_eq *eq, struct fid_av *av,
struct fid_cq *txcq, struct fid_cq *rxcq,
struct fid_cntr *txcntr, struct fid_cntr *rxcntr);
int ft_init_alias_ep(uint64_t flags);
int ft_av_insert(struct fid_av *av, void *addr, size_t count, fi_addr_t *fi_addr,
uint64_t flags, void *context);
int ft_init_av(void);
int ft_join_mc(void);
int ft_init_av_dst_addr(struct fid_av *av_ptr, struct fid_ep *ep_ptr,
fi_addr_t *remote_addr);
int ft_init_av_addr(struct fid_av *av, struct fid_ep *ep,
fi_addr_t *addr);
int ft_exchange_keys(struct fi_rma_iov *peer_iov);
void ft_free_res();
void init_test(struct ft_opts *opts, char *test_name, size_t test_name_len);
static inline void ft_start(void)
{
opts.options |= FT_OPT_ACTIVE;
clock_gettime(CLOCK_MONOTONIC, &start);
}
static inline void ft_stop(void)
{
clock_gettime(CLOCK_MONOTONIC, &end);
opts.options &= ~FT_OPT_ACTIVE;
}
/* Set the FI_MSG_PREFIX mode bit in the given fi_info structure and also set
* the option bit in the given opts structure. If using ft_getinfo, it will
* return -ENODATA if the provider clears the application requested mdoe bit.
*/
static inline void ft_force_prefix(struct fi_info *info, struct ft_opts *opts)
{
info->mode |= FI_MSG_PREFIX;
opts->force_prefix = 1;
}
/* If force_prefix was not requested, just continue. If it was requested,
* return true if it was respected by the provider.
*/
static inline bool ft_check_prefix_forced(struct fi_info *info,
struct ft_opts *opts)
{
if (opts->force_prefix) {
return (info->tx_attr->mode & FI_MSG_PREFIX) &&
(info->rx_attr->mode & FI_MSG_PREFIX);
}
/* Continue if forced prefix wasn't requested. */
return true;
}
int ft_sync(void);
int ft_sync_pair(int status);
int ft_fork_and_pair(void);
int ft_wait_child(void);
int ft_finalize(void);
int ft_finalize_ep(struct fid_ep *ep);
size_t ft_rx_prefix_size(void);
size_t ft_tx_prefix_size(void);
ssize_t ft_post_rx(struct fid_ep *ep, size_t size, void *ctx);
ssize_t ft_post_rx_buf(struct fid_ep *ep, size_t size, void *ctx,
void *op_buf, void *op_mr_desc, uint64_t op_tag);
ssize_t ft_post_tx(struct fid_ep *ep, fi_addr_t fi_addr, size_t size,
uint64_t data, void *ctx);
ssize_t ft_post_tx_buf(struct fid_ep *ep, fi_addr_t fi_addr, size_t size,
uint64_t data, void *ctx,
void *op_buf, void *op_mr_desc, uint64_t op_tag);
ssize_t ft_rx(struct fid_ep *ep, size_t size);
ssize_t ft_tx(struct fid_ep *ep, fi_addr_t fi_addr, size_t size, void *ctx);
ssize_t ft_inject(struct fid_ep *ep, fi_addr_t fi_addr, size_t size);
ssize_t ft_post_rma(enum ft_rma_opcodes op, struct fid_ep *ep, size_t size,
struct fi_rma_iov *remote, void *context);
ssize_t ft_rma(enum ft_rma_opcodes op, struct fid_ep *ep, size_t size,
struct fi_rma_iov *remote, void *context);
ssize_t ft_post_rma_inject(enum ft_rma_opcodes op, struct fid_ep *ep, size_t size,
struct fi_rma_iov *remote);
ssize_t ft_post_atomic(enum ft_atomic_opcodes opcode, struct fid_ep *ep,
void *compare, void *compare_desc, void *result,
void *result_desc, struct fi_rma_iov *remote,
enum fi_datatype datatype, enum fi_op atomic_op,
void *context);
int check_base_atomic_op(struct fid_ep *endpoint, enum fi_op op,
enum fi_datatype datatype, size_t *count);
int check_fetch_atomic_op(struct fid_ep *endpoint, enum fi_op op,
enum fi_datatype datatype, size_t *count);
int check_compare_atomic_op(struct fid_ep *endpoint, enum fi_op op,
enum fi_datatype datatype, size_t *count);
int ft_cq_readerr(struct fid_cq *cq);
int ft_get_rx_comp(uint64_t total);
int ft_get_tx_comp(uint64_t total);
int ft_recvmsg(struct fid_ep *ep, fi_addr_t fi_addr,
size_t size, void *ctx, int flags);
int ft_sendmsg(struct fid_ep *ep, fi_addr_t fi_addr,
size_t size, void *ctx, int flags);
int ft_cq_read_verify(struct fid_cq *cq, void *op_context);
void eq_readerr(struct fid_eq *eq, const char *eq_str);
int64_t get_elapsed(const struct timespec *b, const struct timespec *a,
enum precision p);
void show_perf(char *name, size_t tsize, int iters, struct timespec *start,
struct timespec *end, int xfers_per_iter);
void show_perf_mr(size_t tsize, int iters, struct timespec *start,
struct timespec *end, int xfers_per_iter, int argc, char *argv[]);
int ft_send_recv_greeting(struct fid_ep *ep);
int ft_send_greeting(struct fid_ep *ep);
int ft_recv_greeting(struct fid_ep *ep);
int ft_accept_next_client();
int check_recv_msg(const char *message);
uint64_t ft_info_to_mr_access(struct fi_info *info);
int ft_alloc_bit_combo(uint64_t fixed, uint64_t opt, uint64_t **combos, int *len);
void ft_free_bit_combo(uint64_t *combo);
int ft_cntr_open(struct fid_cntr **cntr);
const char *ft_util_name(const char *str, size_t *len);
const char *ft_core_name(const char *str, size_t *len);
char **ft_split_and_alloc(const char *s, const char *delim, size_t *count);
void ft_free_string_array(char **s);
#define FT_PROCESS_QUEUE_ERR(readerr, rd, queue, fn, str) \
do { \
if (rd == -FI_EAVAIL) { \
readerr(queue, fn " " str); \
} else { \
FT_PRINTERR(fn, rd); \
} \
} while (0)
#define FT_PROCESS_EQ_ERR(rd, eq, fn, str) \
FT_PROCESS_QUEUE_ERR(eq_readerr, rd, eq, fn, str)
#define FT_OPTS_USAGE_FORMAT "%-30s %s"
#define FT_PRINT_OPTS_USAGE(opt, desc) fprintf(stderr, FT_OPTS_USAGE_FORMAT "\n", opt, desc)
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
#define TEST_ENUM_SET_N_RETURN(str, len, enum_val, type, data) \
TEST_SET_N_RETURN(str, len, #enum_val, enum_val, type, data)
#define TEST_SET_N_RETURN(str, len, val_str, val, type, data) \
do { \
if (!strncmp(str, val_str, len)) { \
*(type *)(data) = val; \
return 0; \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif /* _SHARED_H_ */