static void *test_slave_proc(void *input)
{
	char proc_name[24];
	LINX *linx;
	union LINX_SIGNAL *sig;
	struct slave_args *arg_ = (struct slave_args *)input;

	sprintf(proc_name, "linx_bmark_%08u", arg_->slave_no);
	TRACE(1, "Server instance \"%s\" start.", proc_name);
	linx = linx_open(proc_name, 0, NULL);

	sig = linx_alloc(linx, sizeof(struct connEst), CONN_EST);
	sig->connEst.use_linx_api = htonl(arg_->use_linx_api);
	linx_send(linx, &sig, arg_->client);

	if (arg_->use_linx_api)
		test_with_linxlib(arg_->client, linx);
	else
		test_without_linxlib(arg_->client, linx);
	if(arg_->use_pthreads) {
		free(input);
		pthread_exit(NULL);
	}
	return NULL;
}
LINX_SPID create_test_slave(LINX * linx, LINX_SPID server, int use_linx_api,
			    int use_pthreads)
{
	LINX_SPID test_slave_spid;
	union LINX_SIGNAL *sig;
	LINX_SIGSELECT any_sig[] = { 0 };

	sig = linx_alloc(linx, sizeof(struct connEst), CONN_EST);
	sig->connEst.use_linx_api = htonl(use_linx_api);
	sig->connEst.use_pthreads = htonl(use_pthreads);

	linx_send(linx, &sig, server);

	linx_receive(linx, &sig, any_sig);

	if (sig->sigNo != CONN_EST) {
		ERR("Unknown signal %ud", sig->sigNo);
	}

	test_slave_spid = linx_sender(linx, &sig);

	linx_free_buf(linx, &sig);

	return test_slave_spid;
}
void destroy_test_slave(LINX * linx, LINX_SPID ts)
{
	union LINX_SIGNAL *sig;
	LINX_SIGSELECT any_sig[] = { 0 };

	sig = linx_alloc(linx, sizeof(LINX_SIGSELECT), ATTACH_SLAVE_SIG);
	linx_attach(linx, &sig, ts);

	sig = linx_alloc(linx, sizeof(LINX_SIGSELECT), TERMINATE_REQ);
	TRACE(1, "Terminate request");
	linx_send(linx, &sig, ts);

	linx_receive(linx, &sig, any_sig);

	if (sig->sigNo != ATTACH_SLAVE_SIG) {
		ERR("Wrong signal received while waiting for attach signal"
		    " from test slave. %d", sig->sigNo);
	}
	linx_free_buf(linx, &sig);
}
int OseGW_PLT_SendRequest_cbk(int skt, int len, char *payload,
			      struct ClientInfo *cinfo)
{
	struct OseGW_SendRequest *send_request = NULL;
	union LINX_SIGNAL *signal;
	int status = 0;

	send_request = (struct OseGW_SendRequest *) payload;
	send_request->dest_pid = ntohl(send_request->dest_pid);
	send_request->from_pid = ntohl(send_request->from_pid);
	send_request->sig_len = ntohl(send_request->sig_len);
	signal = linx_alloc(cinfo->linx, send_request->sig_len,
		            ntohl(send_request->sig_no));
	if (signal == LINX_NIL) {
		syslog(LOG_ERR, "Linx alloc failed at Send request");
		return -1;
	}

	memcpy(&((char *) signal)[sizeof(SIGSELECT)],
	       send_request->sig_data,
	       send_request->sig_len - sizeof(SIGSELECT));
	if (send_request->from_pid == 0) {
		status = linx_send(cinfo->linx, &signal,send_request->dest_pid);

	} else {
		status = linx_send_w_s(cinfo->linx, &signal,
			               send_request->from_pid,
			               send_request->dest_pid);

	}
	if (status == -1) {
		/* signals sent to closed endpoints are silently discarded */
		if (errno == ECONNRESET || errno == EPIPE) {
			status = 0;
		} else {
			syslog(LOG_ERR, "Error sending signal to pid %x (%s)",
			       (int) send_request->dest_pid, strerror(errno));
			return status;
		}
	}

