Created
March 14, 2016 11:25
-
-
Save joerns/c9a25e9b9e1fab3ea92b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <rdma/fabric.h> | |
#include <rdma/fi_eq.h> | |
#include <rdma/fi_endpoint.h> | |
#include <rdma/fi_cm.h> | |
#include <rdma/fi_errno.h> | |
#include <string.h> | |
#include <netinet/in.h> | |
#include <netdb.h> | |
#include <arpa/inet.h> | |
#include <sys/socket.h> | |
#include <sys/epoll.h> | |
#define ERROR(x, ...) \ | |
do { \ | |
fprintf(stderr, "error: "x"\n", __VA_ARGS__);\ | |
exit(EXIT_FAILURE);\ | |
} while(0) | |
union sockaddr_any { | |
struct sockaddr sa; | |
struct sockaddr_in sin; | |
struct sockaddr_in6 sin6; | |
struct sockaddr_storage ss; | |
}; | |
struct listen_socket | |
{ | |
struct fi_info* fi; | |
struct fid_fabric *fabric; | |
struct fid_eq *eq; | |
struct fid_pep *pep; | |
int fd; | |
}; | |
static const char * | |
sockaddrstr(const union sockaddr_any *addr, socklen_t len, char *buf, size_t buflen, unsigned short* port) | |
{ | |
static char namebuf[BUFSIZ]; | |
static char servbuf[BUFSIZ]; | |
int errcode; | |
if ((errcode = getnameinfo(&addr->sa, len, namebuf, BUFSIZ, | |
servbuf, BUFSIZ, | |
NI_NUMERICHOST | NI_NUMERICSERV))) | |
{ | |
if (errcode != EAI_SYSTEM) { | |
ERROR("getnameinfo failed: %s", gai_strerror(errcode)); | |
} else { | |
ERROR("getnameinfo failed: %s", strerror(errno)); | |
} | |
} | |
snprintf(buf, buflen, "%s", namebuf); | |
*port = atoi(servbuf); | |
return buf; | |
} | |
static void | |
print_endpoint(struct listen_socket* socket) | |
{ | |
union sockaddr_any addr; | |
memset(&addr, 0, sizeof(addr)); | |
size_t addrlen = sizeof(addr); | |
int ret; | |
if((ret = fi_getname(&socket->pep->fid, &addr, &addrlen))) | |
{ | |
ERROR("fi_getname failed: %d '%s'", ret, fi_strerror(-ret)); | |
} | |
char buf[128]; | |
unsigned short port; | |
const char* straddr = sockaddrstr(&addr, addrlen, buf, 128, &port); | |
printf("endpoint = %s:%d\n", straddr, port); | |
} | |
void listen_server(struct listen_socket* socket, const char* address) | |
{ | |
int ret; | |
struct epoll_event ev; | |
struct fi_info* hints; | |
struct fi_eq_attr eq_attr = { | |
.wait_obj = FI_WAIT_FD | |
}; | |
hints = fi_allocinfo(); | |
hints->ep_attr->type = FI_EP_MSG; | |
hints->caps = FI_MSG; | |
hints->mode = FI_LOCAL_MR; | |
if(ret = fi_getinfo(FI_VERSION(1, 0), address, "0", FI_SOURCE, hints, &socket->fi)) { | |
ERROR("fi_getinfo failed: %d '%s'", ret, fi_strerror(-ret)); | |
} | |
//printf("info: %s\n", fi_tostr(socket->fi, FI_TYPE_INFO)); | |
if(ret = fi_fabric(socket->fi->fabric_attr, &socket->fabric, NULL)) { | |
ERROR("fi_fabric failed: %d", ret); | |
} | |
if(ret = fi_eq_open(socket->fabric, &eq_attr, &socket->eq, NULL)) { | |
ERROR("fi_eq_open failed: %d", ret); | |
} | |
if(ret = fi_passive_ep(socket->fabric, socket->fi, &socket->pep, NULL)) { | |
ERROR("fi_passive_ep failed: %d", ret); | |
} | |
if(ret = fi_pep_bind(socket->pep, &socket->eq->fid, 0)) { | |
ERROR("fi_pep_bind failed: %d", ret); | |
} | |
if(ret = fi_listen(socket->pep)) { | |
ERROR("fi_listen failed: %d '%s'", ret, fi_strerror(-ret)); | |
} | |
print_endpoint(socket); | |
} | |
int main() | |
{ | |
int ret; | |
struct listen_socket lsocket; | |
listen_server(&lsocket, "127.0.0.1"); | |
listen_server(&lsocket, "0.0.0.0"); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output of the above program:
The first time with the fixed IP address the port gets auto-assigned, but the second time not.