| /* |
| * Copyright (c) 2005-2012 Intel Corporation. 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. |
| * |
| * $Id$ |
| */ |
| |
| #include <stdlib.h> |
| #include <sys/types.h> |
| #include <endian.h> |
| #include <poll.h> |
| #include <time.h> |
| #include <stdbool.h> |
| #include <pthread.h> |
| |
| #include <rdma/rdma_cma.h> |
| #include <rdma/rsocket.h> |
| #include <infiniband/ib.h> |
| |
| /* Defined in common.c; used in all rsocket demos to determine whether to use |
| * rsocket calls or standard socket calls. |
| */ |
| extern int use_rs; |
| |
| static inline int rs_socket(int f, int t, int p) |
| { |
| int fd; |
| |
| if (!use_rs) |
| return socket(f, t, p); |
| |
| fd = rsocket(f, t, p); |
| if (fd < 0) { |
| if (t == SOCK_STREAM && errno == ENODEV) |
| fprintf(stderr, "No RDMA devices were detected\n"); |
| else |
| perror("rsocket failed"); |
| } |
| return fd; |
| } |
| |
| #define rs_bind(s,a,l) use_rs ? rbind(s,a,l) : bind(s,a,l) |
| #define rs_listen(s,b) use_rs ? rlisten(s,b) : listen(s,b) |
| #define rs_connect(s,a,l) use_rs ? rconnect(s,a,l) : connect(s,a,l) |
| #define rs_accept(s,a,l) use_rs ? raccept(s,a,l) : accept(s,a,l) |
| #define rs_shutdown(s,h) use_rs ? rshutdown(s,h) : shutdown(s,h) |
| #define rs_close(s) use_rs ? rclose(s) : close(s) |
| #define rs_recv(s,b,l,f) use_rs ? rrecv(s,b,l,f) : recv(s,b,l,f) |
| #define rs_send(s,b,l,f) use_rs ? rsend(s,b,l,f) : send(s,b,l,f) |
| #define rs_recvfrom(s,b,l,f,a,al) \ |
| use_rs ? rrecvfrom(s,b,l,f,a,al) : recvfrom(s,b,l,f,a,al) |
| #define rs_sendto(s,b,l,f,a,al) \ |
| use_rs ? rsendto(s,b,l,f,a,al) : sendto(s,b,l,f,a,al) |
| #define rs_poll(f,n,t) use_rs ? rpoll(f,n,t) : poll(f,n,t) |
| #define rs_fcntl(s,c,p) use_rs ? rfcntl(s,c,p) : fcntl(s,c,p) |
| #define rs_setsockopt(s,l,n,v,ol) \ |
| use_rs ? rsetsockopt(s,l,n,v,ol) : setsockopt(s,l,n,v,ol) |
| #define rs_getsockopt(s,l,n,v,ol) \ |
| use_rs ? rgetsockopt(s,l,n,v,ol) : getsockopt(s,l,n,v,ol) |
| |
| union socket_addr { |
| struct sockaddr sa; |
| struct sockaddr_in sin; |
| struct sockaddr_in6 sin6; |
| }; |
| |
| enum rs_optimization { |
| opt_mixed, |
| opt_latency, |
| opt_bandwidth |
| }; |
| |
| int get_rdma_addr(const char *src, const char *dst, const char *port, |
| struct rdma_addrinfo *hints, struct rdma_addrinfo **rai); |
| |
| int oob_server_setup(const char *src_addr, const char *port, int *sock); |
| int oob_client_setup(const char *dst_addr, const char *port, int *sock); |
| int oob_sendrecv(int sock, char val); |
| int oob_recvsend(int sock, char val); |
| |
| void size_str(char *str, size_t ssize, long long size); |
| void cnt_str(char *str, size_t ssize, long long cnt); |
| int size_to_count(int size); |
| void format_buf(void *buf, int size); |
| int verify_buf(void *buf, int size); |
| int do_poll(struct pollfd *fds, int timeout); |
| |
| struct rdma_event_channel *create_event_channel(void); |
| |
| static inline uint64_t gettime_ns(void) |
| { |
| struct timespec now; |
| |
| clock_gettime(CLOCK_MONOTONIC, &now); |
| return now.tv_sec * 1000000000 + now.tv_nsec; |
| } |
| |
| static inline uint64_t gettime_us(void) |
| { |
| return gettime_ns() / 1000; |
| } |
| |
| static inline int sleep_us(unsigned int time_us) |
| { |
| struct timespec spec; |
| |
| if (!time_us) |
| return 0; |
| |
| spec.tv_sec = 0; |
| spec.tv_nsec = time_us * 1000; |
| return nanosleep(&spec, NULL); |
| } |
| |
| |
| struct work_item { |
| struct work_item *next; |
| void (*work_handler)(struct work_item *item); |
| }; |
| |
| struct work_queue { |
| pthread_mutex_t lock; |
| pthread_cond_t cond; |
| |
| pthread_t *thread; |
| int thread_cnt; |
| bool running; |
| |
| struct work_item *head; |
| struct work_item *tail; |
| }; |
| |
| int wq_init(struct work_queue *wq, int thread_cnt); |
| void wq_cleanup(struct work_queue *wq); |
| void wq_insert(struct work_queue *wq, struct work_item *item, |
| void (*work_handler)(struct work_item *item)); |
| struct work_item *wq_remove(struct work_queue *wq); |