	LOG(LOG_INFO, " Sent signal: %#x to pid: %#x\n",
            (int) ntohl(send_request->sig_no),
            (int) send_request->dest_pid);
	status = OseGW_PLT_SendReply_cbk(skt, len, payload, cinfo);
	return status;
}
int OseGW_PLT_AttachReply_cbk(int skt, int len, char *payload,
                              struct ClientInfo *cinfo)
{
	OseGW_UL payload_len = sizeof(struct OseGW_AttachReply);
	struct OseGW_TransportData *reply = NULL;
	struct OseGW_AttachRequest *attach_request = NULL;
	int status = 0;
	PROCESS pid;
	union LINX_SIGNAL *signal;
	LINX_OSATTREF attref;
	int size = 0;

	size = sizeof(struct OseGW_TransportHdr) + payload_len;
	reply = (struct OseGW_TransportData *)malloc(size);
	if (reply == NULL) {
		syslog(LOG_ERR, "Malloc failure in Attach reply ");
		return -1;
	}

	attach_request = (struct OseGW_AttachRequest *)payload;
	pid = ntohl(attach_request->pid);
	attach_request->sig_len = ntohl(attach_request->sig_len);
	LOG(LOG_INFO, "Gateway Client: attaching to %#x", pid);
	if (attach_request->sig_len) {
		signal = linx_alloc(cinfo->linx, attach_request->sig_len,
				    ntohl(attach_request->sig_no));
		if (signal == LINX_NIL) {
			syslog(LOG_ERR, "Linx alloc failed in Attach "
                               "reply");
			free(reply);
			return -1;
		}
		memcpy(&((char *) signal)[sizeof(SIGSELECT)],
		       attach_request->sig_data,
		       attach_request->sig_len - sizeof(SIGSELECT));
		attref = linx_attach(cinfo->linx, &signal, pid);
	} else {
		attref = linx_attach(cinfo->linx, NULL, pid);
	}

	if (attref == LINX_ILLEGAL_ATTREF) {
	        free(reply);
		return -1;
	}
	/* Fill the header */
	reply->hdr.payload_type = htonl(OseGW_PLT_AttachReply);
	reply->hdr.payload_len = htonl(sizeof(struct OseGW_AttachReply));
	/* Fill the payload */
	reply->payload.attach_reply.status = htonl(cinfo->status);
	reply->payload.attach_reply.attref = htonl(attref);
	/*Send */
	size = sizeof(struct OseGW_TransportHdr) + payload_len;
	status = send(skt, (void *) reply, size, 0);
	if (status == size) {
		LOG(LOG_INFO, "Gateway Client: replying AttachReply "
                    "on socket %d", skt);
	} else {
		syslog(LOG_INFO, "Gateway Client: failed replying "
		       "AttachReply on socket %d",  skt);
		status = -1;
	}
	free(reply);
	return status;
}
int OseGW_PLT_HuntReply_cbk(int skt, int len, char *payload,
                            struct ClientInfo *cinfo)
{
	OseGW_UL payload_len = sizeof(struct OseGW_HuntReply);
	struct OseGW_TransportData *reply = NULL;
	struct OseGW_HuntRequest *hunt_request =
		(struct OseGW_HuntRequest *) payload;
	union LINX_SIGNAL *hunt_sig = NULL;
	const LINX_SIGSELECT hunt_sigsel[] = { 1, LINX_OS_HUNT_SIG };
	LINX *gws_hunter;
	PROCESS pid = 0;
	int status = 0;
	int size = 0;

