diff --git a/libknet/internals.h b/libknet/internals.h
index b962347..f864e24 100644
--- a/libknet/internals.h
+++ b/libknet/internals.h
@@ -247,6 +247,12 @@ typedef struct knet_transport_ops {
 	int (*transport_link_clear_config)(knet_handle_t knet_h, struct knet_link *link);
 
 /*
+ * transport callback for incoming dynamic connections
+ * this is called in global read lock context
+ */
+	int (*transport_link_dyn_connect)(knet_handle_t knet_h, int sockfd, struct knet_link *link);
+
+/*
  * per transport error handling of recvmmsg
  * (see _handle_recv_from_links comments for details)
  */
diff --git a/libknet/netutils.c b/libknet/netutils.c
index 4e5859a..be916bf 100644
--- a/libknet/netutils.c
+++ b/libknet/netutils.c
@@ -26,10 +26,6 @@ static int is_v4_mapped(struct sockaddr_storage *ss, socklen_t salen)
 	return memcmp(&addr6->sin6_addr, map, 12);
 }
 
-/*
- * unused now - move to libknet for ACL
- */
-
 int cmpaddr(struct sockaddr_storage *ss1, socklen_t sslen1,
 	    struct sockaddr_storage *ss2, socklen_t sslen2)
 {
diff --git a/libknet/tests/knet_bench.c b/libknet/tests/knet_bench.c
index ad9008d..410d618 100644
--- a/libknet/tests/knet_bench.c
+++ b/libknet/tests/knet_bench.c
@@ -18,13 +18,16 @@
 
 #include "libknet.h"
 
+#include "compat.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 = (pthread_t)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;
@@ -285,8 +326,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':
@@ -307,7 +351,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");
@@ -326,7 +370,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);
 	}
@@ -375,6 +419,12 @@ static void setup_knet(int argc, char *argv[])
 		exit(FAIL);
 	}
 
+	if (knet_handle_pmtud_setfreq(knet_h, 5) < 0) {
+		printf("knet_handle_pmtud_setfreq failed: %s\n", strerror(errno));
+		knet_handle_free(knet_h);
+		exit(FAIL);
+	}
+
 	for (i=0; i < onidx; i++) {
 		if (i == thisidx) {
 			continue;
@@ -444,9 +494,22 @@ static void setup_knet(int argc, char *argv[])
 				printf("knet_link_set_enable failed: %s\n", strerror(errno));
 				exit(FAIL);
 			}
+			if (knet_link_set_ping_timers(knet_h, nodes[i].nodeid, link_idx, 1000, 10000, 2048) < 0) {
+				printf("knet_link_set_ping_timers failed: %s\n", strerror(errno));
+				exit(FAIL);
+			}
+			if (knet_link_set_pong_count(knet_h, nodes[i].nodeid, link_idx, 2) < 0) {
+				printf("knet_link_set_pong_count failed: %s\n", strerror(errno));
+				exit(FAIL);
+			}
 		}
 	}
 
+	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);
@@ -472,38 +535,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);
@@ -521,40 +567,107 @@ 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 %lu bytes message: %s\n", (long)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;
 }
