|
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 |
|