Blame tests/extra_api_tests/tcp_zcopy_cb/server.c

Packit 6d2c1b
#include <sys/types.h>
Packit 6d2c1b
#include <sys/socket.h>
Packit 6d2c1b
#include <netinet/in.h>
Packit 6d2c1b
#include <arpa/inet.h>
Packit 6d2c1b
#include <netdb.h>
Packit 6d2c1b
#include <stdio.h>
Packit 6d2c1b
#include <stdlib.h>
Packit 6d2c1b
#include <string.h>
Packit 6d2c1b
#include <netinet/in.h>
Packit 6d2c1b
#include <mellanox/vma_extra.h>
Packit 6d2c1b
#include "types.h"
Packit 6d2c1b
Packit 6d2c1b
#define BUFFER_SIZE	1024
Packit 6d2c1b
#define TIMEOUT	5
Packit 6d2c1b
Packit 6d2c1b
extern struct config_t		config;
Packit 6d2c1b
Packit 6d2c1b
typedef vma_recv_callback_retval_t (*vma_recv_callback_t)(int fd, size_t sz_iov, struct iovec iov[],
Packit 6d2c1b
                                                          struct vma_info_t* vma_info, void *context);
Packit 6d2c1b
vma_recv_callback_retval_t myapp_vma_recv_pkt_notify_callback(
Packit 6d2c1b
                                                              int fd,
Packit 6d2c1b
                                                              size_t iov_sz,
Packit 6d2c1b
                                                              struct iovec iov[],
Packit 6d2c1b
                                                              struct vma_info_t* vma_info,
Packit 6d2c1b
                                                              void *context);
