diff --git a/src/acs.c b/src/acs.c
index 6c014f083ec8dfc56171c2db1cf9f28cb4cc1c37..78a3aa45531493f52d9aecab6b83ed95c654ae13 100644
--- a/src/acs.c
+++ b/src/acs.c
@@ -18,6 +18,7 @@
 #include "cntlr.h"
 #include "cntlr_cmdu.h"
 #include "utils/debug.h"
+#include "utils/liblist.h"
 #include "wifi_dataelements.h"
 #include "wifi_opclass.h"
 
@@ -364,7 +365,7 @@ void cntlr_acs_recalc(struct controller *c, bool skip_dfs)
 {
 	struct node *n = NULL;
 
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_active_entry(n, &c->nodelist, list) {
 		cntlr_acs_node_channel_recalc(n, skip_dfs);
 	}
 }
@@ -492,7 +493,7 @@ void cntlr_dfs_cleanup(struct controller *c)
 {
 	struct node *n = NULL;
 
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_active_entry(n, &c->nodelist, list) {
 		cntlr_dfs_node_cleanup(n);
 	}
 }
diff --git a/src/cntlr.c b/src/cntlr.c
index 9d290cd4bcacf475b2954ede6de9eab2cd8abd65..374bceee383f018e57b86799574bb2d377a6c565 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -50,6 +50,7 @@
 #include "timer_impl.h"
 #include "topology.h"
 #include "utils/debug.h"
+#include "utils/liblist.h"
 #include "utils/utils.h"
 #include "wifi_dataelements.h"
 #include "wifi_opclass.h"
@@ -120,6 +121,17 @@ struct node *cntlr_find_node(struct controller *c, uint8_t *macaddr)
 	return (struct node *)entry->data;
 }
 