@@ -581,6 +694,7 @@ static void stop_rx_thread(void)
 
 	if (rx_thread) {
 		printf("Shutting down rx thread\n");
+		sleep(2);
 		pthread_cancel(rx_thread);
 		pthread_join(rx_thread, &retval);
 		for (i = 0; i < PCKT_FRAG_MAX; i ++) {
@@ -600,18 +714,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);
 
@@ -639,6 +859,10 @@ int main(int argc, char *argv[])
 
 	setup_knet(argc, argv);
 
+	setup_data_txrx_common();
+
+	sleep(5);
+
 restart:
 	switch(test_type) {
 		default:
@@ -646,11 +870,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 9b88b6c..39181a1 100644
--- a/libknet/threads_send_recv.c
+++ b/libknet/threads_send_recv.c
@@ -28,6 +28,7 @@
 #include "transports.h"
 #include "threads_common.h"
 #include "threads_send_recv.h"
+#include "netutils.h"
 
 /*
  * SEND
@@ -808,7 +809,9 @@ static int pckt_defrag(knet_handle_t knet_h, struct knet_header *inbuf, ssize_t
 	return 1;
 }
 
-static void _parse_recv_from_links(knet_handle_t knet_h, struct mmsghdr *msg)
+#include <stdio.h>
+
+static void _parse_recv_from_links(knet_handle_t knet_h, int sockfd, struct mmsghdr *msg)
 {
 	int err = 0, savederrno = 0;
 	ssize_t outlen;
@@ -822,7 +825,6 @@ static void _parse_recv_from_links(knet_handle_t knet_h, struct mmsghdr *msg)
 	struct knet_header *inbuf = msg->msg_hdr.msg_iov->iov_base;
 	unsigned char *outbuf = (unsigned char *)msg->msg_hdr.msg_iov->iov_base;
 	ssize_t len = msg->msg_len;
-	struct sockaddr_storage *address = msg->msg_hdr.msg_name;
 	struct knet_hostinfo *knet_hostinfo;
 	struct iovec iov_out[1];
 	int8_t channel;
@@ -863,19 +865,39 @@ static void _parse_recv_from_links(knet_handle_t knet_h, struct mmsghdr *msg)
 		src_link = src_host->link +
 				(inbuf->khp_ping_link % KNET_MAX_LINK);
 		if (src_link->dynamic == KNET_LINK_DYNIP) {
-			if (memcmp(&src_link->dst_addr, address, sizeof(struct sockaddr_storage)) != 0) {
+			if (cmpaddr(&src_link->dst_addr, sockaddr_len(&src_link->dst_addr),
+				    msg->msg_hdr.msg_name, sockaddr_len(msg->msg_hdr.msg_name)) != 0) {
+				int x;
+				unsigned char *bar, *foo;
+
+				foo = (unsigned char *)&src_link->dst_addr;
+				bar = (unsigned char *)msg->msg_hdr.msg_name;
+
+				for (x = 0;x < sockaddr_len(msg->msg_hdr.msg_name); x++) {
+					if (bar[x] != foo[x]) {
+						fprintf(stderr, "offset: %d foo: %02x bar: %02x\n", x, foo[x], bar[x]);
+					}
+				}
+
 				log_debug(knet_h, KNET_SUB_RX, "host: %u link: %u appears to have changed ip address",
 					  src_host->host_id, src_link->link_id);
-				memmove(&src_link->dst_addr, address, sizeof(struct sockaddr_storage));
-				if (knet_addrtostr(&src_link->dst_addr, sizeof(struct sockaddr_storage),
+				memset(&src_link->dst_addr, 0, sizeof(struct sockaddr_storage));
+				memmove(&src_link->dst_addr, msg->msg_hdr.msg_name, sockaddr_len(msg->msg_hdr.msg_name));
+				if (knet_addrtostr(&src_link->dst_addr, sockaddr_len(msg->msg_hdr.msg_name),
 						src_link->status.dst_ipaddr, KNET_MAX_HOST_LEN,
 						src_link->status.dst_port, KNET_MAX_PORT_LEN) != 0) {
 					log_debug(knet_h, KNET_SUB_RX, "Unable to resolve ???");
 					snprintf(src_link->status.dst_ipaddr, KNET_MAX_HOST_LEN - 1, "Unknown!!!");
 					snprintf(src_link->status.dst_port, KNET_MAX_PORT_LEN - 1, "??");
+				} else {
+					log_debug(knet_h, KNET_SUB_RX, "NEW CONN: %s %s", src_link->status.dst_ipaddr, src_link->status.dst_port);
 				}
 			}
-			src_link->status.dynconnected = 1;
+			/*
+			 * transport has already accepted the connection here
+			 * otherwise we would not be receiving packets
+			 */
+			knet_h->transport_ops[src_link->transport_type]->transport_link_dyn_connect(knet_h, sockfd, src_link);
 		}
 	}
 
@@ -1206,6 +1228,20 @@ static void _handle_recv_from_links(knet_handle_t knet_h, int sockfd, struct mms
 	}
 
 	for (i = 0; i < msg_recv; i++) {
+		int x;
+		unsigned char *bar;
+		struct sockaddr_storage *foo;
+
+		bar = (unsigned char *)msg->msg_hdr.msg_name;
+		foo = (struct sockaddr_storage *)msg->msg_hdr.msg_name;
+		if (foo->ss_family == AF_INET6) {
+			for (x = 0;x < sizeof(struct sockaddr_storage); x++) {
+				if (bar[x] != 0) {
+					//fprintf(stderr, "offset: %d bar: %02x\n", x, bar[x]);
+				}
+			}
+		}
+
 		err = knet_h->transport_ops[transport]->transport_rx_is_data(knet_h, sockfd, &msg[i]);
 
 		/*
@@ -1226,7 +1262,7 @@ static void _handle_recv_from_links(knet_handle_t knet_h, int sockfd, struct mms
 				goto exit_unlock;
 				break;
 			case 2: /* packet is data and should be parsed as such */
-				_parse_recv_from_links(knet_h, &msg[i]);
+				_parse_recv_from_links(knet_h, sockfd, &msg[i]);
 				break;
 		}
 	}
diff --git a/libknet/transport_sctp.c b/libknet/transport_sctp.c
index c212922..28f54e2 100644
--- a/libknet/transport_sctp.c
+++ b/libknet/transport_sctp.c
@@ -780,6 +780,8 @@ static void _handle_listen_sctp_errors(knet_handle_t knet_h)
 	sctp_handle_info_t *handle_info = knet_h->transports[KNET_TRANSPORT_SCTP];
 	sctp_accepted_link_info_t *accept_info;
 	sctp_listen_link_info_t *info;
