diff --git a/libknet/tests/knet_bench.c b/libknet/tests/knet_bench.c
index 0ddb52f..16f456d 100644
--- a/libknet/tests/knet_bench.c
+++ b/libknet/tests/knet_bench.c
@@ -15,16 +15,19 @@
 #include <unistd.h>
 #include <signal.h>
 #include <pthread.h>
+#include <sys/epoll.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "netutils.h"
+#include "threads_common.h"
 #include "test-common.h"
 
 #define MAX_NODES 128
 
 static int senderid = -1;
+static int thisnodeid = -1;
 static knet_handle_t knet_h;
 static int datafd = 0;
 static int8_t channel = 0;
@@ -35,15 +38,23 @@ static struct sockaddr_storage allv6;
 static int broadcast_test = 1;
 static pthread_t rx_thread = NULL;
 static char *rx_buf[PCKT_FRAG_MAX];
-static int shutdown_in_progress = 0;
+static int wait_for_perf_rx = 0;
+static int filter_msgs = 0;
+
+static int bench_shutdown_in_progress = 0;
 static pthread_mutex_t shutdown_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 #define TEST_PING 0
 #define TEST_PING_AND_DATA 1
-#define TEST_PERF 2
+#define TEST_PERF_BY_SIZE 2
+#define TEST_PERF_BY_TIME 3
 
 static int test_type = TEST_PING;
 
+#define TEST_START 2
+#define TEST_STOP 4
+#define TEST_COMPLETE 6
+
 struct node {
 	int nodeid;
 	int links;
@@ -67,15 +78,22 @@ static void print_help(void)
 	printf(" -l                                        enable global listener on 0.0.0.0/:: (default: off, incompatible with -o)\n");
 	printf(" -o                                        enable baseport offset per nodeid\n");
 	printf(" -w                                        dont wait for all nodes to be up before starting the test (default: wait)\n");
-	printf(" -T [ping|ping_data|perf]                  test type (default: ping)\n");
+	printf(" -T [ping|ping_data|perf-by-size|perf-by-time]\n");
+	printf("                                           test type (default: ping)\n");
 	printf("                                           ping: will wait for all hosts to join the knet network, sleep 5 seconds and quit\n");
 	printf("                                           ping_data: will wait for all hosts to join the knet network, sends some data to all nodes and quit\n");
-	printf("                                           perf: will wait for all hosts to join the knet network, perform a series of benchmarks and quit\n");
+	printf("                                           perf-by-size: will wait for all hosts to join the knet network,\n");
+	printf("                                                         perform a series of benchmarks by transmitting a known\n");
+	printf("                                                         size/quantity of packets and measuring the time, then quit\n");
+	printf("                                           perf-by-time: will wait for all hosts to join the knet network,\n");
+	printf("                                                         perform a series of benchmarks by transmitting a known\n");
+	printf("                                                         size of packets for a given amount of time (10 seconds)\n");
+	printf("                                                         and measuring the quantity of data transmitted, then quit\n");
 	printf(" -s                                        nodeid that will generate traffic for benchmarks\n");
 	printf(" -C                                        repeat the test continously (default: off)\n");
 }
 