+bool cntlr_node_is_active(struct controller *c, uint8_t *macaddr)
+{
+	struct macaddr_entry *entry = NULL;
+
+	entry = mactable_lookup(c->mac_table, macaddr, MAC_ENTRY_ALID);
+	if (WARN_ON(!entry))
+		return false;
+
+	return (((struct node *)entry->data)->is_active);
+}
+
 /* finds radio struct from interface macaddr */
 struct netif_radio *cntlr_find_radio_with_bssid(struct controller *c, uint8_t *bssid)
 {
@@ -413,7 +425,7 @@ void cntlr_send_max_wifi_bh_hops_policy(struct controller *c)
 	trace("%s: max_node_bh_hops %d\n",
 		  __func__, c->cfg.max_node_bh_hops);
 
-	list_for_each_entry(node, &c->nodelist, list) {
+	list_for_each_active_entry(node, &c->nodelist, list) {
 		enum bh_control {
 			BLOCK = 0x00,
 			UNBLOCK = 0x01
@@ -562,6 +574,12 @@ struct cmdu_buff *cntlr_query_sta_metric(struct controller *c, struct sta *s)
 		return NULL;
 	}
 
+	if (!cntlr_node_is_active(c, s->agent_almacaddr)) {
+		cntlr_dbg(LOG_STA, "%s: Agent " MACFMT " is not active\n",
+			  __func__, MAC2STR(s->agent_almacaddr));
+		return NULL;
+	}
+
 	return cntlr_gen_sta_metric_query(c, s->agent_almacaddr, s->macaddr);
 }
 
@@ -569,7 +587,7 @@ static void cntlr_get_all_sta_metrics(struct controller *c)
 {
 	struct node *n = NULL;
 
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_entry(n, &c->nodelist, list) { /* also inactive */
 		struct sta *s = NULL;
 
 		list_for_each_entry(s, &n->stalist, list) {
@@ -1042,7 +1060,7 @@ static void cntlr_query_nodes(atimer_t *t)
 	struct controller *c = container_of(t, struct controller, query_nodes);
 	struct node *n = NULL;
 
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_active_entry(n, &c->nodelist, list) {
 		struct cmdu_buff *cmdu;
 
 		cmdu = cntlr_gen_bk_caps_query(c, n->almacaddr);
@@ -1089,7 +1107,7 @@ bool cntlr_check_config_diff(struct controller *c, uint32_t diff)
 		trace("agent policy config changed\n");
 
 		/* send the policy config cmdu to the marked agent */
-		list_for_each_entry(n, &c->nodelist, list) {
+		list_for_each_active_entry(n, &c->nodelist, list) {
 			struct cmdu_buff *cmdu;
 			int num_bk = 0;
 			uint8_t bk_id[16 * 6] = {0};
@@ -1140,7 +1158,7 @@ bool cntlr_check_config_diff(struct controller *c, uint32_t diff)
 		cntlr_dbg(LOG_QOS, "qos config changed\n");
 
 		/* send the policy config cmdu to the marked agent */
-		list_for_each_entry(n, &c->nodelist, list) {
+		list_for_each_active_entry(n, &c->nodelist, list) {
 			cntlr_qos_sync_node(c, n->almacaddr);
 		}
 	}
@@ -1152,7 +1170,7 @@ bool cntlr_check_config_diff(struct controller *c, uint32_t diff)
 		trace("ap mld config changed\n");
 
 		/* send the ap mld config cmdu to the agent */
-		list_for_each_entry(n, &c->nodelist, list)
+		list_for_each_active_entry(n, &c->nodelist, list)
 			cntlr_send_ap_mld_configuration_request(c, n);
 	}
 
@@ -1162,7 +1180,7 @@ bool cntlr_check_config_diff(struct controller *c, uint32_t diff)
 		trace("bsta mld config changed\n");
 
 		/* send the ap mld config cmdu to the agent */
-		list_for_each_entry(n, &c->nodelist, list)
+		list_for_each_active_entry(n, &c->nodelist, list)
 			cntlr_send_bsta_mld_configuration_request(c, n);
 	}
 #endif
@@ -1185,7 +1203,7 @@ int cntlr_sync_dyn_controller_config(struct controller *c, uint8_t *agent)
 		send_cmdu(c, cmdu);
 		cmdu_free(cmdu);
 	} else {
-		list_for_each_entry(n, &c->nodelist, list) {
+		list_for_each_active_entry(n, &c->nodelist, list) {
 			if (hwaddr_equal(c->almacaddr, n->almacaddr))
 				continue; /* skip locally running agent */
 
@@ -1257,6 +1275,11 @@ static void cntlr_ageout_nodes(struct controller *c)
 	/* Here we need to see that all nodes in nodelist */
 	/* and check there timestamp */
 	list_for_each_entry_safe(n, tmp, &c->nodelist, list) {
+		if (timestamp_expired(&n->last_tsp_seen, NODE_INACTIVE_TIME * 1000)) {
+			topology_remove_device(&c->topology, n->almacaddr);
+			n->is_active = false;
+		}
+
 		if (timestamp_expired(&n->last_tsp_seen, NODE_EXPIRE_TIME * 1000)) {
 
 			list_for_each_entry_safe(r, temp, &n->radiolist, list) {
@@ -1264,7 +1287,6 @@ static void cntlr_ageout_nodes(struct controller *c)
 			}
 
 			cntlr_config_del_node(n->almacaddr);
-			topology_remove_device(&c->topology, n->almacaddr);
 			node_clean_stalist(c, n);
 			cntlr_clean_radiolist(c, n);
 			mactable_del_entry(c->mac_table, n->almacaddr, MAC_ENTRY_ALID);
@@ -1283,7 +1305,7 @@ static void cntlr_renew_nodes_configuration(struct controller *c)
 
 	/* When at least one running node was configured with older config, */
 	/* send autoconfig renew */
-	list_for_each_entry(node, &c->nodelist, list) {
+	list_for_each_active_entry(node, &c->nodelist, list) {
 		if (!timestamp_invalid(&node->last_config) &&
 		    timestamp_less_than(&node->last_config, &c->cfg.last_change) &&
 		    timestamp_greater_than(&node->last_cmdu, &c->cfg.last_change)) {
@@ -1329,7 +1351,7 @@ static void combined_link_metric_periodic_collection(struct controller *c)
 
 	/* AP metrics query for each agent */
 	/* For each agent */
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_active_entry(n, &c->nodelist, list) {
 		uint8_t *new_radiolist;
 		struct netif_radio *r = NULL;
 		int num_bss = 0, num_radio = 0;
diff --git a/src/cntlr.h b/src/cntlr.h
index 58139fdc2176b41903c19196d4f05bbfafaa2a7b..ee6b8f16f62ba20dee9a0186aee2238d3095241a 100644
--- a/src/cntlr.h
+++ b/src/cntlr.h
@@ -42,7 +42,8 @@ struct tlv_tx_linkmetric;
 #define LIMIT_STA_COUNT (100)
 #endif
 
-#define NODE_EXPIRE_TIME 65
+#define NODE_INACTIVE_TIME 65
+#define NODE_EXPIRE_TIME (7 * 24 * 60 * 60) /* 7 days */
 #define METRIC_REP_INTERVAL 10
 
 extern const char *ubus_socket;
@@ -229,6 +230,7 @@ struct uobj_struct {
 struct node {
 	uint8_t almacaddr[6];
 	enum nodetype type;
+	bool is_active;
 	int depth;                         /** >= 0 or -1 for unknown */
 	int ul_type;                       /** uplink type */
 	uint32_t est_thput_ul;		   /* estimated l3 throughput achievable in uplink dir */
@@ -370,6 +372,7 @@ struct sta_error_response {
 struct node *cntlr_add_node(struct controller *c, uint8_t *almacaddr);
 struct node *cntlr_alloc_node(struct controller *c, uint8_t *almacaddr);
 struct node *cntlr_find_node(struct controller *c, uint8_t *almacaddr);
+bool cntlr_node_is_active(struct controller *c, uint8_t *macaddr);
 struct node *cntlr_find_node_with_bssid(struct controller *c, uint8_t *bssid);
 
 struct netif_link *cntlr_alloc_link(struct controller *c,
diff --git a/src/cntlr_cmdu.c b/src/cntlr_cmdu.c
index 083cb0b84f58d2970afc8e406db5df4b8621e2a4..f5748d55bb99f6fd6e60106b32d445849b4b25f5 100644
--- a/src/cntlr_cmdu.c
+++ b/src/cntlr_cmdu.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 #include "utils/debug.h"
+#include "utils/liblist.h"
 #include "cntlr.h"
 #include "cntlr_map.h"
 #include "cntlr_tlv.h"
@@ -1449,7 +1450,7 @@ int send_agent_list_to_all_nodes(struct controller *c)
 	}
 
 	ret = 0;
-	list_for_each_entry(node, &c->nodelist, list) {
+	list_for_each_active_entry(node, &c->nodelist, list) {
 		memcpy(cmdu->origin, node->almacaddr, 6);
 		if (send_cmdu(c, cmdu) == 0xffff)
 			ret = -1;
diff --git a/src/cntlr_commands_impl.c b/src/cntlr_commands_impl.c
index fe91910e06a1bcfae21eece70f97577f492da79f..11790453ad4ae1388423877c97eaa63935b8d268 100644
--- a/src/cntlr_commands_impl.c
+++ b/src/cntlr_commands_impl.c
@@ -26,6 +26,7 @@
 #include "cntlr_map.h"
 #include "cntlr_tlv.h"
 #include "config.h"
+#include "utils/liblist.h"
 #include "utils/utils.h"
 #include "timer.h"
 #include "sta.h"
@@ -1149,7 +1150,7 @@ int COMMAND(trigger_channel_clearing)(void *priv, void *args, void *out)
 	if (!hwaddr_aton(agent, agent_mac))
 		return -EINVAL;
 
-	list_for_each_entry(node, &c->nodelist, list) {
+	list_for_each_active_entry(node, &c->nodelist, list) {
 		if (!hwaddr_is_zero(agent_mac) && memcmp(agent_mac, node->almacaddr, 6))
 			continue;
 
@@ -2336,7 +2337,7 @@ int COMMAND(query_channel_pref)(void *priv, void *args, void *out)
 	if (hwaddr_is_zero(agent_mac)) {
 		struct node *n = NULL;
 
-		list_for_each_entry(n, &c->nodelist, list) {
+		list_for_each_active_entry(n, &c->nodelist, list) {
 			cmdu = cntlr_gen_channel_preference_query(c, n->almacaddr);
 			if (!cmdu)
 				continue;
@@ -2950,7 +2951,7 @@ static int _cntlr_status(struct controller *c, void *args, void *out, bool full)
 		t = blobmsg_open_table(bb, "");
 		blobmsg_add_string(bb, "ieee1905id", hwaddrstr);
 		blobmsg_add_u32(bb, "profile", n->map_profile);
-
+		blobmsg_add_u32(bb, "active", n->is_active ? 1 : 0);
 
 		b = blobmsg_open_array(bb, "radios");
 		list_for_each_entry(p, &n->radiolist, list) {
diff --git a/src/cntlr_map.c b/src/cntlr_map.c
index b26ba55cc82d9b3365a6f1ba0667ddce3a639b5f..88b7af19714b2cbf1b648c4ce744e83b3f901084 100644
--- a/src/cntlr_map.c
+++ b/src/cntlr_map.c
@@ -37,6 +37,7 @@
 #endif
 #endif
 
+#include "utils/liblist.h"
 #include "utils/utils.h"
 #include "utils/debug.h"
 #include "config.h"
@@ -116,7 +117,7 @@ int send_dpp_cce_indication(struct controller *c, uint8_t *agent,
 	} else {
 		struct node *n = NULL;
 
-		list_for_each_entry(n, &c->nodelist, list) {
+		list_for_each_active_entry(n, &c->nodelist, list) {
 			struct cmdu_buff *cmdu;
 
 			cmdu = cntlr_gen_dpp_cce_indication(c, n->almacaddr, advertise);
@@ -4031,8 +4032,10 @@ int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
 	}
 
 	/* update the timestamp of the node */
-	if (n)
+	if (n) {
 		timestamp_update(&n->last_tsp_seen);
+		n->is_active = true;
+	}
 
 	cmdu = cmdu_alloc_custom(cmdutype, &mid, rxif, src, tlvs, len);
 	if (!cmdu) {
@@ -4048,8 +4051,10 @@ int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
 	if (!n)
 		n = cntlr_find_node(c, origin);
 
-	if (n)
+	if (n) {
 		timestamp_update(&n->last_cmdu);
+		n->is_active = true;
+	}
 
 	cmdu_free(cmdu);
 	return ret;
diff --git a/src/cntlr_tlv.c b/src/cntlr_tlv.c
index 1f0ec6c4ee4384059cdfdfe0ede09ef4b9507583..801b805bfd56f440d2ea78c037f2754a0d24be85 100644
--- a/src/cntlr_tlv.c
+++ b/src/cntlr_tlv.c
@@ -25,6 +25,7 @@
 #include <wifidefs.h>
 
 
+#include "utils/liblist.h"
 #include "utils/utils.h"
 #include "utils/debug.h"
 #include "cntlr.h"
@@ -2519,7 +2520,7 @@ int cntlr_gen_agent_list_tlv(struct controller *c, struct cmdu_buff *frm, uint8_
 		return -1;
 
 	i = 0;
-	list_for_each_entry(n, &c->nodelist, list) {
+	list_for_each_active_entry(n, &c->nodelist, list) {
 		dbg("\tagent[%d]:\n", i);
 
 		/* node aladdr */
diff --git a/src/dpp.c b/src/dpp.c
index 5319b6fb9a241f74b0d548ee0b10ffc4d3bac79e..f3fe8f4bb3fccd6ae4efb514f83581508522371c 100644
--- a/src/dpp.c
+++ b/src/dpp.c
@@ -19,6 +19,7 @@
 #include "cntlr_map.h"
 #include "easy/utils.h"
 #include "utils/debug.h"
+#include "utils/liblist.h"
 
 
 const char *dpp_frame_type2str(uint8_t type)
@@ -278,7 +279,7 @@ int dpp_frame_handler(void *dpp, uint8_t *smac, enum dpp_event ev,
 			if (proxy) {
 				struct node *n = NULL;
 
-				list_for_each_entry(n, &c->nodelist, list) {
+				list_for_each_active_entry(n, &c->nodelist, list) {
 					memcpy(resp->origin, n->almacaddr, 6);
 					err("|%s:%d| send frame to "MACFMT"\n", __func__, __LINE__, MAC2STR(n->almacaddr));
 					send_cmdu(c, resp);
diff --git a/src/utils/liblist.h b/src/utils/liblist.h
index d5c9bc4f75e0398b0f9936e71499914f72973294..24ee5320a038c3437f8dcf5b130a294e9a1a8f5a 100644
--- a/src/utils/liblist.h
+++ b/src/utils/liblist.h
@@ -47,4 +47,9 @@ void merge_sort(void *priv, struct list_head *head,
 #define list_sort	merge_sort
 #endif
 
+#define list_for_each_active_entry(p, head, field) \
+	for (p = list_first_entry(head, typeof(*p), field); &p->field != (head); \
+	     p = list_entry(p->field.next, typeof(*p), field)) \
+	     if (p->is_active)
+
 #endif /* LIBLIST_H */