From 95da31064f5b1aa9585e45cc3fa1f9cb9ce58676 Mon Sep 17 00:00:00 2001
From: "nevadita.chatterjee" <nevadita.chatterjee@iopsys.eu>
Date: Thu, 30 Jul 2020 16:35:50 +0530
Subject: [PATCH] map-topology: add 'changelog'

---
 src/topo_ieee1905.c |  10 ++-
 src/topologyd.c     | 194 +++++++++++++++++++++++++++++++++++++++++---
 src/topologyd.h     |   6 +-
 3 files changed, 196 insertions(+), 14 deletions(-)

diff --git a/src/topo_ieee1905.c b/src/topo_ieee1905.c
index b9a9e8b..94811d7 100644
--- a/src/topo_ieee1905.c
+++ b/src/topo_ieee1905.c
@@ -49,16 +49,19 @@ static void topologyd_node_expired(struct uloop_timeout *t)
 	struct node *p = container_of(t, struct node, validity_timer);
 	struct topologyd_private *priv = p->priv;
 
+	//Here we log in the changelog as the node will be deleted
+	changelog_copy_node_info(priv, p, 1, 1);
+
 	if (priv) {
 		node_del(priv->topo.node_htable, p->hwaddr);
 	}
+	priv->topo.num_nodes--;
 }
 
 int topologyd_node_add(struct topologyd_private *priv, struct node *node)
 {
 	struct node *p = NULL;
 
-
 	if (!node || !priv)
 		return -1;
 
@@ -84,7 +87,12 @@ int topologyd_node_add(struct topologyd_private *priv, struct node *node)
 		p->validity_timer.cb = topologyd_node_expired;
 		p->priv = priv;
 		priv->topo.num_nodes++;
+		//Add this in changelog events
+		changelog_copy_node_info(priv, p, 0, 1); 
+
 	} else {
+		//update in changelog
+		update_changelog_info(priv, p, node);	
 		topologyd_copy_update_node(p, node);
 	}
 
diff --git a/src/topologyd.c b/src/topologyd.c
index f1cd507..e326041 100644
--- a/src/topologyd.c
+++ b/src/topologyd.c
@@ -290,21 +290,21 @@ static int topologyd_dump(struct ubus_context *ctx,
 	return 0;
 }
 
-void topologyd_dump_changelog(struct topologyd_private *priv, struct blob_buf *bb)
+void topologyd_print_changelog(struct blob_buf *bb, struct topologyd_private *priv, uint32_t start, uint32_t end) 
 {
 	struct topology_changelog *log;
 	char rpt_ifmacstr[18] = { 0 };
-	char rpt_macstr[18] = { 0 };
-	char nbr_macstr[18] = { 0 };
-	void *a, *t;
-	int i;
-
-	blobmsg_add_u32(bb, "num_changelog", priv->topo.num_changelog);
-
-	a = blobmsg_open_array(bb, "changelog");
-	for (i = 0; i < priv->topo.num_changelog; i++) {
+        char rpt_macstr[18] = { 0 };
+        char nbr_macstr[18] = { 0 };
+        char *timestring;
+        void *t;
+        int i;
+        struct tm *info;
+        time_t tmp_t;
+	
+	dbg("changelog start value is [%d] end value is [%d]", start, end); 
+	for (i = start ; i <= end ; i++) {
 		log = &priv->topo.changelog[i];
-
 		t = blobmsg_open_table(bb, NULL);
 
 		hwaddr_ntoa(log->rpt_macaddr, rpt_macstr);
@@ -317,10 +317,36 @@ void topologyd_dump_changelog(struct topologyd_private *priv, struct blob_buf *b
 		blobmsg_add_string(bb, "neighbor", nbr_macstr);
 
 		blobmsg_add_string(bb, "is1905_neighbor",
-				log->is1905_nbr ? "true" : "false");
+			log->is1905_nbr ? "true" : "false");
 
+		blobmsg_add_string(bb, "event_type",
+			log->type ? "delete" : "add");
+
+		tmp_t = log->timestamp;
+		info = localtime(&tmp_t);
+		timestring = asctime(info);
+		blobmsg_add_string(bb, "timestamp", timestring);
 		blobmsg_close_table(bb, t);
 	}
+}
+void topologyd_dump_changelog(struct topologyd_private *priv, struct blob_buf *bb)
+{
+	void *a;
+	blobmsg_add_u32(bb, "num_changelog", priv->topo.num_changelog);
+
+	a = blobmsg_open_array(bb, "changelog");
+	if(priv->topo.changelog_front == -1) {
+		blobmsg_close_array(bb, a);
+		return;
+	}
+	if(priv->topo.changelog_front > priv->topo.changelog_rear) {
+		topologyd_print_changelog(bb, priv, priv->topo.changelog_front, TOPOLOGY_LOG_MAX-1);
+		topologyd_print_changelog(bb, priv, 0, priv->topo.changelog_rear);
+	}
+	else {
+		topologyd_print_changelog(bb, priv, 0, priv->topo.changelog_rear);
+	}
+
 	blobmsg_close_array(bb, a);
 }
 
@@ -419,6 +445,9 @@ static int topologyd_run(struct topologyd_private *priv)
 	topologyd_start_heartbeat(&priv->heartbeat);
 	topologyd_periodic_refresh(&priv->refresh_timer);
 
+	//initalize the changelog values
+	priv->topo.changelog_front = priv->topo.changelog_rear = -1;
+
 	return 0;
 }
 