+	struct knet_host *host;
+	int link_idx;
 	int i;
 
 	if (recv(handle_info->listensockfd[0], &sockfd, sizeof(int), MSG_DONTWAIT | MSG_NOSIGNAL) != sizeof(int)) {
@@ -797,6 +799,25 @@ static void _handle_listen_sctp_errors(knet_handle_t knet_h)
 	accept_info = knet_h->knet_transport_fd_tracker[sockfd].data;
 	info = accept_info->link_info;
 
+	/*
+	 * clear all links using this accepted socket as
+	 * outbound dynamically connected socket
+	 */
+
+	for (host = knet_h->host_head; host != NULL; host = host->next) {
+		for (link_idx = 0; link_idx < KNET_MAX_LINK; link_idx++) {
+			if ((host->link[link_idx].dynamic == KNET_LINK_DYNIP) &&
+			    (host->link[link_idx].outsock == sockfd)) {
+				log_debug(knet_h, KNET_SUB_TRANSP_SCTP, "Found dynamic connection on host %d link %d (%d)",
+					  host->host_id, link_idx, sockfd);
+				host->link[link_idx].status.dynconnected = 0;
+				host->link[link_idx].transport_connected = 0;
+				host->link[link_idx].outsock = 0;
+				memset(&host->link[link_idx].dst_addr, 0, sizeof(struct sockaddr_storage));
+			}
+		}
+	}
+
 	for (i=0; i<MAX_ACCEPTED_SOCKS; i++) {
 		if (sockfd == info->accepted_socks[i]) {
 			log_debug(knet_h, KNET_SUB_TRANSP_SCTP, "Closing accepted socket %d", sockfd);
@@ -1078,16 +1099,17 @@ static int sctp_transport_link_set_config(knet_handle_t knet_h, struct knet_link
 		goto exit_error;
 	}
 
-	if (_create_connect_socket(knet_h, link) < 0) {
-		savederrno = errno;
-		err = -1;
-		goto exit_error;
+	if (link->dynamic == KNET_LINK_STATIC) {
+		if (_create_connect_socket(knet_h, link) < 0) {
+			savederrno = errno;
+			err = -1;
+			goto exit_error;
+		}
+		link->outsock = info->connect_sock;
 	}
 
 	knet_list_add(&info->list, &handle_info->connect_links_list);
 
-	link->outsock = info->connect_sock;
-
 exit_error:
 	if (err) {
 		if (info) {
@@ -1107,7 +1129,6 @@ exit_error:
 
 /*
  * called with global wrlock
- * FIX exit path error handling
  */
 static int sctp_transport_link_clear_config(knet_handle_t knet_h, struct knet_link *link)
 {
@@ -1361,6 +1382,14 @@ exit_fail:
 	return err;
 }
 
+static int sctp_transport_link_dyn_connect(knet_handle_t knet_h, int sockfd, struct knet_link *kn_link)
+{
+	kn_link->outsock = sockfd;
+	kn_link->status.dynconnected = 1;
+	kn_link->transport_connected = 1;
+	return 0;
+}
+
 static knet_transport_ops_t sctp_transport_ops = {
 	.transport_name = "SCTP",
 	.transport_id = KNET_TRANSPORT_SCTP,
@@ -1369,6 +1398,7 @@ static knet_transport_ops_t sctp_transport_ops = {
 	.transport_free = sctp_transport_free,
 	.transport_link_set_config = sctp_transport_link_set_config,
 	.transport_link_clear_config = sctp_transport_link_clear_config,
+	.transport_link_dyn_connect = sctp_transport_link_dyn_connect,
 	.transport_rx_sock_error = sctp_transport_rx_sock_error,
 	.transport_tx_sock_error = sctp_transport_tx_sock_error,
 	.transport_rx_is_data = sctp_transport_rx_is_data,
diff --git a/libknet/transport_udp.c b/libknet/transport_udp.c
index 2849928..d2c8b96 100644
--- a/libknet/transport_udp.c
+++ b/libknet/transport_udp.c
@@ -378,6 +378,12 @@ static int udp_transport_rx_is_data(knet_handle_t knet_h, int sockfd, struct mms
 	return 2;
 }
 
+static int udp_transport_link_dyn_connect(knet_handle_t knet_h, int sockfd, struct knet_link *kn_link)
+{
+	kn_link->status.dynconnected = 1;
+	return 0;
+}
+
 static knet_transport_ops_t udp_transport_ops = {
 	.transport_name = "UDP",
 	.transport_id = KNET_TRANSPORT_UDP,
@@ -386,6 +392,7 @@ static knet_transport_ops_t udp_transport_ops = {
 	.transport_free = udp_transport_free,
 	.transport_link_set_config = udp_transport_link_set_config,
 	.transport_link_clear_config = udp_transport_link_clear_config,
+	.transport_link_dyn_connect = udp_transport_link_dyn_connect,
 	.transport_rx_sock_error = udp_transport_rx_sock_error,
 	.transport_tx_sock_error = udp_transport_tx_sock_error,
 	.transport_rx_is_data = udp_transport_rx_is_data,
