Index: usr/click/lib/libdns_agent/Makefile
===================================================================
--- usr/click/lib/libdns_agent/Makefile	(revision 37934)
+++ usr/click/lib/libdns_agent/Makefile	(working copy)
@@ -34,7 +34,7 @@
 	  -L${.OBJDIR}/../libhttp_utils -lhttp_utils \
 	  -L${.OBJDIR}/../libfastlog -lfastlog \
 	  -L${.OBJDIR}/../libenglog -lenglog \
-	  -lcrypt -lm -lz
+	  -lcrypt -lanl -lm -lz
 
 .if defined(USTACK)
 .include <bsd.lib.mk>
Index: usr/click/lib/libdns_agent/dns_daemon.c
===================================================================
--- usr/click/lib/libdns_agent/dns_daemon.c	(revision 37934)
+++ usr/click/lib/libdns_agent/dns_daemon.c	(working copy)
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
 #include <bsd/bsd.h>
 
 #include <stdio.h>
@@ -9,11 +10,14 @@
 #include <arpa/inet.h>
 #include <sys/stat.h>
 #include <sys/resource.h>
+#include <netdb.h>
+#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <sys/syslog.h>
 
+
 #include <click/sys/uproxy_limits.h>
 #include "dns_daemon.h"
 #include "webagent_dns.h"
@@ -41,6 +45,17 @@
 extern void* atcp_event_inrq_dequeue(uint16_t app_id);
 extern int atcp_event_outrq_enqueue(int thread_id, void *buf, uint16_t app_id);
 
+struct dns_req_ctx {
+	int busy_fl;
+	webagent_dns_data_t *webagent_ctx;
+	struct gaicb *req[1];
+	struct gaicb req_item;
+};
+#define DNS_REQ_LIST_LEN 20
+
+static __thread struct dns_req_ctx dns_req_wait_list[DNS_REQ_LIST_LEN];
+__thread int outstanding_dns_req_cnt = 0;
+
 static time_t 
 get_nsfile_last_mtime(void)
 {
@@ -383,6 +398,7 @@
 	return;
 }
 
+/* not used, replaced with domain_resolve_asynch */
 static void 
 domain_resolve(char ns_table[][INET6_ADDRSTRLEN], int n_ns, char *host, webagent_dns_data_t *dns_data_p)
 {
@@ -397,7 +413,113 @@
 	return;
 }
 
+static int
+domain_resolve_asynch(char *host, webagent_dns_data_t *dns_data_p)
+{
+	int free_idx = 0;
+	int ret;
+
+	/* find first free slot and Queue nreqs_base..nreqs requests. */
+	while (free_idx < DNS_REQ_LIST_LEN) {
+		if (dns_req_wait_list[free_idx].busy_fl == 0) {
+			break;
+		}
+		free_idx++;
+	}
+	if (free_idx > DNS_REQ_LIST_LEN) {
+		/* Note: this should not happen because in the thread func we do not read if list is full */
+		fastlog_syslog(LOG_DEBUG, "%s: run out of free requests %d", __FUNCTION__, outstanding_dns_req_cnt);
+		ulog_error_no_conn(AMP_ULOG_WEBAGENT, "run out of free requests");
+		return -1;
+	}
+	dns_req_wait_list[free_idx].req_item.ar_name = host;
+	dns_req_wait_list[free_idx].req_item.ar_service = NULL;
+	dns_req_wait_list[free_idx].req_item.ar_request = NULL; //hints will be default
+	dns_req_wait_list[free_idx].req_item.ar_result = NULL;
+	dns_req_wait_list[free_idx].req[0] = &(dns_req_wait_list[free_idx].req_item);
+
+	ret = getaddrinfo_a(GAI_NOWAIT, dns_req_wait_list[free_idx].req, 1, NULL);
+	if (ret) {
+		fastlog_syslog(LOG_DEBUG, "%s: getaddrinfo_a failed %d", __FUNCTION__, ret);
+		ulog_error_no_conn(AMP_ULOG_WEBAGENT, "getaddrinfo_a failed %d", ret);
+		return -2;
+	}
+	/* dns req successfully sent */
+	dns_req_wait_list[free_idx].webagent_ctx = dns_data_p;
+	dns_req_wait_list[free_idx].busy_fl = 1;
+	outstanding_dns_req_cnt++;
+	//fastlog_syslog(LOG_DEBUG, "%s: sent req for %s(idx %d), out reqs %d",
+	//	       __FUNCTION__, host, free_idx, outstanding_dns_req_cnt);
+	return 0;
+}
+
 static void