-static void parse_nodes(char *nodesinfo[MAX_NODES], int onidx, int port, struct node nodes[MAX_NODES], int thisnodeid, int *thisidx)
+static void parse_nodes(char *nodesinfo[MAX_NODES], int onidx, int port, struct node nodes[MAX_NODES], int *thisidx)
 {
 	int i;
 	char *temp = NULL;
@@ -141,6 +159,30 @@ static void sock_notify(void *pvt_data,
 	return;
 }
 
+static int ping_dst_host_filter(void *pvt_data,
+				const unsigned char *outdata,
+				ssize_t outdata_len,
+				uint8_t tx_rx,
+				uint16_t this_host_id,
+				uint16_t src_host_id,
+				int8_t *dst_channel,
+				uint16_t *dst_host_ids,
+				size_t *dst_host_ids_entries)
+{
+	filter_msgs++;
+	if (broadcast_test) {
+		return 1;
+	}
+
+	if (tx_rx == KNET_NOTIFY_TX) {
+		memmove(&dst_host_ids[0], outdata, 2);
+	} else {
+		dst_host_ids[0] = this_host_id;
+	}
+	*dst_host_ids_entries = 1;
+	return 0;
+}
+
 static void setup_knet(int argc, char *argv[])
 {
 	int logfd;
@@ -148,7 +190,6 @@ static void setup_knet(int argc, char *argv[])
 	char *cryptocfg = NULL, *policystr = NULL, *protostr = NULL;
 	char *othernodeinfo[MAX_NODES];
 	struct node nodes[MAX_NODES];
-	int thisnodeid = -1;
 	int thisidx = -1;
 	int onidx = 0;
 	int debug = KNET_LOG_INFO;
@@ -286,8 +327,11 @@ static void setup_knet(int argc, char *argv[])
 				if (!strcmp("ping_data", optarg)) {
 					test_type = TEST_PING_AND_DATA;
 				}
-				if (!strcmp("perf", optarg)) {
-					test_type = TEST_PERF;
+				if (!strcmp("perf-by-size", optarg)) {
+					test_type = TEST_PERF_BY_SIZE;
+				}
+				if (!strcmp("perf-by-time", optarg)) {
+					test_type = TEST_PERF_BY_TIME;
 				}
 				break;
 			case 'C':
@@ -308,7 +352,7 @@ static void setup_knet(int argc, char *argv[])
 		exit(FAIL);
 	}
 
-	parse_nodes(othernodeinfo, onidx, port, nodes, thisnodeid, &thisidx);
+	parse_nodes(othernodeinfo, onidx, port, nodes, &thisidx);
 
 	if (thisidx < 0) {
 		printf("no config for this node found\n");
@@ -327,7 +371,7 @@ static void setup_knet(int argc, char *argv[])
 		}
 	}
 
-	if ((test_type == TEST_PERF) && (senderid < 0)) {
+	if (((test_type == TEST_PERF_BY_SIZE) || (test_type == TEST_PERF_BY_TIME)) && (senderid < 0)) {
 		printf("Error: performance test requires -s to be set (for now)\n");
 		exit(FAIL);
 	}
@@ -448,6 +492,11 @@ static void setup_knet(int argc, char *argv[])
 		}
 	}
 
+	if (knet_handle_enable_filter(knet_h, NULL, ping_dst_host_filter)) {
+		printf("Unable to enable dst_host_filter: %s\n", strerror(errno));
+		exit(FAIL);
+	}
+
 	if (knet_handle_setfwd(knet_h, 1) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		exit(FAIL);
@@ -473,38 +522,21 @@ static void setup_knet(int argc, char *argv[])
 	}
 }
 