	/*Fill the header */
	size = sizeof(struct OseGW_TransportHdr) + payload_len;
	reply = (struct OseGW_TransportData *) malloc(size);
	if (reply == NULL) {
		syslog(LOG_ERR, "Malloc failure in Hunt reply");
		return -1;
	}
	reply->hdr.payload_type = htonl(OseGW_PLT_HuntReply);
	reply->hdr.payload_len = htonl(sizeof(struct OseGW_HuntReply));
	/* Fill the payload */
	hunt_request->user = ntohl(hunt_request->user);
	hunt_request->sig_len = ntohl(hunt_request->sig_len);
	hunt_request->name_index = ntohl(hunt_request->name_index);
	if (hunt_request->sig_len != 0) {
		hunt_sig = linx_alloc(cinfo->linx, hunt_request->sig_len,
				      ntohl(hunt_request->sig_no));
		if (hunt_sig == LINX_NIL) {
			syslog(LOG_ERR, "Linx alloc failed in Hunt reply");
			free(reply);
			return -1;
		}
		size = hunt_request->sig_len - sizeof(SIGSELECT);
		memcpy(&((char *) hunt_sig)[sizeof(SIGSELECT)],
		       &hunt_request->
		       data[ntohl(hunt_request->sig_index)], size);
		/*
		 * This hunt sig will be returned to caller or be cleaned
		 * up when caller closes the gateway socket.
		 */
		status = linx_hunt(cinfo->linx,
				   &hunt_request->data
				   [hunt_request->name_index],
				   &hunt_sig);

		if (status == -1) {
			free(reply);
			return status;
		}
	}

	/*
	 * The gateway hunt(...) returns the pid of the hunted process if the
	 * process exist when the hunt is done. The LINX hunt(...) does not so
	 * a hunt/receive_w_tmo/sender is done to get the pid. The gws_hunter
	 * socket is opened to prevent at client from flooding the gw server
	 * with hunt requests that could lead to out-of-memory in the LINX
	 * kernel module. If the hunted process does not exist the hunt is
	 * cleaned up when the gws_hunter socket is closed.
	 */

	gws_hunter = linx_open("gws_hunter", 0, NULL);
	status = linx_hunt(gws_hunter,
			   &hunt_request->data[hunt_request->name_index],
			   NULL);
	if (status == -1) {
	        free(reply);
	        return status;
	}

	status = linx_receive_w_tmo(gws_hunter, &hunt_sig, 0, hunt_sigsel);
	if (status == -1) {
		free(reply);
		return status;
	}

	if (hunt_sig != LINX_NIL) {
		pid = linx_sender(gws_hunter, &hunt_sig);
		if (pid == LINX_ILLEGAL_SPID) {
			free(reply);
			return -1;
		}
		linx_free_buf(gws_hunter, &hunt_sig);
	}
	/* free up the "hunt" */
	linx_close(gws_hunter);