+cleanup_poll_item(struct dns_req_ctx *poll_item)
+{
+	poll_item->webagent_ctx = NULL;
+	poll_item->busy_fl = 0;
+	outstanding_dns_req_cnt--;
+}
+
+static int
+domain_resolve_poll()
+{
+	int ret;
+	struct addrinfo *res;
+	struct gaicb *req_p;
+	webagent_dns_data_t *webagent_ctx;
+	int poll_freed_cnt = 0;
+
+	for (int i = 0; i < DNS_REQ_LIST_LEN; i++) {
+		if (dns_req_wait_list[i].busy_fl == 0) {
+			continue;
+		}
+		req_p = dns_req_wait_list[i].req[0];
+		ret = gai_error(req_p);
+
+		if (ret == EAI_INPROGRESS) {
+			continue;
+		}
+		webagent_ctx = dns_req_wait_list[i].webagent_ctx;
+
+		if (ret == 0) {
+			/* ready */
+			res = req_p->ar_result;
+			if (res->ai_addr->sa_family == AF_INET) {
+				struct sockaddr_in *my_addr = (struct sockaddr_in *)res->ai_addr;
+				fastlog_syslog(LOG_DEBUG, "%s: [%d], outstanding req %d, thread id %d: host %s -> ip %s",
+					       __FUNCTION__, i, outstanding_dns_req_cnt, webagent_ctx->thread_id,
+					       webagent_ctx->host, inet_ntoa(my_addr->sin_addr));
+
+				webagent_ctx->iptable.ip4_dns_record_table[0].ip = my_addr->sin_addr.s_addr;
+			} else {
+				struct sockaddr_in6 *my_addr = (struct sockaddr_in6 *)res->ai_addr;
+				webagent_ctx->iptable.ip6_dns_record_table[0].ip = my_addr->sin6_addr;
+			}
+			webagent_ctx->ip_num = 1;
+		} else {
+			/* error from dns lookup */
+			fastlog_syslog(LOG_DEBUG, "%s: getaddrinfo_a poll failed, thread id [%hu], host %s",
+				       __FUNCTION__, webagent_ctx->thread_id,  webagent_ctx->host);
+			ulog_error_no_conn(AMP_ULOG_WEBAGENT, "getaddrinfo_a poll failed, thread id [%hu]",
+					   webagent_ctx->thread_id);
+		}
+		/* send it back */
+		ret = atcp_event_outrq_enqueue(webagent_ctx->thread_id, (void*)webagent_ctx, ATCP_DNS_RQ);
+		if (ret != 0) {
+			fastlog_syslog(LOG_DEBUG, "%s: failed to send dns reply back to webagent [%hu]",
+				       __FUNCTION__, webagent_ctx->thread_id);
+			ulog_error_no_conn(AMP_ULOG_WEBAGENT, "failed to insert webagent dns data to outrq [%hu]",
+					   webagent_ctx->thread_id);
+			WEBAGENT_DNS_FREE(webagent_ctx);
+		}
+		cleanup_poll_item(&dns_req_wait_list[i]);
+		poll_freed_cnt++;
+	}
+	return poll_freed_cnt;
+}
+
+static void
 dns_process_data_cb(void *data)
 {
 	int ret;
@@ -417,22 +539,27 @@
 	dns_data_p->thread_id = input_data_p->thread_id;
 
 	if (dns_nameserver_avail) {
-		domain_resolve(ns_table, NAMESERVER_MAX_NUM, input_data_p->host, dns_data_p);
-		if (dns_data_p->ip_num == 0) {
-			dbg_printf("%s: failed to DNS lookup ip address", __FUNCTION__);
-			syslog(LOG_EMERG, "%s: failed to DNS lookup ip address", __FUNCTION__);
-			ulog_error_no_conn(AMP_ULOG_WEBAGENT, "%s: failed to DNS lookup ip address", __FUNCTION__);
+		ret = domain_resolve_asynch(input_data_p->host, dns_data_p);
+		if (ret) {
+			fastlog_syslog(LOG_DEBUG, "%s: failed to send DNS request", __FUNCTION__);
+			ulog_error_no_conn(AMP_ULOG_WEBAGENT, "failed to send DNS request");
+			goto sendback;
 		}
+		/*
+		 * Note: successfully sent a query to dns server, we do not need to enqueue anything back right now,
+		 * we will send back to webagent from the domain_resolve_poll function
+		 */
+		return;
 	}
-
+sendback:
+	/* did not send a query to the dns server, just send back to webagent */
 	ret = atcp_event_outrq_enqueue(input_data_p->thread_id, (void*)dns_data_p, ATCP_DNS_RQ);
 	if (ret != 0) {
 		dbg_printf("%s: failed to insert webagent dns data to outrq [%hu]", __FUNCTION__, input_data_p->thread_id);
-		syslog(LOG_EMERG, "%s: failed to insert webagent dns data to outrq [%hu]", __FUNCTION__, input_data_p->thread_id);
+		fastlog_syslog(LOG_DEBUG, "%s: failed to insert webagent dns data to outrq [%hu]", __FUNCTION__, input_data_p->thread_id);
 		ulog_error_no_conn(AMP_ULOG_WEBAGENT, "%s: failed to insert webagent dns data to outrq [%hu]", __FUNCTION__, input_data_p->thread_id);
 		WEBAGENT_DNS_FREE(dns_data_p);
 	}
-	
 	return;
 }
 
@@ -441,7 +568,7 @@
 {
 	if(user_ticks_init() != 0){
         printf("Could not access system ticks.. exiting\n");
-		fastlog_syslog(LOG_ERR, "Could not access system ticks.. exiting\n");
+        fastlog_syslog(LOG_ERR, "Could not access system ticks.. exiting\n");
         return -1;
     }
 
@@ -483,21 +610,33 @@
 			last_ticks = click_softticks100;
 		}
 
-		if (atcp_event_inrq_empty(ATCP_DNS_RQ)) {
-            usleep(DNS_AGENT_SLEEP_TIME);
-            continue;
-        }
+		if (atcp_event_inrq_empty(ATCP_DNS_RQ) && outstanding_dns_req_cnt == 0) {
+			/* nothing incoming or outstanding */
+			usleep(DNS_AGENT_SLEEP_TIME);
+			continue;
+		}
 
+		if (outstanding_dns_req_cnt) {
+			if (domain_resolve_poll() == 0) {
+				/* nothing freed up from the poll */
+				usleep(DNS_AGENT_SLEEP_TIME);
+			}
+		}
+
 		while (!atcp_event_inrq_empty(ATCP_DNS_RQ)) {
-			data_p = atcp_event_inrq_dequeue(ATCP_DNS_RQ);
-			if (data_p == NULL) {
+			if(outstanding_dns_req_cnt < DNS_REQ_LIST_LEN) {
+				/* only read if we have room in the dns req list */
+				data_p = atcp_event_inrq_dequeue(ATCP_DNS_RQ);
+				if (data_p == NULL) {
+					break;
+				}
+				dns_process_data_cb(data_p);
+				WEBAGENT_DNS_FREE(data_p);
+			} else {
+				/* poll is full cannot send right now */
 				break;
 			}
-
-			dns_process_data_cb(data_p);
-			WEBAGENT_DNS_FREE(data_p);
 		}
-
 	}
 }
 