-static int ping_dst_host_filter(void *pvt_data,
-				const unsigned char *outdata,
-				ssize_t outdata_len,
-				uint8_t tx_rx,
-				uint16_t this_host_id,
-				uint16_t src_host_id,
-				int8_t *dst_channel,
-				uint16_t *dst_host_ids,
-				size_t *dst_host_ids_entries)
-{
-	if (broadcast_test) {
-		return 1;
-	}
-
-	if (tx_rx == KNET_NOTIFY_TX) {
-		memmove(&dst_host_ids[0], outdata, 2);
-	} else {
-		dst_host_ids[0] = this_host_id;
-	}
-	*dst_host_ids_entries = 1;
-	return 0;
-}
-
 static void *_rx_thread(void *args)
 {
-	fd_set rfds;
-	ssize_t len;
-	struct timeval tv;
+	int rx_epoll;
+	struct epoll_event ev;
+	struct epoll_event events[KNET_EPOLL_MAX_EVENTS];
+
 	struct sockaddr_storage address[PCKT_FRAG_MAX];
 	struct mmsghdr msg[PCKT_FRAG_MAX];
 	struct iovec iov_in[PCKT_FRAG_MAX];
 	int i, msg_recv;
+	struct timespec clock_start, clock_end;
+	unsigned long long time_diff = 0;
+	uint64_t rx_pkts = 0;
+	uint64_t rx_bytes = 0;
+	unsigned int current_pckt_size = 0;
 
 	for (i = 0; i < PCKT_FRAG_MAX; i++) {
 		rx_buf[i] = malloc(KNET_MAX_PACKET_SIZE);
@@ -522,40 +554,108 @@ static void *_rx_thread(void *args)
 		msg[i].msg_hdr.msg_iovlen = 1;
 	}
 
-select_loop:
-	tv.tv_sec = 5;
-	tv.tv_usec = 0;
+	rx_epoll = epoll_create(KNET_EPOLL_MAX_EVENTS + 1);
+	if (rx_epoll < 0) {
+		printf("RXT: Unable to create epoll!\nHALTING RX THREAD!\n");
+		return NULL;
+	}
 
-	FD_ZERO(&rfds);
-	FD_SET(datafd, &rfds);
+	memset(&ev, 0, sizeof(struct epoll_event));
+	ev.events = EPOLLIN;
+	ev.data.fd = datafd;
 
-	len = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
-	if (len < 0) {
-		printf("RXT: Unable select over datafd\nHALTING RX THREAD!\n");
+	if (epoll_ctl(rx_epoll, EPOLL_CTL_ADD, datafd, &ev)) {
+		printf("RXT: Unable to add datafd to epoll\nHALTING RX THREAD!\n");
 		return NULL;
 	}
-	if (!len) {
-		printf("RXT: No data for the past 5 seconds\n");
-	}
-	if (FD_ISSET(datafd, &rfds)) {
-		msg_recv = recvmmsg(datafd, msg, PCKT_FRAG_MAX, MSG_DONTWAIT | MSG_NOSIGNAL, NULL);
-		if (msg_recv < 0) {
-			printf("RXT: error from recvmmsg: %s\n", strerror(errno));
-		}
-		for (i = 0; i < msg_recv; i++) {
-			if (msg[i].msg_len == 0) {
-				printf("RXT: received 0 bytes message?\n");
+
+	memset(&clock_start, 0, sizeof(clock_start));
+	memset(&clock_end, 0, sizeof(clock_start));
+
+	while (!bench_shutdown_in_progress) {
+		if (epoll_wait(rx_epoll, events, KNET_EPOLL_MAX_EVENTS, 1) >= 1) {
+			msg_recv = recvmmsg(datafd, msg, PCKT_FRAG_MAX, MSG_DONTWAIT | MSG_NOSIGNAL, NULL);
+			if (msg_recv < 0) {
+				printf("RXT: error from recvmmsg: %s\n", strerror(errno));
 			}
-			if (test_type == TEST_PING_AND_DATA) {
-				printf("received %u bytes message: %s\n", msg[i].msg_len, (char *)msg[i].msg_hdr.msg_iov->iov_base);
+			switch(test_type) {
+				case TEST_PING_AND_DATA:
+					for (i = 0; i < msg_recv; i++) {
+						if (msg[i].msg_len == 0) {
+							printf("RXT: received 0 bytes message?\n");
+						}
+						printf("received %u bytes message: %s\n", msg[i].msg_len, (char *)msg[i].msg_hdr.msg_iov->iov_base);
+					}
+					break;
+				case TEST_PERF_BY_SIZE:
+					/*
+					 * do stats here
+					 * potential logic:
+					 * - check size of incoming first packet to set timers
+					 * - detect variations of pckt size to stop timers and do math
+					 */
+					for (i = 0; i < msg_recv; i++) {
+						if (msg[i].msg_len < 64) {
+							if (msg[i].msg_len == 0) {
+								printf("RXT: received 0 bytes message?\n");
+							}
+							if (msg[i].msg_len == TEST_START) {
+								printf("received start control message!\n");
+								if (clock_gettime(CLOCK_MONOTONIC, &clock_start) != 0) {
+									printf("Unable to get start time!\n");
+								}
+							}
+							if (msg[i].msg_len == TEST_STOP) {
+								uint64_t total_rx_bytes;
+								uint64_t total_rx_pkts;
+								unsigned long long time;
+								printf("received stop control message!\n");
+								if (clock_gettime(CLOCK_MONOTONIC, &clock_end) != 0) {
+									printf("Unable to get end time!\n");
+								}
+								timespec_diff(clock_start, clock_end, &time_diff);
+								printf("Received %zu bytes (%zu pckts size: %u) in %llu/ns\n", rx_bytes, rx_pkts, current_pckt_size, time_diff - 10000000000llu);
+								time = time_diff / 1000000000llu;
+								total_rx_bytes = rx_bytes / time;
+								total_rx_pkts = rx_pkts / time;
+
+								printf("TIME: %llu\n", time);
+								printf("total rx bytes %zu / sec\n", total_rx_bytes);
+								printf("total rx pkts %zu / sec\n", total_rx_pkts);
+
+								rx_pkts = 0;
+								rx_bytes = 0;
+								current_pckt_size = 0;
+							}
+							if (msg[i].msg_len == TEST_COMPLETE) {
+								printf("received end of test control message!\n");
+								printf("received by filter_msgs: %d\n", filter_msgs);
+								wait_for_perf_rx = 1;
+							}
+							continue;
+						}
+						rx_pkts++;
+						rx_bytes = rx_bytes + msg[i].msg_len;
+						current_pckt_size = msg[i].msg_len;
+					}
+					break;
+				case TEST_PERF_BY_TIME:
+					/*
+					 * do stats here
+					 * potential logic:
+					 * - start timer when first packet arrives, end timer will stop counting.
+					 * - be careful there might still be packets in flight that we need flush.
+					 */
+					sleep(1);
+					wait_for_perf_rx = 1;
+					break;
 			}
-			/*
-			 * do stats here
-			 */
+
 		}
 	}
 
-	goto select_loop;
+	epoll_ctl(rx_epoll, EPOLL_CTL_DEL, datafd, &ev);
+	close(rx_epoll);
 
 	return NULL;
 }
@@ -601,18 +701,124 @@ static void send_ping_data(void)
 	sleep(1);
 }
 
+static int setup_send_buffers_common(struct mmsghdr *msg, struct iovec *iov_out, char *tx_buf[])
+{
+	int i;
+
+	for (i = 0; i < PCKT_FRAG_MAX; i++) {
+		tx_buf[i] = malloc(KNET_MAX_PACKET_SIZE);
+		if (!tx_buf[i]) {
+			printf("TXT: Unable to malloc!\n");
+			return -1;
+		}
+		memset(tx_buf[i], 0, KNET_MAX_PACKET_SIZE);
+		iov_out[i].iov_base = (void *)tx_buf[i];
+		iov_out[i].iov_len = KNET_MAX_PACKET_SIZE;
+		memset(&msg[i].msg_hdr, 0, sizeof(struct msghdr));
+		msg[i].msg_hdr.msg_iov = &iov_out[i];
+		msg[i].msg_hdr.msg_iovlen = 1;
+	}
+	return 0;
+}
+
+static int send_messages(struct mmsghdr *msg, int msgs_to_send)
+{
+	int sent_msgs, prev_sent, progress, total_sent;
+
+	total_sent = 0;
+	sent_msgs = 0;
+	prev_sent = 0;
+	progress = 1;
+
+retry:
+	errno = 0;
+	sent_msgs = sendmmsg(datafd, msg, msgs_to_send, MSG_NOSIGNAL);
+
+	if (sent_msgs < 0) {
+		if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+			printf("local socket is overloaded, slowing down\n");
+			usleep(KNET_THREADS_TIMERES);
+			goto retry;
+		}
+		printf("Unable to send messages: %s\n", strerror(errno));
+		return -1;
+	}
+
+	total_sent = total_sent + sent_msgs;
+
+	if ((sent_msgs >= 0) && (sent_msgs < msgs_to_send)) {
+		if ((sent_msgs) || (progress)) {
+			msgs_to_send = msgs_to_send - sent_msgs;
+			prev_sent = prev_sent + sent_msgs;
+			if (sent_msgs) {
+				progress = 1;
+			} else {
+				progress = 0;
+			}
+			goto retry;
+		}
+		if (!progress) {
+			printf("Unable to send more messages after retry\n");
+		}
+	}
+	return total_sent;
+}
+
+static void send_perf_data_by_size(void)
+{
+	char *tx_buf[PCKT_FRAG_MAX];
+	struct mmsghdr msg[PCKT_FRAG_MAX];
+	struct iovec iov_out[PCKT_FRAG_MAX];
+	char ctrl_message[16];
+	int sent_msgs;
+	int loops = 100;
+	int i;
+//	struct timespec clock_start, clock_end;
+//	unsigned long long time_diff;
+	uint64_t tx_pkts = 0;
+//	uint64_t tx_bytes = 0;
+
+	setup_send_buffers_common(msg, iov_out, tx_buf);
+
+	memset(ctrl_message, 0, sizeof(ctrl_message));
+	knet_send(knet_h, ctrl_message, TEST_START, channel);
+
+	filter_msgs = 0;
+
+	for (i = 0; i < loops; i++) {
+		sent_msgs = send_messages(msg, 256);
+		if (sent_msgs < 0) {
+			printf("Something went wrong, aborting\n");
+			exit(FAIL);
+		}
+		tx_pkts = tx_pkts + sent_msgs;
+	}
+
+	sleep(10);
+
+	printf("Sent: %zu expected: %d filter: %d error: %s\n", tx_pkts, 128 * loops, filter_msgs, strerror(errno));
+
+	knet_send(knet_h, ctrl_message, TEST_STOP, channel);
+
+	knet_send(knet_h, ctrl_message, TEST_COMPLETE, channel);
+
+	for (i = 0; i < PCKT_FRAG_MAX; i++) {
+		free(tx_buf[i]);
+	}
+}
+
 static void cleanup_all(void)
 {
 	if (pthread_mutex_lock(&shutdown_mutex)) {
 		return;
 	}
 
-	if (shutdown_in_progress) {
+	if (bench_shutdown_in_progress) {
 		pthread_mutex_unlock(&shutdown_mutex);
 		return;
 	}
 
-	shutdown_in_progress = 1;
+	bench_shutdown_in_progress = 1;
 
 	pthread_mutex_unlock(&shutdown_mutex);
 
@@ -640,6 +846,10 @@ int main(int argc, char *argv[])
 
 	setup_knet(argc, argv);
 
+	setup_data_txrx_common();
+
+	sleep(5);
+
 restart:
 	switch(test_type) {
 		default:
@@ -647,11 +857,20 @@ restart:
 			sleep(5);
 			break;
 		case TEST_PING_AND_DATA:
-			setup_data_txrx_common();
 			send_ping_data();
 			break;
-		case TEST_PERF:
-			setup_data_txrx_common();
+		case TEST_PERF_BY_SIZE:
+			if (senderid == thisnodeid) {
+				send_perf_data_by_size();
+			} else {
+				while(!wait_for_perf_rx) {
+					printf("Waiting for perf rx thread to finish\n");
+					sleep(1);
+				}
+			}
+			break;
+		case TEST_PERF_BY_TIME:
+			//send_perf_data_by_time();
 			break;
 	}
 	if (continous) {
diff --git a/libknet/threads_send_recv.c b/libknet/threads_send_recv.c
index 022de34..615ad20 100644
--- a/libknet/threads_send_recv.c
+++ b/libknet/threads_send_recv.c
@@ -64,6 +64,12 @@ retry:
 				     msg, msg_idx, MSG_DONTWAIT | MSG_NOSIGNAL);
 		savederrno = errno;
 
+		if ((sent_msgs < 0) && (savederrno == ENOBUFS)) {
+			log_debug(knet_h, KNET_SUB_TX, "socket is overloaded.. retry\n");
+			usleep(KNET_THREADS_TIMERES);
+			goto retry;
+		}
+
 		if ((sent_msgs >= 0) && (sent_msgs < msg_idx)) {
 			if ((sent_msgs) || (progress)) {
 				msgs_to_send = msg_idx - sent_msgs;
@@ -823,6 +829,8 @@ static void _parse_recv_from_links(knet_handle_t knet_h, struct sockaddr_storage
 	struct knet_hostinfo *knet_hostinfo;
 	struct iovec iov_out[1];
 	int8_t channel;
+	int i;
+	char *bla;
 
 	if (knet_h->crypto_instance) {
 		if (crypto_authenticate_and_decrypt(knet_h,
@@ -843,7 +851,12 @@ static void _parse_recv_from_links(knet_handle_t knet_h, struct sockaddr_storage
 	}
 
 	if (inbuf->kh_version != KNET_HEADER_VERSION) {
-		log_debug(knet_h, KNET_SUB_RX, "Packet version does not match");
+		log_debug(knet_h, KNET_SUB_RX, "Packet version does not match: %d", ind);
+		bla = (char *)&inbuf;
+		for (i = 0; i < len; i++) {
+			printf("%02x ", bla[i]);
+		}
+		printf("\n");
 		return;
 	}
 
@@ -1175,7 +1188,7 @@ static void _handle_recv_from_links(knet_handle_t knet_h, int sockfd, struct mms
 	 */
 
 	if (msg_recv <= 0) {
-		log_err(knet_h, KNET_SUB_RX, "Error message received from recvmmsg on socket %d: %s", sockfd, strerror(savederrno));
+		//log_err(knet_h, KNET_SUB_RX, "Error message received from recvmmsg on socket %d: %s", sockfd, strerror(savederrno));
 		knet_h->transport_ops[transport]->transport_rx_sock_error(knet_h, sockfd, msg_recv, savederrno);
 		goto exit_unlock;
 	}
diff --git a/libknet/transport_sctp.c b/libknet/transport_sctp.c
index 03a6a10..0b5d644 100644
--- a/libknet/transport_sctp.c
+++ b/libknet/transport_sctp.c
@@ -171,6 +171,17 @@ static int _configure_sctp_socket(knet_handle_t knet_h, int sock, struct sockadd
 		goto exit_error;
 	}
 
+#if 0
+	value = 1;
+	if (setsockopt(sock, SOL_SCTP, SCTP_DISABLE_FRAGMENTS, &value, sizeof(value)) < 0) {
+		savederrno = errno;
+		err = -1;
+		log_err(knet_h, KNET_SUB_TRANSPORT, "Unable to set sctp disable fragments: %s",
+			strerror(savederrno));
+		goto exit_error;
+	}
+#endif
+
 	if (_enable_sctp_notifications(knet_h, sock, type) < 0) {
 		savederrno = errno;
 		err = -1;