Packit 6d2c1b
void free_packet(void* packet_id, int fd);
Packit 6d2c1b
int server_management(int *mangSocket);
Packit 6d2c1b
int get_sock_fd(int *sock, int mangSock);
Packit 6d2c1b
int receive_data(int *sock, int mangSock);
Packit 6d2c1b
struct vma_api_t *vma_api = NULL;
Packit 6d2c1b
Packit 6d2c1b
int server_main(){
Packit 6d2c1b
	int		sock	= INVALID_SOCKET;
Packit 6d2c1b
	int		mangSock	= INVALID_SOCKET;
Packit 6d2c1b
	int		result	= -1;
Packit 6d2c1b
	int		rc;
Packit 6d2c1b
	struct 	timeval timeout;
Packit 6d2c1b
	struct 	pending_packet_t pending_packet;
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Enter Function server_main\n");
Packit 6d2c1b
		
Packit 6d2c1b
	if (config.callbackReturn == HOLD) {	
Packit 6d2c1b
		pending_packet.valid = 0;
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	rc =  server_management(&mangSock);
Packit 6d2c1b
    CHECK_VALUE("server_management", rc, 0, goto cleanup);
Packit 6d2c1b
Packit 6d2c1b
	rc = get_sock_fd(&sock, mangSock);
Packit 6d2c1b
	CHECK_VALUE("get_sock_fd", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	if(config.nonBlocking){
Packit 6d2c1b
	  	rc = make_socket_non_blocking(sock);
Packit 6d2c1b
		CHECK_VALUE("make_socket_non_blocking", rc, 0, goto cleanup);
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		timeout.tv_sec = TIMEOUT;
Packit 6d2c1b
		timeout.tv_usec = 0;
Packit 6d2c1b
		
Packit 6d2c1b
		rc = setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
Packit 6d2c1b
				 sizeof(timeout));
Packit 6d2c1b
		CHECK_VALUE("setsockopt", rc, 0, goto cleanup);
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	vma_api = vma_get_api();
Packit 6d2c1b
	CHECK_NOT_EQUAL("vma_get_api", vma_api, NULL, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Server gets VMA APIs\n");
Packit 6d2c1b
	
Packit 6d2c1b
	rc = vma_api->register_recv_callback(sock, myapp_vma_recv_pkt_notify_callback, &pending_packet);
Packit 6d2c1b
	CHECK_VALUE("register_recv_callback", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Callback function registered with VMA\n");
Packit 6d2c1b
Packit 6d2c1b
	rc = receive_data(&sock, mangSock);
Packit 6d2c1b
	CHECK_VALUE("receive_data", rc, 0, goto cleanup);
Packit 6d2c1b
Packit 6d2c1b
	if (config.callbackReturn == HOLD) {
Packit 6d2c1b
		CHECK_VALUE("pending_packet.valid", pending_packet.valid, 1, goto cleanup);
Packit 6d2c1b
		free_packet(pending_packet.vma_info->packet_id, sock);
Packit 6d2c1b
		free(pending_packet.vma_info);
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	/* sync for termination */
Packit 6d2c1b
	rc = sync_side(mangSock, 1);
Packit 6d2c1b
	CHECK_VALUE("sync_side", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	result = 0;
Packit 6d2c1b
 cleanup:
Packit 6d2c1b
  	if(sock != INVALID_SOCKET){
Packit 6d2c1b
		rc = close(sock);
Packit 6d2c1b
		CHECK_VALUE("close", rc, 0, result = -1);
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	if(mangSock != INVALID_SOCKET) {
Packit 6d2c1b
		rc = close(mangSock);
Packit 6d2c1b
		CHECK_VALUE("close", rc, 0, result = -1);
Packit 6d2c1b
	}
Packit 6d2c1b
	return result;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void myapp_processes_packet_func(
Packit 6d2c1b
                            struct iovec* iov,
Packit 6d2c1b
                            size_t iov_sz,
Packit 6d2c1b
                            void* packet_id,
Packit 6d2c1b
                            int s){
Packit 6d2c1b
  printf("Enter Function myapp_processes_packet_func\n");
Packit 6d2c1b
  /*myapp_processes_packet_func(.....);*/
Packit 6d2c1b
  
Packit 6d2c1b
  /* Return zero copied packet buffer back to VMA
Packit 6d2c1b
  // Would be better to collect a bunch of buffers and return them all at once
Packit 6d2c1b
  // which will save locks inside VMA
Packit 6d2c1b
  */
Packit 6d2c1b
	free_packet(packet_id, s);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
/**
Packit 6d2c1b
 * Free VMA buffer reserved for given packet
Packit 6d2c1b
 * Params:
Packit 6d2c1b
 *		*packet_id	: ID of packet to remove
Packit 6d2c1b
 *		fd			: File descriptor for socket.
Packit 6d2c1b
 **/
Packit 6d2c1b
void free_packet(void* packet_id, int fd){
Packit 6d2c1b
Packit 6d2c1b
  struct vma_packet_t* vma_packet;
Packit 6d2c1b
  vma_packet = malloc(sizeof(vma_packet->packet_id));
Packit 6d2c1b
  vma_packet->packet_id = packet_id;
Packit 6d2c1b
  vma_api->free_packets(fd, vma_packet, 1);
Packit 6d2c1b
  free(vma_packet);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
vma_recv_callback_retval_t myapp_vma_recv_pkt_notify_callback(
Packit 6d2c1b
                                                              int fd,
Packit 6d2c1b
                                                              size_t iov_sz,
Packit 6d2c1b
                                                              struct iovec iov[],
Packit 6d2c1b
                                                              struct vma_info_t* vma_info,
Packit 6d2c1b
                                                              void *context)
Packit 6d2c1b
{
Packit 6d2c1b
	struct pending_packet_t *p_pending_packet;
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Enter Function myapp_vma_recv_pkt_notify_callback\n");
Packit 6d2c1b
		
Packit 6d2c1b
	if (strcmp(iov[0].iov_base, "recv") == 0) {
Packit 6d2c1b
		printf("VMA's info struct is not something we recognize so un register the application's callback function\n");
Packit 6d2c1b
		printf("VMA extra API filtered to VMA_PACKET_RECV\n");
Packit 6d2c1b
		return VMA_PACKET_RECV;
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	if (strcmp(iov[0].iov_base, "drop") == 0){
Packit 6d2c1b
		printf("VMA extra API filtered to VMA_PACKET_DROP\n");
Packit 6d2c1b
		return VMA_PACKET_DROP;
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	if (strcmp(iov[0].iov_base, "hold") == 0){
Packit 6d2c1b
		printf("VMA extra API filtered to VMA_PACKET_HOLD\n");
Packit 6d2c1b
Packit 6d2c1b
		/* In hold case we check pending_packet,free its holding buffer if its valid and then fill it with new packet data,
Packit 6d2c1b
		   so each packet will be freed in the next callback */
Packit 6d2c1b
		p_pending_packet = (struct pending_packet_t *)context;
Packit 6d2c1b
		if (p_pending_packet->valid)
Packit 6d2c1b
			myapp_processes_packet_func(p_pending_packet->iov, p_pending_packet->iovec_size, p_pending_packet->vma_info->packet_id, fd);
Packit 6d2c1b
		memcpy(p_pending_packet->iov, iov, sizeof(struct iovec)*iov_sz);
Packit 6d2c1b
		p_pending_packet->iovec_size = iov_sz;
Packit 6d2c1b
		p_pending_packet->vma_info = malloc(sizeof(struct vma_info_t));
Packit 6d2c1b
		memcpy (p_pending_packet->vma_info, vma_info, sizeof(struct vma_info_t));
Packit 6d2c1b
		p_pending_packet->valid = 1;
Packit 6d2c1b
		
Packit 6d2c1b
		return VMA_PACKET_HOLD;
Packit 6d2c1b
	}
Packit 6d2c1b
	printf("VMA extra API filtered to VMA_PACKET_RECV\n");
Packit 6d2c1b
	
Packit 6d2c1b
	return VMA_PACKET_RECV;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
int server_management(
Packit 6d2c1b
                      int            *mangSocket){
Packit 6d2c1b
	int                     rc;
Packit 6d2c1b
	int                     result          = -1;
Packit 6d2c1b
	int                     on              = 1;
Packit 6d2c1b
	int                     mainSocket      = INVALID_SOCKET;
Packit 6d2c1b
	socklen_t               clilen;
Packit 6d2c1b
	struct sockaddr_in      servAddr;
Packit 6d2c1b
	struct sockaddr_in      cliAddr;
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Enter Function server_management\n");
Packit 6d2c1b
	
Packit 6d2c1b
	mainSocket = socket(AF_INET, SOCK_STREAM, 0);
Packit 6d2c1b
	CHECK_NOT_EQUAL("socket", mainSocket, INVALID_SOCKET, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	bzero((char *) &servAddr, sizeof(servAddr));
Packit 6d2c1b
	servAddr.sin_family = AF_INET;
Packit 6d2c1b
	servAddr.sin_addr.s_addr = inet_addr(config.mngip);
Packit 6d2c1b
	servAddr.sin_port = htons(config.port + 15);
Packit 6d2c1b
	
Packit 6d2c1b
	rc = setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
Packit 6d2c1b
	CHECK_VALUE("setsockopt", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	rc = bind(mainSocket, (struct sockaddr *) &servAddr, sizeof(servAddr));
Packit 6d2c1b
	CHECK_VALUE("bind", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	listen(mainSocket,1);
Packit 6d2c1b
	CHECK_VALUE("listen", rc, 0, goto cleanup);
Packit 6d2c1b
	clilen = sizeof(cliAddr);
Packit 6d2c1b
	
Packit 6d2c1b
	*mangSocket = accept(mainSocket, (struct sockaddr *) &cliAddr, &clilen);
Packit 6d2c1b
	CHECK_NOT_EQUAL("accept", *mangSocket, INVALID_SOCKET, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	printf("server Accepting new client\n");
Packit 6d2c1b
	result = 0;
Packit 6d2c1b
 cleanup:
Packit 6d2c1b
	return result;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
/**
Packit 6d2c1b
 *Generate TCP socket, bind it to specific address, listen and accept new connection.
Packit 6d2c1b
 *
Packit 6d2c1b
 * Params:
Packit 6d2c1b
 *		*sock	: File descriptor represent generated socket
Packit 6d2c1b
 *		mangSock	: File descriptor used for management
Packit 6d2c1b
 * Returns:
Packit 6d2c1b
 *		These calls return 0, or -1 if an error occurred.
Packit 6d2c1b
 **/
Packit 6d2c1b
int get_sock_fd(int *sock, int mangSock){
Packit 6d2c1b
	int		rc;
Packit 6d2c1b
	int		on		= 1;
Packit 6d2c1b
	int		result	= -1;
Packit 6d2c1b
	int		mainSocket	= INVALID_SOCKET;
Packit 6d2c1b
	struct 	sockaddr_in	sAddr;
Packit 6d2c1b
	struct		sockaddr_in	cliAddr;
Packit 6d2c1b
	socklen_t	clilen;
Packit 6d2c1b
Packit 6d2c1b
	printf("Enter Function get_sock_fd\n");
Packit 6d2c1b
	
Packit 6d2c1b
	memset(&sAddr, 0, sizeof(sAddr)); 
Packit 6d2c1b
	
Packit 6d2c1b
	mainSocket = socket(AF_INET, SOCK_STREAM, 0);
Packit 6d2c1b
	CHECK_NOT_EQUAL("socket", mainSocket, INVALID_SOCKET, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	/* Set server Address */
Packit 6d2c1b
	sAddr.sin_family		= AF_INET;
Packit 6d2c1b
	sAddr.sin_port			= htons(config.port);
Packit 6d2c1b
	sAddr.sin_addr.s_addr	= inet_addr(config.sip);
Packit 6d2c1b
	
Packit 6d2c1b
	if(config.reuseAddr){
Packit 6d2c1b
		rc = setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
Packit 6d2c1b
		CHECK_VALUE("setsockopt", rc, 0, goto cleanup);
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	/* Bind socket to server address */
Packit 6d2c1b
	rc = bind(mainSocket, (struct sockaddr *) &sAddr, sizeof(sAddr));
Packit 6d2c1b
	CHECK_VALUE("bind", rc, 0, goto cleanup);
Packit 6d2c1b
			
Packit 6d2c1b
	memset(&cliAddr, 0, sizeof(cliAddr));
Packit 6d2c1b
	
Packit 6d2c1b
	rc = listen(mainSocket, 1);
Packit 6d2c1b
	CHECK_VALUE("listen", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	/* sync to connect from other side */
Packit 6d2c1b
	rc = sync_side(mangSock, 1);
Packit 6d2c1b
	CHECK_VALUE("sync_side", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	clilen = sizeof(cliAddr);
Packit 6d2c1b
	
Packit 6d2c1b
	*sock = accept(mainSocket, (struct sockaddr *) &cliAddr, &clilen);
Packit 6d2c1b
	CHECK_NOT_EQUAL("accept", *sock, INVALID_SOCKET, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	printf("server Accepting new client\n");
Packit 6d2c1b
	
Packit 6d2c1b
	result = 0;
Packit 6d2c1b
cleanup:
Packit 6d2c1b
	return result;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
/**
Packit 6d2c1b
 *Receive data from given TCP socket fd.
Packit 6d2c1b
 *
Packit 6d2c1b
 * Params:
Packit 6d2c1b
 *		*sock	: File descriptor represent test socket
Packit 6d2c1b
 *		mangSock	: File descriptor used for management
Packit 6d2c1b
 * Returns:
Packit 6d2c1b
 *		These calls return 0, or -1 if an error occurred.
Packit 6d2c1b
 **/
Packit 6d2c1b
int receive_data(int *sock, int mangSock){
Packit 6d2c1b
	
Packit 6d2c1b
	int	result	= -1;
Packit 6d2c1b
	int	rc;
Packit 6d2c1b
	void* recv_data;
Packit 6d2c1b
	
Packit 6d2c1b
	printf("Enter Function receive_data\n");
Packit 6d2c1b
Packit 6d2c1b
	recv_data = malloc(sizeof(char) * BUFFER_SIZE);
Packit 6d2c1b
	CHECK_NOT_EQUAL("malloc", recv_data, NULL, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	rc = sync_side(mangSock, 1);
Packit 6d2c1b
	CHECK_VALUE("sync_side", rc, 0, goto cleanup);
Packit 6d2c1b
	
Packit 6d2c1b
	if(config.nonBlocking){
Packit 6d2c1b
		rc = select_read(sock, TIMEOUT, 0);
Packit 6d2c1b
		if (config.callbackReturn == DROP) {
Packit 6d2c1b
			CHECK_VALUE("select_read", rc, 0, goto cleanup);
Packit 6d2c1b
		}	
Packit 6d2c1b
		else {
Packit 6d2c1b
			CHECK_NOT_EQUAL("select_read", rc, 0, goto cleanup);
Packit 6d2c1b
			CHECK_NOT_EQUAL("select_read", rc, -1, goto cleanup);
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	rc = recv(*sock, recv_data, BUFFER_SIZE, 0);
Packit 6d2c1b
	if (config.callbackReturn == RECV) {
Packit 6d2c1b
		CHECK_NOT_EQUAL("recv", rc, -1, goto cleanup);
Packit 6d2c1b
		CHECK_NOT_EQUAL("recv", rc, 0, goto cleanup);
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		CHECK_VALUE("recv", rc, -1, goto cleanup);
Packit 6d2c1b
		CHECK_VALUE("recv", errno, EAGAIN, goto cleanup);
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	result = 0;
Packit 6d2c1b
cleanup:
Packit 6d2c1b
	if (recv_data)
Packit 6d2c1b
		free(recv_data);
Packit 6d2c1b
	return result;
Packit 6d2c1b
}
Packit 6d2c1b