Blame tests/extra_api_tests/socketxtreme/server_tcp.c

Packit Service aa3af4
/* server_tcp.c
Packit Service aa3af4
 *
Packit Service aa3af4
 * build:
Packit Service aa3af4
 * epoll: gcc server_tcp.c -o server_tcp.out -DVMA_DEV="ens1f0" -DVMA_API=0 -I/usr/include
Packit Service aa3af4
 * xtreme: gcc server_tcp.c -o server_tcp.out -DVMA_DEV="ens1f0" -DVMA_API=1 -I<path to mellanox/vma_extra.h>
Packit Service aa3af4
 *
Packit Service aa3af4
 * usage:
Packit Service aa3af4
 * epoll: sudo server_tcp.out 1.1.3.15:17000
Packit Service aa3af4
 * socketxtreme: sudo env LD_PRELOAD=libvma.so server_tcp.out 1.1.3.15:17000
Packit Service aa3af4
 */
Packit Service aa3af4
#include <stdio.h>
Packit Service aa3af4
#include <stdlib.h>
Packit Service aa3af4
#include <string.h>
Packit Service aa3af4
#include <unistd.h>
Packit Service aa3af4
#include <errno.h>
Packit Service aa3af4
#include <sys/types.h>
Packit Service aa3af4
#include <sys/socket.h>
Packit Service aa3af4
#include <netdb.h>
Packit Service aa3af4
#include <netinet/in.h>
Packit Service aa3af4
#include <netinet/ip.h>
Packit Service aa3af4
#include <netinet/tcp.h>
Packit Service aa3af4
#include <arpa/inet.h>
Packit Service aa3af4
#include <fcntl.h>
Packit Service aa3af4
#include <getopt.h>
Packit Service aa3af4
#include <assert.h>
Packit Service aa3af4
#include <sys/select.h>
Packit Service aa3af4
#include <sys/mman.h> /* mlock */
Packit Service aa3af4
#include <sys/time.h>
Packit Service aa3af4
#include <time.h>
Packit Service aa3af4
#include <signal.h>
Packit Service aa3af4
#include <sys/epoll.h>
Packit Service aa3af4
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
#include <mellanox/vma_extra.h>
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
/* Bind to device */
Packit Service aa3af4
#if !defined(VMA_DEV)
Packit Service aa3af4
#define IB_DEV "ens3f1"
Packit Service aa3af4
#else
Packit Service aa3af4
#define QUOTE(name) #name
Packit Service aa3af4
#define STR(macro) QUOTE(macro)
Packit Service aa3af4
#define IB_DEV STR(VMA_DEV)
Packit Service aa3af4
#endif
Packit Service aa3af4
Packit Service aa3af4
/* Number of listeners */
Packit Service aa3af4
#define SFD_NUM 2
Packit Service aa3af4
Packit Service aa3af4
/* Number of peers */
Packit Service aa3af4
#define FD_NUM 10
Packit Service aa3af4
Packit Service aa3af4
#define EXIT_FAILURE 1
Packit Service aa3af4
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
static struct vma_api_t *_vma_api = NULL;
Packit Service aa3af4
static int _vma_ring_fd = -1;
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
static volatile int _done = 0;
Packit Service aa3af4
Packit Service aa3af4
static inline char *_addr2str(struct sockaddr_in *addr) {
Packit Service aa3af4
	static __thread char addrbuf[100];
Packit Service aa3af4
	inet_ntop(AF_INET, &addr->sin_addr, addrbuf, sizeof(addrbuf));
Packit Service aa3af4
	sprintf(addrbuf, "%s:%d", addrbuf, ntohs(addr->sin_port));
Packit Service aa3af4
Packit Service aa3af4
	return addrbuf;
Packit Service aa3af4
}
Packit Service aa3af4
Packit Service aa3af4
static void _proc_signal(int signal_id)
Packit Service aa3af4
{
Packit Service aa3af4
   _done = signal_id;
Packit Service aa3af4
}
Packit Service aa3af4
Packit Service aa3af4
static int _set_noblock(int fd)
Packit Service aa3af4
{
Packit Service aa3af4
	int rc = 0;
Packit Service aa3af4
	int flag;
Packit Service aa3af4
Packit Service aa3af4
	flag = fcntl(fd, F_GETFL);
Packit Service aa3af4
	if (flag < 0) {
Packit Service aa3af4
		rc = -errno;
Packit Service aa3af4
		printf("failed to get socket flags %s\n", strerror(errno));
Packit Service aa3af4
	}
Packit Service aa3af4
	flag |= O_NONBLOCK;
Packit Service aa3af4
	rc = fcntl(fd, F_SETFL, flag);
Packit Service aa3af4
	if (rc < 0) {
Packit Service aa3af4
		rc = -errno;
Packit Service aa3af4
		printf("failed to set socket flags %s\n", strerror(errno));
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	return rc;
Packit Service aa3af4
}
Packit Service aa3af4
Packit Service aa3af4
static int _tcp_create_and_bind(struct sockaddr_in *addr)
Packit Service aa3af4
{
Packit Service aa3af4
	int rc = 0;
Packit Service aa3af4
	int fd;
Packit Service aa3af4
	int flag;
Packit Service aa3af4
Packit Service aa3af4
	fd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
Packit Service aa3af4
	if (!fd) {
Packit Service aa3af4
		rc = -EBUSY;
Packit Service aa3af4
		printf("Failed to create socket\n");
Packit Service aa3af4
		goto err;
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
#if defined(IB_DEV)
Packit Service aa3af4
	rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)IB_DEV, strlen(IB_DEV));
Packit Service aa3af4
    if (rc < 0) {
Packit Service aa3af4
            printf("Failed to setsockopt(SO_BINDTODEVICE) for %s: %s\n", IB_DEV, strerror(errno));
Packit Service aa3af4
            exit(1);
Packit Service aa3af4
    }
Packit Service aa3af4
#endif
Packit Service aa3af4
Packit Service aa3af4
	flag = 1;
Packit Service aa3af4
	rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(int));