Index: usr/click/lib/libuinet-atcp/bin/atcp/Makefile
===================================================================
--- usr/click/lib/libuinet-atcp/bin/atcp/Makefile	(revision 37934)
+++ usr/click/lib/libuinet-atcp/bin/atcp/Makefile	(working copy)
@@ -11,7 +11,7 @@
 CXXFLAGS= -std=c++11 -I${TOPDIR}/../libbreakpad/build/src
 LIBBREAKPAD_CLIENT=${TOPDIR}/../libbreakpad/build/src/client/linux/libbreakpad_client.a
 ifneq ($(ARM64), yes)
-LDADD= -L${UINET_DESTDIR}/lib/ -lm -lpcap \
+LDADD= -L${UINET_DESTDIR}/lib/ -lanl -lm -lpcap \
 	-L${RTE_SDK}/${RTE_TARGET}/lib -ldpdk \
 	-Wl,--start-group \
 	-L${TOPDIR}/../libenv -lenv \
@@ -79,7 +79,7 @@
 	-ludev \
 	-lpciaccess ${TOPDIR}/lib/libev/.libs/libev.a
 else
-LDADD= -L${UINET_DESTDIR}/lib/ -lm -lpcap \
+LDADD= -L${UINET_DESTDIR}/lib/ -lanl -lm -lpcap \
 	-L${RTE_SDK}/${RTE_TARGET}/lib -ldpdk \
 	-Wl,--start-group \
 	-L${TOPDIR}/../libenv -lenv \