@@ -560,3 +589,144 @@ void topologyd_stop(struct topologyd_private *priv)
 	uloop_done();
 	free(priv);
 }
+
+// Check if the changelog queue is full
+int is_full(struct topology *t) 
+{
+	if ((t->changelog_front == t->changelog_rear + 1) || (t->changelog_front == 0 && t->changelog_rear == TOPOLOGY_LOG_MAX - 1)) 
+		return 1;
+	return 0;
+}
+
+// Adding an entry in changelog
+void enqueue_changelog(struct topology *t, struct topology_changelog *c) 
+{
+	dbg("Inside enqueue_changelog \n");
+	struct topology_changelog *elem;	
+	if (is_full(t)) {
+		dbg("Changelog queue is full deleting the front node \n");
+		t->changelog_front = (t->changelog_front + 1) % TOPOLOGY_LOG_MAX;
+		t->num_changelog--;
+	}
+	
+	if (t->changelog_front == -1) 
+		t->changelog_front = 0;
+	t->changelog_rear = (t->changelog_rear + 1) % TOPOLOGY_LOG_MAX;
+	elem =&(t->changelog[t->changelog_rear]);
+	memset(elem, 0, sizeof(struct topology_changelog ));
+	memcpy(elem->rpt_macaddr, c->rpt_macaddr, 6);
+	memcpy(elem->rpt_ifmacaddr, c->rpt_ifmacaddr, 6);
+	memcpy(elem->nbr_macaddr, c->nbr_macaddr, 6);
+	elem->is1905_nbr = c->is1905_nbr;
+	elem->type = c->type;
+	elem->timestamp = time(NULL); 
+	//Maintain the number of elements in changelog
+	t->num_changelog++;
+}
+
+void changelog_copy_node_info(struct topologyd_private *t, struct node *p, int32_t event, bool is1905)
+{
+	dbg("Inside changelog_copy_node_info \n");
+	struct topology_changelog elem;
+
+	if(event == 0)
+		memcpy(elem.rpt_macaddr, p->hwaddr, 6);
+	else
+		memcpy(elem.rpt_macaddr, t->ieee1905_macaddr, 6);
+
+	//add the selfnode macaddress
+	memcpy(elem.rpt_ifmacaddr, t->ieee1905_macaddr, 6);
+	memcpy(elem.nbr_macaddr, p->hwaddr, 6);
+	elem.is1905_nbr = is1905;
+	elem.type = event;
+	enqueue_changelog(&(t->topo), &elem);
+}
+
+void update_changelog_info(struct topologyd_private *priv, struct node *dest, struct node *src)
+{
+	dbg("Inside update_changelog_info \n");
+	int i = 0, j = 0, k = 0, found = 0;
+	struct topology_changelog elem;
+
+	if (dest == NULL || src == NULL || priv == NULL)
+                return;
+
+        //Check the update in neighbor node 
+        if (dest->nbr_num !=  src->nbr_num) {
+		//Here a new neighbor is added or deleted
+		if (dest->nbr_num > src->nbr_num) {
+			dbg("Inside update_changelog_info deleting neighbor node\n");
+			// neighbor node is deleted
+			for( i = 0; i< dest->nbr_num ; i++) {
+				found = 0;
+				for(j = 0; j < src->nbr_num; j++) {
+					if (memcmp(dest->nbrlist[i], src->nbrlist[j], 6) == 0){
+						found = 1;
+						break;
+					}
+				}
+				if (found == 0) {
+					memcpy(elem.nbr_macaddr, dest->nbrlist[i], 6);
+					memcpy(elem.rpt_macaddr, dest->hwaddr, 6);
+					memcpy(elem.rpt_ifmacaddr, dest->hwaddr, 6);
+					elem.is1905_nbr = 1;
+					elem.type = 1;
+					enqueue_changelog(&(priv->topo), &elem);
+				}
+			}
+		}
+		else {
+			dbg("Inside update_changelog_info adding neighbor node\n");
+			//neighbor node is added
+			k = src->nbr_num - dest->nbr_num;
+			for( i = 0; i< k ; i++) {
+				memcpy(elem.nbr_macaddr, src->nbrlist[i], 6);
+				memcpy(elem.rpt_macaddr, src->hwaddr, 6);
+				memcpy(elem.rpt_ifmacaddr, src->hwaddr, 6);
+				elem.is1905_nbr = 1;
+				elem.type = 0;
+				enqueue_changelog(&(priv->topo), &elem);
+			}
+		}
+	}
+
+	//Check the update in non neighbor node
+        if (dest->non1905_nbr_num != src->non1905_nbr_num) {
+		//Here a new non ieee1905 neighbor is added or deleted
+		if (dest->non1905_nbr_num > src->non1905_nbr_num) {
+                        // non1905 neighbor node is deleted
+			dbg("Inside update_changelog_info deleting non neighbor node\n");
+			for( i = 0; i< dest->non1905_nbr_num ; i++) {
+				found = 0;
+				for(j = 0; j < src->non1905_nbr_num; j++) {
+					if (memcmp(dest->non1905_nbrlist[i], src->non1905_nbrlist[j], 6) == 0){
+						found = 1;
+						break;
+					}
+				}
+				if (found == 0) {
+					memcpy(elem.nbr_macaddr, dest->non1905_nbrlist[i], 6);
+					memcpy(elem.rpt_macaddr, dest->hwaddr, 6);
+					memcpy(elem.rpt_ifmacaddr, dest->hwaddr, 6);
+					elem.is1905_nbr = 0;
+					elem.type = 1;
+					enqueue_changelog(&(priv->topo), &elem);
+				}
+			}
+		}
+                else {
+                        //non1905 neighbor node is added
+			dbg("Inside update_changelog_info adding non neighbor node\n");
+                        k = src->non1905_nbr_num - dest->non1905_nbr_num;
+                        for( i = 0; i< k ; i++) {
+                                memcpy(elem.nbr_macaddr, src->non1905_nbrlist[i], 6);
+                                memcpy(elem.rpt_macaddr, src->hwaddr, 6);
+                                memcpy(elem.rpt_ifmacaddr, src->hwaddr, 6);
+                                elem.is1905_nbr = 0;
+                                elem.type = 0;
+                                enqueue_changelog(&(priv->topo), &elem);
+                        }
+                }
+	}
+	return;
+}
diff --git a/src/topologyd.h b/src/topologyd.h
index 04987b6..200fc0d 100644
--- a/src/topologyd.h
+++ b/src/topologyd.h
@@ -63,6 +63,8 @@ struct topology {
 	int32_t num_nodes;
 	uint32_t num_changelog;
 	struct topology_changelog changelog[TOPOLOGY_LOG_MAX];
+	int32_t changelog_front;
+	int32_t changelog_rear;
 	struct hlist_head node_htable[NODE_HTABLE_SIZE];
 };
 
@@ -97,6 +99,8 @@ int topologyd_node_add(struct topologyd_private *priv, struct node *n);
 int topologyd_get_ieee1905_macaddr(struct topologyd_private *p);
 int topologyd_send_ieee1905_topology_query(struct topologyd_private *p,
 								uint8_t *dest);
+void changelog_copy_node_info(struct topologyd_private *t, struct node *p, 
+				int32_t event, bool is1905);
 
-
+void update_changelog_info(struct topologyd_private *priv, struct node *dest, struct node *src);
 #endif /* TOPOLOGYD_H */
-- 
GitLab