Packit Service aa3af4
	if (rc < 0) {
Packit Service aa3af4
		printf("Failed to setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
Packit Service aa3af4
		goto err;
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	rc = bind(fd, (struct sockaddr *) addr, sizeof(*addr));
Packit Service aa3af4
	if (rc < 0) {
Packit Service aa3af4
		rc = -EBUSY;
Packit Service aa3af4
		printf("Failed to bind socket\n");
Packit Service aa3af4
		goto err;
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	listen(fd, SOMAXCONN);
Packit Service aa3af4
Packit Service aa3af4
	printf("Listen  : fd=%d %s\n", fd, _addr2str((struct sockaddr_in *)addr));
Packit Service aa3af4
Packit Service aa3af4
err:
Packit Service aa3af4
	return (rc == 0 ? fd : (-1));
Packit Service aa3af4
}
Packit Service aa3af4
Packit Service aa3af4
int main(int argc, char *argv[])
Packit Service aa3af4
{
Packit Service aa3af4
	struct sigaction sa;
Packit Service aa3af4
	int ret = 0;
Packit Service aa3af4
	int efd;
Packit Service aa3af4
	int sfd[SFD_NUM];
Packit Service aa3af4
	int fd = -1;
Packit Service aa3af4
	int max_events = 0;
Packit Service aa3af4
	int max_sfd = 0;
Packit Service aa3af4
	struct epoll_event ev;
Packit Service aa3af4
	uint64_t event;
Packit Service aa3af4
	struct epoll_event *events = NULL;
Packit Service aa3af4
	struct conn_info {
Packit Service aa3af4
		int *fds;
Packit Service aa3af4
		int count;
Packit Service aa3af4
		char msg[1024];
Packit Service aa3af4
	} conns;
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
	struct vma_completion_t *vma_comps;
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
	int flag;
Packit Service aa3af4
	struct sockaddr_in addr;
Packit Service aa3af4
	struct sockaddr in_addr;
Packit Service aa3af4
	socklen_t in_len;
Packit Service aa3af4
	int i = 0;
Packit Service aa3af4
	int j = 0;
Packit Service aa3af4
Packit Service aa3af4
	/* catch SIGINT to exit */
Packit Service aa3af4
	memset(&sa, 0, sizeof(sa));
Packit Service aa3af4
	sa.sa_handler = _proc_signal;
Packit Service aa3af4
	sa.sa_flags = 0;
Packit Service aa3af4
	sigemptyset(&(sa.sa_mask));
Packit Service aa3af4
	if (sigaction(SIGINT, &sa, NULL) != 0) {
Packit Service aa3af4
        	perror("Failed to create signal handler");
Packit Service aa3af4
        	exit(EXIT_FAILURE);
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	/* Step:1 Initialize VMA API */
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
	_vma_api = vma_get_api();
Packit Service aa3af4
	if (_vma_api == NULL) {
Packit Service aa3af4
		printf("VMA Extra API not found\n");
Packit Service aa3af4
	}
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
	max_events = FD_NUM + sizeof(sfd) / sizeof(sfd[0]);
Packit Service aa3af4
Packit Service aa3af4
	conns.count = 0;
Packit Service aa3af4
	conns.fds = calloc(max_events, sizeof(*conns.fds));
Packit Service aa3af4
	assert(conns.fds);
Packit Service aa3af4
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
	vma_comps = calloc(max_events, sizeof(*vma_comps));
Packit Service aa3af4
	assert(vma_comps);
Packit Service aa3af4
#else
Packit Service aa3af4
	efd = epoll_create1(0);
Packit Service aa3af4
	assert(efd >= 0);
Packit Service aa3af4
Packit Service aa3af4
	events = calloc(max_events, sizeof(*events));
Packit Service aa3af4
	assert(events);
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
	printf("Launching <receiver> mode...\n");
Packit Service aa3af4
Packit Service aa3af4
	/* Step:2 Create listen socket */
Packit Service aa3af4
	for (i = 0; (i < SFD_NUM) && (argc > (i + 1)); i++) {
Packit Service aa3af4
		char *optarg = argv[i + 1];
Packit Service aa3af4
		char *token1 = NULL;
Packit Service aa3af4
		char *token2 = NULL;
Packit Service aa3af4
		const char s[2] = ":";
Packit Service aa3af4
Packit Service aa3af4
		token1 = strtok(optarg, s);
Packit Service aa3af4
		token2 = strtok(NULL, s);
Packit Service aa3af4
Packit Service aa3af4
		memset(&addr, 0, sizeof(addr));
Packit Service aa3af4
		addr.sin_family = PF_INET;
Packit Service aa3af4
		addr.sin_addr.s_addr = inet_addr(token1);
Packit Service aa3af4
		addr.sin_port = htons(atoi(token2));
Packit Service aa3af4
		sfd[i] = _tcp_create_and_bind(&addr);
Packit Service aa3af4
		if (sfd[i] < 0) {
Packit Service aa3af4
			perror("Failed to create socket");
Packit Service aa3af4
			exit(EXIT_FAILURE);
Packit Service aa3af4
		}
Packit Service aa3af4
		max_sfd++;
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	/* Step:3 Need to get ring or set listen socket */
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
	if (_vma_ring_fd < 0) {
Packit Service aa3af4
		_vma_api->get_socket_rings_fds(sfd[0], &_vma_ring_fd, 1);
Packit Service aa3af4
		assert((-1) != _vma_ring_fd);
Packit Service aa3af4
	}
Packit Service aa3af4
#else
Packit Service aa3af4
	for (i = 0; i < max_sfd; i++) {
Packit Service aa3af4
		ev.events = EPOLLIN;
Packit Service aa3af4
		ev.data.fd = sfd[i];
Packit Service aa3af4
		if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[i], &ev) == -1) {
Packit Service aa3af4
				perror("epoll_ctl() failed");
Packit Service aa3af4
			exit(EXIT_FAILURE);
Packit Service aa3af4
		}
Packit Service aa3af4
	}
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
	while (!_done) {
Packit Service aa3af4
		int n = 0;
Packit Service aa3af4
Packit Service aa3af4
		/* Step:4 Get events */
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
		while (0 == n) {
Packit Service aa3af4
			n = _vma_api->socketxtreme_poll(_vma_ring_fd, vma_comps, max_events, 0);
Packit Service aa3af4
		}
Packit Service aa3af4
#else
Packit Service aa3af4
		n = epoll_wait(efd, events, max_events, 0);
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
		for (j = 0; j < n; j++) {
Packit Service aa3af4
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
			event = vma_comps[j].events;
Packit Service aa3af4
			event |= ( event & VMA_SOCKETXTREME_PACKET ? EPOLLIN : 0);
Packit Service aa3af4
			fd = (event & VMA_SOCKETXTREME_NEW_CONNECTION_ACCEPTED ? vma_comps[j].listen_fd : vma_comps[j].user_data);
Packit Service aa3af4
#else
Packit Service aa3af4
			event = events[j].events;
Packit Service aa3af4
			fd = events[j].data.fd;
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
			if ((event & EPOLLERR) || (event & EPOLLHUP) || (event & EPOLLRDHUP)) {
Packit Service aa3af4
				printf("epoll error\n");
Packit Service aa3af4
				exit(EXIT_FAILURE);
Packit Service aa3af4
			}
Packit Service aa3af4
Packit Service aa3af4
			/* Step:5 Accept connections */
Packit Service aa3af4
			for (i = 0; i < max_sfd; i++) {
Packit Service aa3af4
				if (fd == sfd[i]) break;
Packit Service aa3af4
			}
Packit Service aa3af4
			if (i < max_sfd) {
Packit Service aa3af4
				in_len = sizeof(in_addr);
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
				fd = vma_comps[j].user_data;
Packit Service aa3af4
				memcpy(&in_addr, &vma_comps[j].src, in_len);
Packit Service aa3af4
#else
Packit Service aa3af4
				fd = accept(fd, &in_addr, &in_len);
Packit Service aa3af4
				if (fd < 0) {
Packit Service aa3af4
					printf("Accept failed: %s", strerror(errno));
Packit Service aa3af4
			        	exit(EXIT_FAILURE);
Packit Service aa3af4
				}
Packit Service aa3af4
				ev.events = EPOLLIN | EPOLLET;
Packit Service aa3af4
				ev.data.fd = fd;
Packit Service aa3af4
				if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1) {
Packit Service aa3af4
					printf("epoll_ctl() failed: %s", strerror(errno));
Packit Service aa3af4
					exit(EXIT_FAILURE);
Packit Service aa3af4
			    	}
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
				conns.fds[conns.count] = fd;
Packit Service aa3af4
				conns.count++;
Packit Service aa3af4
Packit Service aa3af4
				printf("Accepted: #%d by sfd=%d fd=%d from %s\n", conns.count, sfd[i], fd, _addr2str((struct sockaddr_in *)&in_addr));
Packit Service aa3af4
Packit Service aa3af4
				flag = 1;
Packit Service aa3af4
				ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
Packit Service aa3af4
				if (ret < 0) {
Packit Service aa3af4
					printf("Failed to disable NAGLE: %s\n", strerror(errno));
Packit Service aa3af4
			        	exit(EXIT_FAILURE);
Packit Service aa3af4
				}
Packit Service aa3af4
Packit Service aa3af4
				ret = _set_noblock(fd);
Packit Service aa3af4
				continue;
Packit Service aa3af4
			}
Packit Service aa3af4
Packit Service aa3af4
			/* Step:6 Process data */
Packit Service aa3af4
			if (event & EPOLLIN) {
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
			  printf("vma_comps[j].packet.num_bufs equal to %d \n", vma_comps[j].packet.num_bufs);
Packit Service aa3af4
				assert(1 == vma_comps[j].packet.num_bufs);
Packit Service aa3af4
				assert(sizeof(conns.msg) > vma_comps[j].packet.total_len);
Packit Service aa3af4
				memcpy(conns.msg, vma_comps[j].packet.buff_lst->payload, vma_comps[j].packet.total_len);
Packit Service aa3af4
				ret = vma_comps[j].packet.total_len;
Packit Service aa3af4
				_vma_api->socketxtreme_free_vma_packets(&vma_comps[j].packet, 1);
Packit Service aa3af4
#else
Packit Service aa3af4
				ret = recv(fd, conns.msg, sizeof(conns.msg), 0);
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
				if (ret < 0) {
Packit Service aa3af4
			        	exit(EXIT_FAILURE);
Packit Service aa3af4
				}
Packit Service aa3af4
				if (ret > 0) {
Packit Service aa3af4
					conns.msg[ret - 1] = '\0';
Packit Service aa3af4
				} else {
Packit Service aa3af4
					conns.msg[0] = '\0';
Packit Service aa3af4
				}
Packit Service aa3af4
				printf("Received: fd=%d ret=%d %s\n", fd, ret, conns.msg);
Packit Service aa3af4
			}
Packit Service aa3af4
		}
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
err:
Packit Service aa3af4
Packit Service aa3af4
	for (i = 0; i < max_sfd; i++) {
Packit Service aa3af4
		if (sfd[i] > 0) {
Packit Service aa3af4
			close(sfd[i]);
Packit Service aa3af4
		}
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
	for (i = 0; i < conns.count; i++) {
Packit Service aa3af4
		if (conns.fds[i] > 0) {
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
#else
Packit Service aa3af4
			epoll_ctl(efd, EPOLL_CTL_DEL, conns.fds[i], NULL);
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
			close(conns.fds[i]);
Packit Service aa3af4
		}
Packit Service aa3af4
	}
Packit Service aa3af4
	if (conns.fds) {
Packit Service aa3af4
		free(conns.fds);
Packit Service aa3af4
	}
Packit Service aa3af4
Packit Service aa3af4
#if defined(VMA_API) && (VMA_API == 1)
Packit Service aa3af4
	if (vma_comps) {
Packit Service aa3af4
		free(vma_comps);
Packit Service aa3af4
	}
Packit Service aa3af4
#else
Packit Service aa3af4
	if (events) {
Packit Service aa3af4
		free(events);
Packit Service aa3af4
	}
Packit Service aa3af4
#endif /* VMA_API */
Packit Service aa3af4
Packit Service aa3af4
	close(efd);
Packit Service aa3af4
Packit Service aa3af4
	exit(0);
Packit Service aa3af4
}