	reply->payload.hunt_reply.status = htonl(cinfo->status);
	reply->payload.hunt_reply.pid = htonl(pid);
	/*Send */
	size = sizeof(struct OseGW_TransportHdr) + payload_len;
	status = send(skt, (void *) reply, size, 0);
	if (status == size) {
		LOG(LOG_INFO, "Gateway Client: replying HuntReply "
                    "on socket %d", skt);
	} else {
		syslog(LOG_INFO, "Gateway Clinet: failed replying "
		       "HuntReply on socket %d", skt);
		status = -1;
	}
	free(reply);
	return status;
}
int main(int argc, char *argv[])
{
	LINX *linx;
	LINX_SPID server_spid;
	union LINX_SIGNAL *sig;
	pthread_t server_th;
	int c;
	int loop_cnt = LOOP_CNT;
	int use_linx_api = LINX_SOCKET;
	size_t msg_size = BURST_SIZE;
	unsigned long burst_cnt = BURST_CNT;
	size_t start_msg_size = START_MSG_SIZE;
	size_t end_msg_size = END_MSG_SIZE;
	unsigned long throughput_instances = THROUGHPUT_INSTANCES;
	int iterations = ITERATIONS;
	LINX_SIGSELECT any_sig[] = { 0 };

	char *path = NULL;
	char *server_name = NULL;
	int run_attach_test = 0;
	int run_com_test = 0;
	int kill_server = 0;
	int all = 0;
	int use_pthreads = 0;

	if (argc < 2) {
		print_usage(argv[0]);
		return 0;
	}

	while ((c = getopt(argc, argv, "S?p:ac:n:m:b:i:s:e:Alt:qP")) != -1) {
		switch (c) {
		case 'S':
			/* Start server */
			server_name = (optarg == NULL ? SERVER_NAME : optarg);
			break;

		case 'P':
			/* Start server as posix thread */
			server_name = SERVER_NAME;
			use_pthreads = 1;
			break;

		case 'p':
			/* Hunt path */
			path = optarg;
			break;

		case 'a':
			/* Run attach test */
			run_attach_test = 1;
			break;

		case 'c':
			/* Connection test */
			run_com_test = atoi(optarg);
			break;

		case 'n':
			/* Loop count */
			loop_cnt = atoi(optarg);
			break;

		case 'm':
			/* Message size */
			msg_size = atol(optarg);
			break;

		case 'b':
			/* Burst count */
			burst_cnt = atol(optarg);
			break;

		case 'i':
			/* Iterations */
			iterations = atoi(optarg);
			break;

		case 's':
			/* Start message size */
			start_msg_size = atol(optarg);
			break;

		case 'e':
			/* End message size */
			end_msg_size = atol(optarg);
			break;

		case 'A':
			/* Run all tests */
			all = 1;
			break;

		case 'l':
			/* Use linx api in tests */
			use_linx_api = LINX_API;
			break;

		case 't':
			/* Number of instances in throughput */
			throughput_instances = atoi(optarg);
			break;

		case 'q':
			/* Quit the server */
			kill_server = 1;
			break;
		default:
			print_usage(argv[0]);
			return 0;
		}
	}

	if(use_pthreads) {
		kill_server = 1;
		if (pthread_create(&server_th, NULL, server,
				   (void *)server_name)) {
			fprintf(stderr, "pthread_create(): %d\n", errno);
			exit(errno);
		}
	} else if (server_name != NULL) {
		(void)server(server_name);
		return 0;
	}

	/* Path to server */
	path = path && *path ? path : CS_PATH SERVER_NAME;

	/* Hunt for server */
	linx = linx_open(CLIENT_NAME, 0, NULL);
	linx_hunt(linx, path, NULL);
	linx_receive_w_tmo(linx, &sig, 1000, any_sig);
	if (sig == NULL) {
		printf("Hunt failed. No server found at path '%s'.\n"
		       "Is the server started and path ok? "
		       "(Server started with -S option)\n", path);
		linx_close(linx);
		return 1;
	}
	if (sig->sigNo != LINX_OS_HUNT_SIG) {
		ERR("Failed to hunt for '%s'", path);
		linx_free_buf(linx, &sig);
		linx_close(linx);
		return 1;
	}
	server_spid = linx_sender(linx, &sig);
	linx_free_buf(linx, &sig);

	/* Attach to server */
	sig = linx_alloc(linx, sizeof(LINX_SIGSELECT), ATTACH_SERV_SIG);
	linx_attach(linx, &sig, server_spid);

	if (run_attach_test) {
		attach_test(linx, path, loop_cnt, server_spid, use_linx_api,
			    use_pthreads);
	}

	switch (run_com_test) {
	case 1:
		/* Start com test 1 */
		linx_bmark_latency(linx, path, loop_cnt, msg_size, msg_size,
				   ONE_ITERATION, server_spid, use_linx_api,
				   use_pthreads);
		break;
	case 2:
		/* Start com test 2 */
		linx_bmark_burst(linx, path, loop_cnt, msg_size,
				 msg_size, ONE_ITERATION,
				 burst_cnt, server_spid, use_linx_api,
				 use_pthreads);
		break;
	case 3:
		/* Start com test 3 */
		linx_bmark_latency(linx, path, loop_cnt, start_msg_size,
				   end_msg_size, iterations, server_spid,
				   use_linx_api, use_pthreads);
		break;
	case 4:
		/* Start com test 4 */
		linx_bmark_burst(linx, path, loop_cnt, start_msg_size,
				 end_msg_size, iterations, burst_cnt,
				 server_spid, use_linx_api, use_pthreads);
		break;
	case 5:
		/* Start com test 5 */
		linx_bmark_throughput(path, loop_cnt, msg_size,
				      server_spid, use_linx_api,
				      throughput_instances, use_pthreads);
		break;
	default:
		break;
	}

	if (all) {
		/* All tests  */
		attach_test(linx, path, loop_cnt, server_spid, use_linx_api,
			    use_pthreads);
		linx_bmark_latency(linx, path, loop_cnt, msg_size, msg_size,
				   ONE_ITERATION, server_spid, use_linx_api,
				   use_pthreads);
		linx_bmark_burst(linx, path, loop_cnt, msg_size, msg_size,
				 ONE_ITERATION, burst_cnt,
				 server_spid, use_linx_api, use_pthreads);
		linx_bmark_latency(linx, path, loop_cnt, start_msg_size,
				   end_msg_size, iterations,
				   server_spid, use_linx_api, use_pthreads);
		linx_bmark_burst(linx, path, loop_cnt, start_msg_size,
				 end_msg_size, iterations, burst_cnt,
				 server_spid, use_linx_api, use_pthreads);
		linx_bmark_throughput(path, loop_cnt, msg_size,
				      server_spid, use_linx_api,
				      throughput_instances, use_pthreads);
	}

	if (kill_server) {
		/* If no test argument specified, let server close */
		sig = linx_alloc(linx, sizeof(LINX_SIGSELECT), CONN_TERM);
		linx_send(linx, &sig, server_spid);
		printf("Waiting for attach from server.\n");
		linx_receive(linx, &sig, any_sig);
		if (sig == LINX_NIL) {
			ERR("No attach signal was received from the server.");
		}
		if (sig->sigNo != ATTACH_SERV_SIG) {
			ERR("Wrong signal received while waiting for "
			    "attach signal from server.");
		}
		linx_free_buf(linx, &sig);

		/* Close client spid */
		linx_close(linx);
	}

	if(use_pthreads)
		pthread_join(server_th, NULL);
	
	return 0;
}
static void test_with_linxlib(LINX_SPID client, LINX * linx)
{
	LINX_SPID sender;
	union LINX_SIGNAL *sig;
	LINX_SIGSELECT any_sig[] = { 0 };

	for (;;) {
		linx_receive(linx, &sig, any_sig);

		sender = linx_sender(linx, &sig);
		if (sender != client) {
			WARN("Ignoring signal from spid %ud", sender);
			linx_free_buf(linx, &sig);
			continue;
		}

		switch (sig->sigNo) {
		case ECHO_SIG:
			TRACE(1, "Sending echo");
			linx_send(linx, &sig, client);
			break;

		case TERMINATE_REQ:
			TRACE(1, "Terminating");
			linx_free_buf(linx, &sig);
			linx_close(linx);
			return;

		case ATTACH_TEST_REQ:
			linx_send(linx, &sig, client);
			linx_close(linx);
			return;

		case BURST_REQ:
			{
				int sigCnt = ntohl(sig->burstReq.n);
				int reply_size =
				    ntohl(sig->burstReq.reply_size);
				LINX_SIGSELECT reply_sigNo =
				    ntohl(sig->burstReq.reply_sigNo);
				union LINX_SIGNAL *list = 0;

				linx_free_buf(linx, &sig);

				/* Allocate all signals before sending then to
				 * make the send loop as tight as possible */
				while (sigCnt--) {
					sig = linx_alloc(linx, reply_size,
							 reply_sigNo);
					sig->burstSig.sigNo = reply_sigNo;
					sig->burstSig.next = list;
					list = sig;
				}

				while (list) {
					sig = list;
					list = list->burstSig.next;
					sig->burstSig.next = NULL;
					linx_send(linx, &sig, client);
				}
				break;
			}

		default:
			WARN("Ignoring unknown signal %ud", sig->sigNo);
			linx_free_buf(linx, &sig);
		}
	}
}