diff --git a/src/pathcomp/backend/pathComp_sp.c b/src/pathcomp/backend/pathComp_sp.c
index 48231b591e66ae0f8161ff14f79e7c9a6d832328..252c1d614a3f3874ee8879195eafa388fd34eca2 100644
--- a/src/pathcomp/backend/pathComp_sp.c
+++ b/src/pathcomp/backend/pathComp_sp.c
@@ -1,291 +1,294 @@
-/*
- * Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h> 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <glib.h>
-#include <sys/time.h>
-#include <ctype.h>
-#include <strings.h>
-#include <time.h>
-#include <math.h>
-#include <fcntl.h>
-
-#include "pathComp_log.h"
-#include "pathComp_tools.h"
-#include "pathComp_sp.h"
-
-// Global Variables
-GList* contextSet;
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_sp.c
- * 	@brief handling the Dijkstra algorithm
- *
- *  @param pred
- *  @param g
- *	@param s
- *  @param mapNodes
- *
- *	@author Ricardo Mart�nez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-gint computation(struct pred_t* pred, struct graph_t* g, struct service_t* s, struct map_nodes_t* mapNodes) {
-	g_assert(pred);
-	g_assert(g);
-	g_assert(s);
-
-	// Check the both ingress src and dst endpoints are in the graph
-	gint srcMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[0].device_uuid, mapNodes);
-	if (srcMapIndex == -1) {
-		DEBUG_PC("ingress DeviceId: %s NOT in the graph", s->service_endpoints_id[0].device_uuid);
-		return -1;
-	}
-
-	gint dstMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
-	if (dstMapIndex == -1) {
-		DEBUG_PC("egress DeviceId: %s NOT in the graph", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-
-	// Compute the shortest path
-	dijkstra(srcMapIndex, dstMapIndex, g, s, mapNodes, NULL, NULL, 0x00000000);
-
-	// Check that a feasible solution in term of latency and bandwidth is found
-	gint map_dstIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
-	struct map_t* dest_map = &mapNodes->map[map_dstIndex];
-	if (!(dest_map->distance < INFINITY_COST)) {
-		DEBUG_PC("destination: %s NOT reachable", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-
-	DEBUG_PC("AvailBw @ %s is %f", dest_map->verticeId.nodeId, dest_map->avaiBandwidth);
-	// Check that the computed available bandwidth is larger than 0.0
-	if (dest_map->avaiBandwidth <= (gfloat)0.0) {
-		DEBUG_PC("dst: %s NOT REACHABLE", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-	DEBUG_PC("dst: %s REACHABLE", s->service_endpoints_id[1].device_uuid);
-	// Handle predecessors
-	build_predecessors(pred, s, mapNodes);
-
-	return 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_sp.c
- * 	@brief CSPF algorithm execution
- *
- *  @param s
- *  @param path
- *  @param g
- *
- *	@author Ricardo Mart�nez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* path, struct graph_t* g) {
-	g_assert(s);
-	g_assert(path);
-	g_assert(g);
-
-	// create map of devices / nodes to handle the path computation using the context
-	struct map_nodes_t *mapNodes = create_map_node();
-	build_map_node(mapNodes, g);
-
-	// predecessors to store the computed path    
-	struct pred_t* predecessors = create_predecessors();
-
-	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
-	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
-
-	// SP computation
-	gint done = computation(predecessors, g, s, mapNodes);
-	if (done == -1) {
-		DEBUG_PC("NO PATH FOUND %s[%s] ---> %s[%s]", iEp->device_uuid, iEp->endpoint_uuid, eEp->device_uuid, eEp->endpoint_uuid);
-		comp_route_connection_issue_handler(path, s);
-		g_free(mapNodes); g_free(predecessors);
-		return;
-	}
-
-	// Construct the path from the computed predecessors
-	struct compRouteOutputItem_t* p = create_path_item();
-	//print_predecessors(predecessors);
-	build_path(p, predecessors, s);
-	//DEBUG_PC ("Path is constructed");
-
-	gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
-	struct map_t* dst_map = &mapNodes->map[indexDest]; 	
-	set_path_attributes(p, dst_map);
-	DEBUG_PC("Computed Path Avail Bw: %f, Path Cost: %f, latency: %f", p->availCap, p->cost, p->delay);
-	print_path(p);
-
-	gboolean feasibleRoute = check_computed_path_feasability(s, p);
-	if (feasibleRoute == TRUE) {
-		DEBUG_PC("SP Feasible");
-		print_path(p);
-		path->numPaths++;
-
-		// Copy the serviceId
-		DEBUG_PC("contextId: %s", s->serviceId.contextId);
-		copy_service_id(&path->serviceId, &s->serviceId);
-
-		// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
-		for (gint i = 0; i < s->num_service_endpoints_id; i++) {
-			struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
-			struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
-			copy_service_endpoint_id(oEp, iEp);
-		}
-		path->num_service_endpoints_id = s->num_service_endpoints_id;
-
-		// Copy the computed path
-		struct path_t* targetedPath = &(path->paths[path->numPaths - 1]);
-		duplicate_path_t(p, targetedPath);
-		print_path_t(targetedPath);
-		g_free(predecessors);
-		g_free(p);
-		g_free(mapNodes);
-		return;
-	}
-	DEBUG_PC("SP FAILED!!!");
-	comp_route_connection_issue_handler(path, s);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_sp.c
- * 	@brief Iterates over the list of network connectivity service requests
- * to compute their own paths fulfilling the constraints
- *
- *  @param outputList
- *
- *	@author Ricardo Mart�nez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-void sp_execution_services(struct compRouteOutputList_t* oPathList) {
-	g_assert(oPathList);	
-	// Check at least there is a service to be processed 
-	if (g_list_length(serviceList) == 0) {
-		DEBUG_PC("Lengtg requested serviceList is Empty...");
-		return;
-	}
-
-	DEBUG_PC("----- Starting the SP Computation ------");
-	gint i = 0;
-	for (GList* listnode = g_list_first(serviceList);
-		listnode;
-		listnode = g_list_next(listnode), i++) {
-		//struct service_t* service = &(serviceList->services[i]);
-		struct service_t* service = (struct service_t*)(listnode->data);
-
-		 DEBUG_PC("Starting the Computation for ServiceId: %s [ContextId: %s]", service->serviceId.service_uuid, service->serviceId.contextId);
-		 struct compRouteOutput_t* pathService = &(oPathList->compRouteConnection[i]);
-		 // check endpoints of the service are different (PE devices/nodes are different)
-		 if (same_src_dst_pe_nodeid(service) == 0) {
-			 DEBUG_PC("PEs are the same... no path computation");
-			 comp_route_connection_issue_handler(pathService, service);
-			 oPathList->numCompRouteConnList++;
-			 continue;
-		 }
-
-		 // get the graph associated to the contextId in the contextSet, if no then error
-		 struct graph_t* g = get_graph_by_contextId(contextSet, service->serviceId.contextId);
-		 if (g == NULL) {
-			 DEBUG_PC("The targeted contextId is NOT in the ContextSet ... then NO graph");
-			 comp_route_connection_issue_handler(pathService, service);
-			 oPathList->numCompRouteConnList++;
-			 continue;
-		 }
-
-		 computation_shortest_path(service, pathService, g);
-		 oPathList->numCompRouteConnList++;
-
-		 // for each network connectivity service, a single computed path (out of the KCSP) is retuned
-		 // If path is found, then the selected resources must be pre-assigned into the context information
-		 if (pathService->noPathIssue == NO_PATH_CONS_ISSUE) {
-			 continue;
-		 }
-		 struct path_t* path = &(pathService->paths[pathService->numPaths - 1]);
-		 //allocate_graph_resources(path, service, g);			// LGR: crashes in some cases with assymetric topos
-		 //allocate_graph_reverse_resources(path, service, g);	// LGR: crashes in some cases with assymetric topos
-		 print_graph(g);
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_sp.c
- * 	@brief handles the path computation for the constrained shortest path
- *
- *  @param compRouteOutput
- *
- *	@author Ricardo Mart�nez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) {
-	g_assert(routeConnList);
-	gint numSuccesPathComp = 0, numPathCompIntents = 0;
-
-	DEBUG_PC("================================================================");
-	DEBUG_PC("===========================   SP   =========================");
-	DEBUG_PC("================================================================");
-	// increase the number of Path Comp. Intents
-	numPathCompIntents++;
-	gint http_code = HTTP_CODE_OK;
-
-	// timestamp t0
-	struct timeval t0;
-	gettimeofday(&t0, NULL);
-
-	// Allocate memory for the context
-	contextSet = NULL;
-	// Build up the contextSet (>= 1)
-	build_contextSet(&contextSet);
-	print_contextSet(contextSet);
-#if 1	
-	//Triggering the path computation for each specific network connectivity service
-	sp_execution_services(routeConnList);
-
-	// -- timestamp t1
-	struct timeval t1, delta;
-	gettimeofday(&t1, NULL);
-	delta.tv_sec = t1.tv_sec - t0.tv_sec;
-	delta.tv_usec = t1.tv_usec - t0.tv_usec;
-	delta = tv_adjust(delta);
-
-	numSuccesPathComp++;
-	update_stats_path_comp(routeConnList, delta, numSuccesPathComp, numPathCompIntents);
-	print_path_connection_list(routeConnList);
-#endif
-
-	g_list_free_full(g_steal_pointer(&contextSet), (GDestroyNotify)destroy_context);
-	return http_code;
-}
-
-
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	# Copyright 2022 Centre Tecnològic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Author: CTTC/CERCA PONS RU Ricardo Martínez (ricardo.martinez@cttc.es)
+ */
+ ////////////////////////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <stdlib.h> 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <glib.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <strings.h>
+#include <time.h>
+#include <math.h>
+#include <fcntl.h>
+
+#include "pathComp_log.h"
+#include "pathComp_tools.h"
+#include "pathComp_sp.h"
+
+// Global Variables
+GList* contextSet;
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_sp.c
+ * 	@brief handling the Dijkstra algorithm
+ *
+ *  @param pred
+ *  @param g
+ *	@param s
+ *  @param mapNodes
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+gint computation(struct pred_t* pred, struct graph_t* g, struct service_t* s, struct map_nodes_t* mapNodes) {
+	g_assert(pred);
+	g_assert(g);
+	g_assert(s);
+
+	// Check the both ingress src and dst endpoints are in the graph
+	gint srcMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[0].device_uuid, mapNodes);
+	if (srcMapIndex == -1) {
+		DEBUG_PC("ingress DeviceId: %s NOT in the graph", s->service_endpoints_id[0].device_uuid);
+		return -1;
+	}
+
+	gint dstMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
+	if (dstMapIndex == -1) {
+		DEBUG_PC("egress DeviceId: %s NOT in the graph", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+
+	// Compute the shortest path
+	dijkstra(srcMapIndex, dstMapIndex, g, s, mapNodes, NULL, NULL, 0x00000000);
+
+	// Check that a feasible solution in term of latency and bandwidth is found
+	gint map_dstIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
+	struct map_t* dest_map = &mapNodes->map[map_dstIndex];
+	if (!(dest_map->distance < INFINITY_COST)) {
+		DEBUG_PC("destination: %s NOT reachable", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+
+	DEBUG_PC("AvailBw @ %s is %f", dest_map->verticeId.nodeId, dest_map->avaiBandwidth);
+	// Check that the computed available bandwidth is larger than 0.0
+	if (dest_map->avaiBandwidth <= (gfloat)0.0) {
+		DEBUG_PC("dst: %s NOT REACHABLE", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+	DEBUG_PC("dst: %s REACHABLE", s->service_endpoints_id[1].device_uuid);
+	// Handle predecessors
+	build_predecessors(pred, s, mapNodes);
+
+	return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_sp.c
+ * 	@brief CSPF algorithm execution
+ *
+ *  @param s
+ *  @param path
+ *  @param g
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* path, struct graph_t* g) {
+	g_assert(s);
+	g_assert(path);
+	g_assert(g);
+
+	// create map of devices / nodes to handle the path computation using the context
+	struct map_nodes_t *mapNodes = create_map_node();
+	build_map_node(mapNodes, g);
+
+	// predecessors to store the computed path    
+	struct pred_t* predecessors = create_predecessors();
+
+	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
+	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
+
+	// SP computation
+	gint done = computation(predecessors, g, s, mapNodes);
+	if (done == -1) {
+		DEBUG_PC("NO PATH FOUND %s[%s] ---> %s[%s]", iEp->device_uuid, iEp->endpoint_uuid, eEp->device_uuid, eEp->endpoint_uuid);
+		comp_route_connection_issue_handler(path, s);
+		g_free(mapNodes); g_free(predecessors);
+		return;
+	}
+
+	// Construct the path from the computed predecessors
+	struct compRouteOutputItem_t* p = create_path_item();
+	//print_predecessors(predecessors);
+	build_path(p, predecessors, s);
+	//DEBUG_PC ("Path is constructed");
+
+	gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
+	struct map_t* dst_map = &mapNodes->map[indexDest]; 	
+	set_path_attributes(p, dst_map);
+	DEBUG_PC("Computed Path Avail Bw: %f, Path Cost: %f, latency: %f", p->availCap, p->cost, p->delay);
+	print_path(p);
+
+	gboolean feasibleRoute = check_computed_path_feasability(s, p);
+	if (feasibleRoute == TRUE) {
+		DEBUG_PC("SP Feasible");
+		print_path(p);
+		path->numPaths++;
+
+		// Copy the serviceId
+		DEBUG_PC("contextId: %s", s->serviceId.contextId);
+		copy_service_id(&path->serviceId, &s->serviceId);
+
+		// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
+		for (gint i = 0; i < s->num_service_endpoints_id; i++) {
+			struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
+			struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
+			copy_service_endpoint_id(oEp, iEp);
+		}
+		path->num_service_endpoints_id = s->num_service_endpoints_id;
+
+		// Copy the computed path
+		struct path_t* targetedPath = &(path->paths[path->numPaths - 1]);
+		duplicate_path_t(p, targetedPath);
+		print_path_t(targetedPath);
+		g_free(predecessors);
+		g_free(p);
+		g_free(mapNodes);
+		return;
+	}
+	DEBUG_PC("SP FAILED!!!");
+	comp_route_connection_issue_handler(path, s);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_sp.c
+ * 	@brief Iterates over the list of network connectivity service requests
+ * to compute their own paths fulfilling the constraints
+ *
+ *  @param outputList
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+void sp_execution_services(struct compRouteOutputList_t* oPathList) {
+	g_assert(oPathList);	
+	// Check at least there is a service to be processed 
+	if (g_list_length(serviceList) == 0) {
+		DEBUG_PC("Lengtg requested serviceList is Empty...");
+		return;
+	}
+
+	DEBUG_PC("----- Starting the SP Computation ------");
+	gint i = 0;
+	for (GList* listnode = g_list_first(serviceList);
+		listnode;
+		listnode = g_list_next(listnode), i++) {
+		//struct service_t* service = &(serviceList->services[i]);
+		struct service_t* service = (struct service_t*)(listnode->data);
+
+		 DEBUG_PC("Starting the Computation for ServiceId: %s [ContextId: %s]", service->serviceId.service_uuid, service->serviceId.contextId);
+		 struct compRouteOutput_t* pathService = &(oPathList->compRouteConnection[i]);
+		 // check endpoints of the service are different (PE devices/nodes are different)
+		 if (same_src_dst_pe_nodeid(service) == 0) {
+			 DEBUG_PC("PEs are the same... no path computation");
+			 comp_route_connection_issue_handler(pathService, service);
+			 oPathList->numCompRouteConnList++;
+			 continue;
+		 }
+
+		 // get the graph associated to the contextId in the contextSet, if no then error
+		 struct graph_t* g = get_graph_by_contextId(contextSet, service->serviceId.contextId);
+		 if (g == NULL) {
+			 DEBUG_PC("The targeted contextId is NOT in the ContextSet ... then NO graph");
+			 comp_route_connection_issue_handler(pathService, service);
+			 oPathList->numCompRouteConnList++;
+			 continue;
+		 }
+
+		 computation_shortest_path(service, pathService, g);
+		 oPathList->numCompRouteConnList++;
+
+		 // for each network connectivity service, a single computed path (out of the KCSP) is retuned
+		 // If path is found, then the selected resources must be pre-assigned into the context information
+		 if (pathService->noPathIssue == NO_PATH_CONS_ISSUE) {
+			 continue;
+		 }
+		 struct path_t* path = &(pathService->paths[pathService->numPaths - 1]);
+		 allocate_graph_resources(path, service, g);
+		 allocate_graph_reverse_resources(path, service, g);
+		 print_graph(g);
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_sp.c
+ * 	@brief handles the path computation for the constrained shortest path
+ *
+ *  @param compRouteOutput
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) {
+	g_assert(routeConnList);
+	gint numSuccesPathComp = 0, numPathCompIntents = 0;
+
+	DEBUG_PC("================================================================");
+	DEBUG_PC("===========================   SP   =========================");
+	DEBUG_PC("================================================================");
+	// increase the number of Path Comp. Intents
+	numPathCompIntents++;
+	gint http_code = HTTP_CODE_OK;
+
+	// timestamp t0
+	struct timeval t0;
+	gettimeofday(&t0, NULL);
+
+	// Allocate memory for the context
+	contextSet = NULL;
+	// Build up the contextSet (>= 1)
+	build_contextSet(&contextSet);
+	print_contextSet(contextSet);
+#if 1	
+	//Triggering the path computation for each specific network connectivity service
+	sp_execution_services(routeConnList);
+
+	// -- timestamp t1
+	struct timeval t1, delta;
+	gettimeofday(&t1, NULL);
+	delta.tv_sec = t1.tv_sec - t0.tv_sec;
+	delta.tv_usec = t1.tv_usec - t0.tv_usec;
+	delta = tv_adjust(delta);
+
+	numSuccesPathComp++;
+	update_stats_path_comp(routeConnList, delta, numSuccesPathComp, numPathCompIntents);
+	print_path_connection_list(routeConnList);
+#endif
+
+	g_list_free_full(g_steal_pointer(&contextSet), (GDestroyNotify)destroy_context);
+	return http_code;
+}
+
+
diff --git a/src/pathcomp/backend/pathComp_tools.c b/src/pathcomp/backend/pathComp_tools.c
index e7b91ee9e5a8a0a1c28344d17247e307238ed4c7..ab4a394f1928b1324bc376551ed459d44bff5126 100644
--- a/src/pathcomp/backend/pathComp_tools.c
+++ b/src/pathcomp/backend/pathComp_tools.c
@@ -1,3397 +1,3401 @@
-/*
- * Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h> 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <glib.h>
-#include <sys/time.h>
-#include <ctype.h>
-#include <strings.h>
-#include <time.h>
-#include <math.h>
-#include <fcntl.h>
-#include <uuid/uuid.h>
-#include <errno.h>
-
-#include "pathComp_log.h"
-#include "pathComp.h"
-#include "pathComp_tools.h"
-
-gint numPathCompIntents = 0;  // number of events triggering the path computation
-//gint numSuccesPathComp = 0; // number of events resulting in succesfully path computations fulfilling the constraints
-struct timeval total_path_comp_time;
-gdouble totalReqBw = 0.0;
-gdouble totalServedBw = 0.0;
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function for time processing
- *
- * 	@param a
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- ////////////////////////////////////////////////////////////////////////////////////////
-struct timeval tv_adjust (struct timeval a) {
-	while (a.tv_usec >= 1000000) {
-		a.tv_usec -= 1000000;
-		a.tv_sec++;
-	}
-	while (a.tv_usec < 0) {
-		a.tv_usec += 1000000;
-		a.tv_sec--;
-	}
-	return a;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief friendly function to copy safely strings
- *
- * 	@param dst
- *  @param src
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- ////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_string(gchar* dst, gchar* src) {
-	g_assert(dst); g_assert(src);
-	strcpy(dst, src);
-	dst[strlen(dst)] = '\0';
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to print the computed the path
- *
- *	@param path
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void print_path (struct compRouteOutputItem_t *p) {
-	g_assert(p);	
-	DEBUG_PC ("=========== COMPUTED PATH =======================");
-	DEBUG_PC ("E2E Avail. Bw: %f, Latency: %f, Cost: %f, Consumed Power (in W): %f", p->availCap, p->delay, p->cost, p->power);
-	for (gint k = 0; k < p->numRouteElements; k++) {
-		DEBUG_PC ("%s[%s] --> %s[%s]", p->routeElement[k].aNodeId.nodeId, p->routeElement[k].aEndPointId,
-																p->routeElement[k].zNodeId.nodeId, p->routeElement[k].zEndPointId);
-		DEBUG_PC("\t linkId: %s", p->routeElement[k].linkId);
-		DEBUG_PC("\t aTopologyId: %s", p->routeElement[k].aTopologyId);
-		DEBUG_PC("\t zTopologyId: %s", p->routeElement[k].zTopologyId);
-	}
-	DEBUG_PC ("==================================================================");		
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to print the output path formed by link Ids
- *
- *	@param p
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_path_t(struct path_t* p) {
-	g_assert(p);
-	DEBUG_PC(" ============ COMPUTED OUTPUT PATH =================");
-	DEBUG_PC("Path AvailBw: %f, Cost: %f, Latency: %f, Power: %f", p->path_capacity.value,
-			p->path_cost.cost_value, p->path_latency.fixed_latency, p->path_power.power);
-	DEBUG_PC("number of links of path %d", p->numPathLinks);
-	for (gint k = 0; k < p->numPathLinks; k++) {
-		DEBUG_PC("Link: %s", p->pathLinks[k].linkId);
-		for (gint l = 0; l < p->pathLinks[k].numLinkTopologies; l++) {
-			DEBUG_PC("end Link [%d] TopologyId: %s", l, p->pathLinks[k].linkTopologies[l].topologyId);
-		}
-		DEBUG_PC(" ContextId: %s", p->pathLinks[k].topologyId.contextId);
-		DEBUG_PC(" TopologyUUid: %s", p->pathLinks[k].topologyId.topology_uuid);
-		DEBUG_PC(" aDeviceId: %s", p->pathLinks[k].aDeviceId);
-		DEBUG_PC(" aEndpointId: %s", p->pathLinks[k].aEndPointId);
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used allocate memory for struct path_t
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- ////////////////////////////////////////////////////////////////////////////////////////
-struct path_t* create_path() {
-	struct path_t* p = g_malloc0(sizeof(struct path_t));
-	if (p == NULL) {
-		DEBUG_PC("Memory allocation failure");
-		exit(-1);
-	}
-	return(p);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Returns the char (36 bytes) format of a uuid
- *
- *	@param uuid
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-gchar* get_uuid_char(uuid_t uuid) {
-	gchar* uuidChar = g_malloc0(16); // uuid has 36 chars
-	if (uuidChar == NULL) {
-		DEBUG_PC("Memory Allocation failure");
-		exit(-1);
-	}
-	uuid_unparse(uuid, (char *)uuidChar);
-	return uuidChar;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Makes a copy of the service identifier (including the context)
- *
- *	@param o
- *  @param i
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void copy_service_id(struct serviceId_t* o, struct serviceId_t* i) {
-	g_assert(o); g_assert(i);
-	memcpy(o->contextId, i->contextId, sizeof(i->contextId));
-	memcpy(o->service_uuid, i->service_uuid, sizeof(i->service_uuid));
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Makes a copy of the service endpoint identifier (including the topology (contect and topology id), device and endpoint (port))
- *
- *	@param oEp
- *  @param iEp
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void copy_service_endpoint_id(struct service_endpoints_id_t* oEp, struct service_endpoints_id_t* iEp) {
-	g_assert(oEp); g_assert(iEp);
-
-	// copy topology information
-	memcpy(oEp->topology_id.contextId, iEp->topology_id.contextId, sizeof(iEp->topology_id.contextId));
-	memcpy(oEp->topology_id.topology_uuid, iEp->topology_id.topology_uuid, sizeof(iEp->topology_id.topology_uuid));
-
-	// copy the endpoint
-	memcpy(oEp->device_uuid, iEp->device_uuid, sizeof(iEp->device_uuid));
-	memcpy(oEp->endpoint_uuid, iEp->endpoint_uuid, sizeof(iEp->endpoint_uuid));
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief From the set of contexts, it is returned the graph associated to that context matching
- *	with the passed contextId.
- *
- *	@param Set
- *  @param contextId
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct graph_t* get_graph_by_contextId(GList* set, gchar* contextId) {
-	g_assert(contextId);
-
-	// iterate over the set of context. Pick the one matching with contextId, and return the graph.
-	// If not found, return NULL
-	struct graph_t* g = NULL;
-	for (GList *ln = g_list_first(set);
-		ln;
-		ln = g_list_next(ln)){
-		struct context_t* context = (struct context_t*)(ln->data);
-		if (strcmp(context->contextId, contextId) == 0) {
-			g = &(context->g);
-			return g;
-		}
-	}
-	return NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Process the service constraint and maps them into the path constraints
- * to be fulfilled
- *
- *  @param path_constraints
- *  @param s
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct path_constraints_t * get_path_constraints(struct service_t* s) {
-	g_assert(s);
-	
-	struct path_constraints_t* path_constraints = g_malloc0(sizeof(struct path_constraints_t));
-	if (path_constraints == NULL) {
-		DEBUG_PC("Memory Allocation Failure");
-		exit(-1);
-	}
-
-	char* eptr;
-	for (gint i = 0; i < s->num_service_constraints; i++) {
-		struct constraint_t* constraint = &(s->constraints[i]);;
-		if (strncmp((const char*)constraint->constraint_type, "bandwidth", 9) == 0) {
-			path_constraints->bwConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
-			path_constraints->bw = TRUE;
-			//DEBUG_PC("Path Constraint Bw: %f", path_constraints->bwConstraint);
-		}
-		if (strncmp((const char*)constraint->constraint_type, "cost", 4) == 0) {
-			path_constraints->costConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
-			path_constraints->cost = TRUE;
-			//DEBUG_PC("Path Constraint Cost: %f", path_constraints->costConstraint);
-		}
-		if (strncmp((const char*)constraint->constraint_type, "latency", 7) == 0) {
-			path_constraints->latencyConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
-			path_constraints->latency = TRUE;
-			//DEBUG_PC("Path Constraint Latency: %f", path_constraints->latencyConstraint);
-		}
-		if (strncmp((const char*)constraint->constraint_type, "energy", 6) == 0) {
-			path_constraints->energyConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
-			path_constraints->energy = TRUE;
-			//DEBUG_PC("Path Constraint Energy: %f", path_constraints->energyConstraint);
-		}
-	}
-	return path_constraints;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Creates the predecessors to keep the computed path
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct pred_t * create_predecessors () {
-	struct pred_t *predecessors = g_malloc0 (sizeof (struct pred_t));
-	if (predecessors == NULL) {
-		DEBUG_PC ("memory allocation failed\n");
-		exit (-1);
-	}   
-	return predecessors;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief create edge
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct edges_t* create_edge() {
-	struct edges_t* e = g_malloc0(sizeof(struct edges_t));
-	if (e == NULL) {
-		DEBUG_PC("Memory allocation failed\n");
-		exit(-1);
-	}
-	return e;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Prints the list of the predecessors for a given computed Shortest Path
- *
- *	@param p 
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void print_predecessors (struct pred_t *p)
-{
-	g_assert (p);
-	DEBUG_PC ("Number of Predecessors: %d", p->numPredComp);
-	for (gint i = 0; i < p->numPredComp; i++) {
-		struct pred_comp_t *pComp = &(p->predComp[i]);
-		DEBUG_PC ("deviceId: %s", pComp->v.nodeId);		
-		struct edges_t *e = &(pComp->e);
-		DEBUG_PC("Edge[#%d] (linkId): %s", i, e->linkId);
-		DEBUG_PC ("\t %s[%s] ===>", e->aNodeId.nodeId, e->aEndPointId);
-		DEBUG_PC("\t %s[%s]", e->zNodeId.nodeId, e->zEndPointId);
-		DEBUG_PC("\t aTopologyId: %s", e->aTopologyId);
-		DEBUG_PC("\t zTopologyId: %s", e->zTopologyId);
-	}	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Builds the list of predecessors for the request destination using the computed Shortest Path
- *	being stored in map
- *
- *	@param p 
- *	@param s
- *	@param map
- *	
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void build_predecessors (struct pred_t *p, struct service_t *s, struct map_nodes_t *map) {
-	g_assert (p); g_assert (s); g_assert (map);
-	
-	struct nodes_t *v = create_node();
-	duplicate_string(v->nodeId, s->service_endpoints_id[1].device_uuid);
-	
-	struct edges_t *e = create_edge();	
-	get_edge_from_map_by_node (e, v, map);
-			
-	// Get u (being source of edge e)
-	struct nodes_t u;	
-	duplicate_node_id (&e->aNodeId, &u);
-		
-	// Add to the predecessors list
-	struct pred_comp_t *pred = &(p->predComp[p->numPredComp]);
-	duplicate_node_id (&u, &pred->v);	
-	struct edges_t *e1 = &(pred->e);	
-	duplicate_edge (e1, e);
-	p->numPredComp++;	
-	// Back-trace edges till reaching the srcPEId
-	struct nodes_t* srcNode = create_node();
-	duplicate_string(srcNode->nodeId, s->service_endpoints_id[0].device_uuid);
-
-	while (compare_node_id (&u, srcNode) != 0) 	{		
-		duplicate_node_id (&u, v);
-		get_edge_from_map_by_node (e, v, map);		
-		// Get the u (being source of edge e)		
-		duplicate_node_id (&e->aNodeId, &u);		
-		// Get the new predecessor
-		struct pred_comp_t *pred = &p->predComp[p->numPredComp];			
-		// Add to the predecessors list					
-		duplicate_node_id (&u, &pred->v);		
-		struct edges_t *e1 = &(pred->e);
-		duplicate_edge (e1, e);
-		p->numPredComp++;		
-	}
-	print_predecessors (p);
-    g_free (e); g_free(v); g_free(srcNode);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief It creates a struct nodes_t
- *
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct nodes_t * create_node ()
-{
-	struct nodes_t *n = g_malloc0 (sizeof (struct nodes_t));
-	if (n == NULL) {
-		DEBUG_PC ("memory allocation problem");
-		exit (-1);
-	}
-	return n;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief It creates a routeElement_t
- *
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct routeElement_t * create_routeElement () {
-	struct routeElement_t *rE = g_malloc0 (sizeof (struct routeElement_t));
-	if (rE == NULL)	{
-		DEBUG_PC ("memory allocation problem");
-		exit (-1);		
-	}
-	return rE;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief copy node ids
- *
- *	@param src
- *  @param dst
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_node_id (struct nodes_t *src, struct nodes_t *dst) {	
-	g_assert (src);
-	g_assert (dst);	
-	//DEBUG_PC ("Duplicate nodeId for %s", src->nodeId);	
-	strcpy (dst->nodeId, src->nodeId);	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief compares a pair of node Ids
- *
- *	@param a
- *  @param b
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint compare_node_id (struct nodes_t *a, struct nodes_t *b) {
-	g_assert (a);
-	g_assert (b);	
-	return (memcmp (&a->nodeId, b->nodeId, strlen (b->nodeId)));	
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief duplicate two routeElement_t
- *
- *	@param src
- *  @param dst
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_routeElement (struct routeElement_t *src, struct routeElement_t *dst)
-{
-	g_assert (src);
-	g_assert (dst);
-	
-	duplicate_node_id (&(src->aNodeId), &(dst->aNodeId));
-	duplicate_node_id (&(src->zNodeId), &(dst->zNodeId));
-	duplicate_string(dst->aEndPointId, src->aEndPointId);
-	duplicate_string(dst->zEndPointId, src->zEndPointId);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief duplicate two edges
- *
- *	@param e1 (destination)
- *  @param e2 (source)
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_edge (struct edges_t *e1, struct edges_t *e2) {
-	g_assert (e1); g_assert (e2);
-		
-	duplicate_node_id (&e2->aNodeId, &e1->aNodeId);
-	duplicate_node_id (&e2->zNodeId, &e1->zNodeId);
-	//DEBUG_PC ("e->aNodeId: %s --->  e->zNodeId: %s", e1->aNodeId.nodeId, e1->zNodeId.nodeId);
-	duplicate_string(e1->aEndPointId, e2->aEndPointId);
-	duplicate_string(e1->zEndPointId, e2->zEndPointId);
-	duplicate_string(e1->linkId, e2->linkId);
-	duplicate_string(e1->interDomain_localId, e2->interDomain_localId);
-	duplicate_string(e1->interDomain_remoteId, e2->interDomain_remoteId);
-	duplicate_string(e1->aTopologyId, e2->aTopologyId);
-	duplicate_string(e1->zTopologyId, e2->zTopologyId);
-	
-	e1->unit = e2->unit;
-	memcpy(&e1->totalCap, &e2->totalCap, sizeof(gdouble));
-	memcpy(&e1->availCap, &e2->availCap, sizeof(gdouble));
-
-	memcpy (&e1->cost, &e2->cost, sizeof (gdouble));
-    memcpy (&e1->delay, &e2->delay, sizeof (gdouble));
-	memcpy(&e1->energy, &e2->energy, sizeof(gdouble));
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Duplicate path 
- *
- *	@param a - original
- *  @param b - copy
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_path (struct compRouteOutputItem_t *a, struct compRouteOutputItem_t *b) {		
-	g_assert (a); 	g_assert (b);
-	memcpy(&b->availCap, &a->availCap, sizeof (gdouble));		
-	memcpy(&b->cost, &a->cost, sizeof(gdouble));	
-	memcpy(&b->delay, &a->delay, sizeof (gdouble));
-	memcpy(&b->power, &a->power, sizeof(gdouble));
-	b->numRouteElements = a->numRouteElements;
-	for (gint k = 0; k < a->numRouteElements; k++) {			
-		//DEBUG_PC ("aNodeId: %s // zNodeId: %s", a->routeElement[k].aNodeId.nodeId, a->routeElement[k].zNodeId.nodeId);
-		// aNodeId duplication
-		struct nodes_t *n1 = &(a->routeElement[k].aNodeId);
-		struct nodes_t *n2 = &(b->routeElement[k].aNodeId);			
-		duplicate_node_id (n1, n2);					
-		//zNodeId duplication
-		n1 = &(a->routeElement[k].zNodeId);
-		n2 = &(b->routeElement[k].zNodeId);			
-		duplicate_node_id (n1, n2);
-		duplicate_string(b->routeElement[k].aEndPointId, a->routeElement[k].aEndPointId);
-		duplicate_string(b->routeElement[k].zEndPointId, a->routeElement[k].zEndPointId);
-		duplicate_string(b->routeElement[k].linkId, a->routeElement[k].linkId);
-		duplicate_string(b->routeElement[k].aTopologyId, a->routeElement[k].aTopologyId);
-		duplicate_string(b->routeElement[k].zTopologyId, a->routeElement[k].zTopologyId);
-	}	
-	return;	
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Duplicate path from compRouteOutputItem_t to path_t
- *
- *	@param a - original
- *  @param b - copy
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_path_t(struct compRouteOutputItem_t* a, struct path_t* b) {
-	g_assert(a); g_assert(b);
-
-	// transfer path characteristics ...
-	memcpy(&b->path_capacity.value, &a->availCap, sizeof(gdouble));
-	memcpy(&b->path_cost.cost_value, &a->cost, sizeof(gdouble));
-	memcpy(&b->path_latency.fixed_latency, &a->delay, sizeof(gdouble));
-	memcpy(&b->path_power.power, &a->power, sizeof(gdouble));
-
-	b->numPathLinks = a->numRouteElements;
-
-	for (gint k = 0; k < a->numRouteElements; k++) {
-		struct routeElement_t* rE = &(a->routeElement[k]);
-		struct pathLink_t* pL = &(b->pathLinks[k]);
-
-		// copy the aDeviceId and aEndpointId, zDeviceId and zEndPointId
-		duplicate_string(pL->aDeviceId, rE->aNodeId.nodeId);
-		duplicate_string(pL->zDeviceId, rE->zNodeId.nodeId);
-		duplicate_string(pL->aEndPointId, rE->aEndPointId);
-		duplicate_string(pL->zEndPointId, rE->zEndPointId);
-
-		duplicate_string(pL->topologyId.topology_uuid, rE->aTopologyId);
-		duplicate_string(pL->topologyId.contextId, rE->contextId);
-
-		//copy the linkId
-		duplicate_string(pL->linkId, rE->linkId);
-		pL->numLinkTopologies++;
-		duplicate_string(pL->linkTopologies[pL->numLinkTopologies - 1].topologyId, rE->aTopologyId);
-		pL->numLinkTopologies++;
-		duplicate_string(pL->linkTopologies[pL->numLinkTopologies - 1].topologyId, rE->zTopologyId);
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Return the index into mapN related nodeId
- * 
- *  @param nodeId
- *  @para mapN
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint get_map_index_by_nodeId (gchar *nodeId, struct map_nodes_t * mapN) {
-    gint i = 0;    
-    for (i = 0; i < mapN->numMapNodes; i++) {
-		//DEBUG_PC ("i: %d; current: %s // targeted: %s", i, mapN->map[i].verticeId.nodeId, nodeId);
-        if (memcmp (mapN->map[i].verticeId.nodeId, nodeId, strlen (nodeId)) == 0) {
-			//DEBUG_PC ("Index: %d", i);
-			return i;            
-        }
-    }
-	//DEBUG_PC ("Index: %d", index);
-    return -1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Get the edge e enabling reaching the computed v in mapNodes
- * 
- *  @param e
- *  @param v
- *  @param mapN
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void get_edge_from_map_by_node (struct edges_t *e, struct nodes_t* v, struct map_nodes_t *mapN) {	
-	//DEBUG_PC ("Get the Edge into map from node v: %s", v.nodeId);	
-	// Get the edge reaching the node v from mapNodes
-	gint map_vIndex = get_map_index_by_nodeId (v->nodeId, mapN);	
-	//DEBUG_PC ("aNodeId: %s --> zNodeId: %s", mapN->map[map_vIndex].predecessor.aNodeId.nodeId, mapN->map[map_vIndex].predecessor.zNodeId.nodeId);	
-	struct edges_t *te = &(mapN->map[map_vIndex].predecessor);	
-	duplicate_edge (e, te);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Get the edge from the predecessors array for a given node n
- * 
- *  @param e
- *  @param n
- *  @param predecessors
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void get_edge_from_predecessors (struct edges_t *e, struct nodes_t* n, struct pred_t *predecessors) {
-	g_assert(predecessors);
-	DEBUG_PC ("Get edge outgoing node %s from predecessors list", n->nodeId);
-	//print_predecessors (predecessors);
-	for (gint i = 0; i < predecessors->numPredComp; i++) {
-		struct pred_comp_t *pred = &(predecessors->predComp[i]);
-		if (compare_node_id (n, &pred->v) == 0) {
-			// Add to the predecessors list
-			struct edges_t *te = &(pred->e);
-			DEBUG_PC("add e (linkId): %s", te->linkId);
-			duplicate_edge (e, te);
-			return;
-		}	
-	}	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Construct the path using the predecessors list
- * 
- *  @param path
- *  @param predecessors
- *	@param s
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, struct service_t *s) {
-	// Get the source device Id	of the network connectivity service
-	struct nodes_t *v = create_node();
-	// Src Node of the Service set to v
-	duplicate_string(v->nodeId, s->service_endpoints_id[0].device_uuid);
-								  	
-	// Get the edge for v in predecessors
-	struct edges_t* e = create_edge();
-	get_edge_from_predecessors (e, v, predecessors);	
-	// Get the target for e
-	struct nodes_t u;	
-	duplicate_node_id (&e->zNodeId, &u);
-	//DEBUG_PC ("u: %s", u.nodeId);
-	struct path_constraints_t* pathCons = get_path_constraints(s);		
-
-	// Add route element to the path being constructed
-	gint k = 0;
-	duplicate_node_id (&e->aNodeId, &p->routeElement[k].aNodeId);
-	duplicate_node_id (&e->zNodeId, &p->routeElement[k].zNodeId);
-	duplicate_string(p->routeElement[k].aEndPointId, e->aEndPointId);
-	duplicate_string(p->routeElement[k].zEndPointId, e->zEndPointId);
-	duplicate_string(p->routeElement[k].linkId, e->linkId);
-	duplicate_string(p->routeElement[k].aTopologyId, e->aTopologyId);
-	duplicate_string(p->routeElement[k].zTopologyId, e->zTopologyId);
-	duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId);
-	p->numRouteElements++;
-
-	// Get Dst Node of connectivity service
-	struct nodes_t* dst = create_node();
-	duplicate_string(dst->nodeId, s->service_endpoints_id[1].device_uuid);
-	while (compare_node_id (&u, dst) != 0) {
-		k++; 
-		p->numRouteElements++;			
-		duplicate_node_id (&u, v);
-		get_edge_from_predecessors (e, v, predecessors);
-		// Get the target u		
-		duplicate_node_id (&e->zNodeId, &u);
-		// Add route element to the path being constructed		
-		duplicate_node_id (&e->aNodeId, &p->routeElement[k].aNodeId);
-		duplicate_node_id (&e->zNodeId, &p->routeElement[k].zNodeId);
-		duplicate_string(p->routeElement[k].aEndPointId, e->aEndPointId);
-		duplicate_string(p->routeElement[k].zEndPointId, e->zEndPointId);
-		duplicate_string(p->routeElement[k].linkId, e->linkId);
-		duplicate_string(p->routeElement[k].aTopologyId, e->aTopologyId);
-		duplicate_string(p->routeElement[k].zTopologyId, e->zTopologyId);
-		duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId);		
-	}		
-	g_free(e); g_free(v); g_free(pathCons);
-	//DEBUG_PC ("Path is constructed");	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Print the graph for DEBUG_PCging purposes
- * 
- *  @param g
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void print_graph (struct graph_t *g) {
-	g_assert(g);
-    DEBUG_PC ("================================================================");
-    DEBUG_PC ("===========================   GRAPH   ==========================");
-    DEBUG_PC ("================================================================");
-	DEBUG_PC("Graph Num Vertices: %d", g->numVertices);    
-    
-    for (gint i = 0; i < g->numVertices; i++) {
-        DEBUG_PC ("Head Vertice [%s]", g->vertices[i].verticeId.nodeId);
-        for (gint j = 0; j < g->vertices[i].numTargetedVertices; j++)
-        {
-            DEBUG_PC ("  Tail Vertice: %s", g->vertices[i].targetedVertices[j].tVertice.nodeId);
-            for (gint k = 0; k < g->vertices[i].targetedVertices[j].numEdges; k++)
-            {
-                struct edges_t *e = &(g->vertices[i].targetedVertices[j].edges[k]);
-				DEBUG_PC ("%s(%s) --> %s(%s) [C: %f, Bw: %f b/s, Delay: %f ms]", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, 
-								e->zEndPointId, e->cost, e->availCap, e->delay);				
-           }
-        }       
-    }     
-    return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Look for a given edge into the graph
- *
- *  @param verticeIndex
- *	@param targetedVerticeIndex
- *  @param e
- *  @param g
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint graph_edge_lookup (gint verticeIndex, gint targetedVerticeIndex, struct edges_t *e, struct graph_t *g)	{
-	gint indexEdge = -1;
-	
-	for (gint j = 0; j < g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex].numEdges; j++) {
-		struct edges_t *e2 = &(g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex].edges[j]);
-		if ((compare_node_id (&e->aNodeId, &e2->aNodeId) == 0) &&
-			(compare_node_id (&e->zNodeId, &e2->zNodeId) == 0) &&
-			(strcmp (e->aEndPointId, e2->aEndPointId) == 0) &&
-			(strcmp (e->zEndPointId, e2->zEndPointId) == 0) &&
-			(strcmp(e->linkId, e2->linkId) == 0)) {
-			DEBUG_PC ("%s (%s) --> %s (%s) [linkId: %s] FOUND in the Graph at index: %d", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, 
-							e->zEndPointId, e->linkId, j);
-			indexEdge = j;
-			return indexEdge;
-		}		
-	}	
-	return indexEdge;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Look for a given vertice within the graph using the nodeId
- *
- *  @param nodeId
- *	@param g
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint graph_vertice_lookup (gchar *nodeId, struct graph_t *g)
-{
-    gint index = -1; 
-	//DEBUG_PC("Searching Node: %s", nodeId);
-    for (gint i = 0; i < g->numVertices; i++) {
-		//DEBUG_PC("Checked Graph Node: %s", g->vertices[i].verticeId.nodeId);
-		if (memcmp (g->vertices[i].verticeId.nodeId, nodeId, strlen (nodeId)) == 0)
-        {
-            index = i;
-            //DEBUG_PC ("%s is found in the graph vertice [%d]", nodeId, index);
-            break;
-        }     
-    }  
-    return (index);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Check if a nodeId is already considered into the set of targeted vertices from a given vertice
- *
- *  @param nodeId
- *  @param vIndex
- *  @param g
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint graph_targeted_vertice_lookup (gint vIndex, gchar *nodeId, struct graph_t *g)
-{
-    gint addedTargetedVerticeIndex = -1;
-    gint i = 0;
-    
-    if (g->vertices[vIndex].numTargetedVertices == 0)
-    {
-        return (addedTargetedVerticeIndex);
-    }
-    
-    for (i = 0; i < g->vertices[vIndex].numTargetedVertices; i++)
-    {
-        if (memcmp (g->vertices[vIndex].targetedVertices[i].tVertice.nodeId, nodeId, strlen (nodeId)) == 0)
-        {
-            DEBUG_PC ("Targeted %s reachable from %s", nodeId, g->vertices[vIndex].verticeId.nodeId);
-            addedTargetedVerticeIndex = i;
-            return (addedTargetedVerticeIndex);
-        }        
-    }    
-    // not found ...    
-    return (addedTargetedVerticeIndex);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Check if a nodeId is already considered into the set of targeted vertices from a given vertice, if not to be added
- *
- *  @param nodeId
- *  @param vIndex
- *  @param g
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint graph_targeted_vertice_add (gint vIndex, gchar *nodeId, struct graph_t *g)
-{
-    gint addedTargetedVerticeIndex = -1;
-    gint i = 0;
-    
-    if (g->vertices[vIndex].numTargetedVertices == 0)
-    {
-        //DEBUG_PC ("targeted vertice %s being reachable from vertice %s", nodeId, g->vertices[vIndex].verticeId.nodeId);        
-        addedTargetedVerticeIndex = 0;
-        return (addedTargetedVerticeIndex);
-    }
-    
-    for (i = 0; i < g->vertices[vIndex].numTargetedVertices; i++)
-    {        
-		if (memcmp (g->vertices[vIndex].targetedVertices[i].tVertice.nodeId, nodeId, strlen (nodeId)) == 0)
-        {
-            //DEBUG_PC ("Targeted vertice %s is already considered in the reachable from vertice %s", nodeId, g->vertices[vIndex].verticeId.nodeId);
-            addedTargetedVerticeIndex = -1;
-            return (addedTargetedVerticeIndex);
-        }        
-    }    
-    // It is not found, next to be added at i position
-    addedTargetedVerticeIndex = i;
-    return (addedTargetedVerticeIndex);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Remove edge from the graph
- *
- *  @param g
- *  @param e
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-void remove_edge_from_graph (struct graph_t *g, struct edges_t *e) {
-	// Find the ingress vertice into the graph
-	DEBUG_PC ("Removing from Graph %s[%s]) ---> %s[%s] (linkId: %s)", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, e->aEndPointId, e->linkId);
-	gint verticeIndex = -1;		
-	verticeIndex = graph_vertice_lookup (e->aNodeId.nodeId, g);
-	if (verticeIndex == -1)	{
-		DEBUG_PC ("Edge w/ %s is NOT in the Graph!!", e->aNodeId.nodeId);
-		return;
-	}
-	
-	// Find the targeted vertice from vertice Id
-	gint targetedVerticeIndex = -1;
-	targetedVerticeIndex = graph_targeted_vertice_lookup (verticeIndex, e->zNodeId.nodeId, g);
-	if (targetedVerticeIndex == -1)	{
-		DEBUG_PC ("%s --> %s NOT in the Graph!!", e->aNodeId.nodeId, e->zNodeId.nodeId);
-		return;
-	}	
-	//DEBUG_PC ("%s --> %s found in the Graph", e->aNodeId.nodeId, e->zNodeId.nodeId);
-	
-	// Get the edge position
-	gint edgeIndex = -1;
-	edgeIndex = graph_edge_lookup (verticeIndex, targetedVerticeIndex, e, g);
-	if (edgeIndex == -1) {
-		DEBUG_PC ("%s --> %s NOT in the Graph!!", e->aNodeId.nodeId, e->zNodeId.nodeId);
-		return;
-	}
-	
-	//DEBUG_PC ("%s --> %s FOUND in Graph w/ edgeIndex: %d", e->aNodeId.nodeId, e->zNodeId.nodeId, edgeIndex);
-	
-	// Remove the edge
-	//DEBUG_PC ("Start Removing %s --> %s from Graph", e->aNodeId.nodeId, e->zNodeId.nodeId);	
-	struct targetNodes_t *v = &(g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex]);	
-	for (gint j = edgeIndex; j < v->numEdges; j++) {	
-		struct edges_t *e1 = &(v->edges[j]);
-		struct edges_t *e2 = &(v->edges[j+1]);		
-		duplicate_edge (e1, e2);
-	}
-	v->numEdges --;
-	DEBUG_PC ("Number of Edges between %s and %s is %d", e->aNodeId.nodeId, e->zNodeId.nodeId, v->numEdges);	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief create the pointer for keeping a set of the paths (struct compRouteOutput_t)
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct path_set_t * create_path_set () {
-	struct path_set_t * p = g_malloc0 (sizeof (struct path_set_t));
-	if (p == NULL) {
-		DEBUG_PC ("Memory allocation problem");
-		exit (-1);		
-	}
-	return p;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Remove the path set
- *
- * @param p
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2021
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void remove_path_set(struct path_set_t* p) {
-	g_assert(p); g_free(p);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Create map of nodes to handle the path computation
- *
- * 	@param mapN
- *  @param g
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void build_map_node (struct map_nodes_t *mapN, struct graph_t *g) {
-	//DEBUG_PC ("Construction of the Map of Nodes");               
-    for (gint i = 0; i < g->numVertices; i++) {	
-		duplicate_node_id (&g->vertices[i].verticeId, &mapN->map[i].verticeId);
-        mapN->map[i].distance = INFINITY_COST;
-        mapN->map[i].avaiBandwidth = 0.0;
-        mapN->map[i].latency = INFINITY_COST;
-		mapN->map[i].power = INFINITY_COST;
-        mapN->numMapNodes++;
-    }
-    //DEBUG_PC ("mapNodes formed by %d Nodes", mapN->numMapNodes);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Allocate memory for path of struct compRouteOutputList_t *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct compRouteOutputList_t * create_route_list () {
-	struct compRouteOutputList_t *p = g_malloc0 (sizeof (struct compRouteOutputList_t));
-	if (p == NULL) {
-		DEBUG_PC ("Memory Allocation Problem");
-		exit (-1);
-	}
-	return p;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Copy all the attributes defining a path
- *
- * @param dst_path
- * @param src_path
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void copy_path(struct path_t* dst_path, struct path_t* src_path) {
-	g_assert(dst_path);
-	g_assert(src_path);
-
-	// Path capacity
-	dst_path->path_capacity.unit = src_path->path_capacity.unit;
-	memcpy(&dst_path->path_capacity.value, &src_path->path_capacity.value, sizeof(gdouble));
-
-	// Path latency
-	memcpy(&dst_path->path_latency.fixed_latency, &src_path->path_latency.fixed_latency, sizeof(gdouble));
-
-	// Path cost
-	duplicate_string(dst_path->path_cost.cost_name, src_path->path_cost.cost_name);
-	memcpy(&dst_path->path_cost.cost_value, &src_path->path_cost.cost_value, sizeof(gdouble));
-	memcpy(&dst_path->path_cost.cost_algorithm, &src_path->path_cost.cost_algorithm, sizeof(gdouble));
-
-	// Path links
-	dst_path->numPathLinks = src_path->numPathLinks;
-	for (gint i = 0; i < dst_path->numPathLinks; i++) {
-		struct pathLink_t* dPathLink = &(dst_path->pathLinks[i]);
-		struct pathLink_t* sPathLink = &(src_path->pathLinks[i]);
-
-		duplicate_string(dPathLink->linkId, sPathLink->linkId);
-		duplicate_string(dPathLink->aDeviceId, sPathLink->aDeviceId);
-		duplicate_string(dPathLink->zDeviceId, sPathLink->zDeviceId);
-		duplicate_string(dPathLink->aEndPointId, sPathLink->aEndPointId);
-		duplicate_string(dPathLink->zEndPointId, sPathLink->zEndPointId);
-
-		duplicate_string(dPathLink->topologyId.contextId, sPathLink->topologyId.contextId);
-		duplicate_string(dPathLink->topologyId.topology_uuid, sPathLink->topologyId.topology_uuid);
-
-		dPathLink->numLinkTopologies = sPathLink->numLinkTopologies;
-		for (gint j = 0; j < dPathLink->numLinkTopologies; j++) {
-			struct linkTopology_t* dLinkTop = &(dPathLink->linkTopologies[j]);
-			struct linkTopology_t* sLinkTop = &(sPathLink->linkTopologies[j]);
-
-			duplicate_string(dLinkTop->topologyId, sLinkTop->topologyId);
-		}
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Duplicate the route output instance
- *
- * @param dst_ro
- * @param src_ro
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_compRouteOuput(struct compRouteOutput_t* dst_ro, struct compRouteOutput_t* src_ro) {
-	g_assert(dst_ro); g_assert(src_ro); 
-		
-	// Copy the serviceId
-	copy_service_id(&dst_ro->serviceId, &src_ro->serviceId);
-	dst_ro->num_service_endpoints_id = src_ro->num_service_endpoints_id;
-
-	for (gint j = 0; j < dst_ro->num_service_endpoints_id; j++) {
-		struct service_endpoints_id_t* iEp = &(src_ro->service_endpoints_id[j]);
-		struct service_endpoints_id_t* oEp = &(dst_ro->service_endpoints_id[j]);
-		copy_service_endpoint_id(oEp, iEp);
-	}
-
-	// Copy paths
-	dst_ro->numPaths = src_ro->numPaths;
-	for (gint j = 0; j < dst_ro->numPaths; j++) {
-		struct path_t* dst_path = &(dst_ro->paths[j]);
-		struct path_t* src_path = &(src_ro->paths[j]);
-		copy_path(dst_path, src_path);
-	}
-	// copy no path issue value
-	dst_ro->noPathIssue = src_ro->noPathIssue;
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Duplicate the computation route output list
- * 
- * @param dst
- * @param src
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_route_list(struct compRouteOutputList_t* dst, struct compRouteOutputList_t* src) {
-	g_assert(src); g_assert(dst);
-
-	dst->numCompRouteConnList = src->numCompRouteConnList;
-	dst->compRouteOK = src->compRouteOK;
-	memcpy(&dst->compRouteConnAvBandwidth, &src->compRouteConnAvBandwidth, sizeof(gdouble));
-	memcpy(&dst->compRouteConnAvPathLength, &src->compRouteConnAvPathLength, sizeof(gdouble));
-	for (gint i = 0; i < src->numCompRouteConnList; i++) {
-		struct compRouteOutput_t* src_ro = &(src->compRouteConnection[i]);
-		struct compRouteOutput_t* dst_ro = &(dst->compRouteConnection[i]);
-		duplicate_compRouteOuput(dst_ro, src_ro);
-	}	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Allocate memory for path of struct compRouteOutputItem_t *
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct compRouteOutputItem_t *create_path_item () {
-	struct compRouteOutputItem_t *p = g_malloc0 (sizeof (struct compRouteOutputItem_t));
-	if (p == NULL) 	{
-		DEBUG_PC ("Memory Allocation Problem");
-		exit (-1);
-	}
-	return p;	
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Sort the set of paths the AvailBw, Cost and Delay
- *
- *	@params setP
- *  @params args
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void sort_path_set(struct path_set_t* setP, guint args) {
-	g_assert(setP);
-	// Sort the paths contained in setP by:
-	// 1st Criteria: The path cost (maybe bound to link distance)
-	// 2nd Criteria: The consumed path power 
-	// 3nd Criteria: The path latency
-	// 3rd Criteria: The available Bw
-	float epsilon = 0.1;
-
-	for (gint i = 0; i < setP->numPaths; i++) {
-		for (gint j = 0; j < (setP->numPaths - i - 1); j++)	{
-			struct compRouteOutputItem_t* path1 = &setP->paths[j];
-			struct compRouteOutputItem_t* path2 = &setP->paths[j + 1];			
-			struct compRouteOutputItem_t* pathTmp = create_path_item();
-			//////////////////////// Criterias ////////////////////////////////////////
-			// 1st Criteria (Cost)
-			if (path2->cost < path1->cost) {
-				duplicate_path(path1, pathTmp);
-				duplicate_path(path2, path1);
-				duplicate_path(pathTmp, path2);
-				g_free(pathTmp);
-				continue;
-			}
-			if (path2->cost == path1->cost) {
-				// 2nd Criteria (Energy)
-				if (args & ENERGY_EFFICIENT_ARGUMENT) {
-					if (path2->power < path1->power) {
-						duplicate_path(path1, pathTmp);
-						duplicate_path(path2, path1);
-						duplicate_path(pathTmp, path2);
-						g_free(pathTmp);
-						continue;
-					}
-					else {	  // path1->power < path2->power
-						g_free(pathTmp);
-						continue;
-					}
-				}
-				else { // No enery efficient argument
-					// 3rd Criteria (latency)
-					if (path2->delay < path1->delay) {
-						duplicate_path(path1, pathTmp);
-						duplicate_path(path2, path1);
-						duplicate_path(pathTmp, path2);
-						g_free(pathTmp);
-						continue;
-					}
-					else if (path1->delay < path2->delay) {
-						g_free(pathTmp);
-						continue;
-					}
-					else { // path1->delay == path2->delay
-						// 4th Criteria (available bw)
-						if (path2->availCap > path1->availCap) {
-							duplicate_path(path1, pathTmp);
-							duplicate_path(path2, path1);
-							duplicate_path(pathTmp, path2);
-							g_free(pathTmp);
-							continue;
-						}
-						else {
-							g_free(pathTmp);
-							continue;
-						}
-					}
-				}
-			}
-			else {	// path1->cost < path2->cost
-				g_free(pathTmp);
-				continue;
-			}				
-		}
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Remove first element from the path sets 
- *
- *	@params setP
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void pop_front_path_set (struct path_set_t *setP) {
-	for (gint j = 0; j < setP->numPaths - 1; j++) {
-		struct compRouteOutputItem_t *path1 = &setP->paths[j];
-		struct compRouteOutputItem_t *path2 = &setP->paths[j+1];		
-		duplicate_path (path2, path1);		
-	}
-	setP->numPaths--;	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Add routeElement to the back of the path
- *
- * 	@param rE
- * 	@param p
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void add_routeElement_path_back (struct routeElement_t *rE, struct compRouteOutputItem_t *p) {
-	//DEBUG_PC ("p->numRouteElements: %d", p->numRouteElements);
-	p->numRouteElements++;
-	gint index = p->numRouteElements - 1;
-	
-	struct nodes_t *pn = &(p->routeElement[index].aNodeId);
-	struct nodes_t *rEn = &(rE->aNodeId);
-	
-	// duplicate aNodeId
-	duplicate_node_id (rEn, pn);	
-	pn = &(p->routeElement[index].zNodeId);
-	rEn = &(rE->zNodeId);
-	duplicate_node_id (rEn, pn);
-	duplicate_string(p->routeElement[index].aEndPointId, rE->aEndPointId);
-	duplicate_string(p->routeElement[index].zEndPointId, rE->zEndPointId);
-	duplicate_string(p->routeElement[index].linkId, rE->linkId);
-	duplicate_string(p->routeElement[index].aTopologyId, rE->aTopologyId);
-	duplicate_string(p->routeElement[index].zTopologyId, rE->zTopologyId);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief This function compares ap and rootPath. If all the links are equal between both ap and rootPath till the sN, then the link from sN to next node 
- * 	ap is returned
- * 
- * @params ap
- * @params p
- * @params sN
- * @params e
- * 
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gboolean matching_path_rootPath (struct compRouteOutputItem_t *ap, struct compRouteOutputItem_t *rootPath, struct nodes_t *sN, struct edges_t *e) {
-	gint j = 0;
-	gboolean ret = FALSE;
-	while ((j < ap->numRouteElements) && (j < rootPath->numRouteElements)) {
-		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0) &&
-			//(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) != 0) &&
-			(memcmp (sN->nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0)) {						
-			duplicate_node_id (&ap->routeElement[j].aNodeId, &e->aNodeId);
-			duplicate_node_id (&ap->routeElement[j].zNodeId, &e->zNodeId);
-			duplicate_string(e->aEndPointId, ap->routeElement[j].aEndPointId);
-			duplicate_string(e->zEndPointId, ap->routeElement[j].zEndPointId);
-			duplicate_string(e->linkId, ap->routeElement[j].linkId);
-			return TRUE;			
-		}		
-		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0) && 
-			(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) == 0)) {
-			j++;			
-			continue;			
-		}
-		
-		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) != 0) || 
-			(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) != 0)) {
-			//DEBUG_PC ("ap and rootPath not in the same path");
-			return ret;
-		}
-	}	
-	return ret;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief This function is used to modify the graph to be used for running the subsequent SP computations acording to the YEN algorithm principles
- * 
- * @params g
- * @params A
- * @params rootPath
- * @params spurNode
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void modify_targeted_graph (struct graph_t *g, struct path_set_t *A, struct compRouteOutputItem_t * rootPath, struct nodes_t * spurNode) {
-	//DEBUG_PC ("Modify the Targeted graph according to the Yen algorithm principles");
-	for (gint j = 0; j < A->numPaths; j++) {
-		struct compRouteOutputItem_t *ap = &A->paths[j];
-		struct edges_t *e = create_edge();
-		gboolean ret =  FALSE;
-		ret = matching_path_rootPath (ap, rootPath, spurNode, e);		
-		if (ret == TRUE) {
-			DEBUG_PC ("Removal %s[%s] --> %s[%s] from the graph", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, e->aEndPointId);
-			remove_edge_from_graph (g, e);
-			//DEBUG_PC ("Print Resulting Graph");
-			print_graph (g);
-			g_free (e);			
-		}
-		if (ret == FALSE) {
-			g_free (e);
-			continue;
-		}						
-	}	
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Supporting fucntion to Check if a nodeId is already in the items of a given GList
- * 
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint find_nodeId (gconstpointer data, gconstpointer userdata)
-{
-     /** check values */
-     g_assert(data != NULL);
-     g_assert(userdata != NULL);
- 
-     struct nodeItem_t *SNodeId = (struct nodeItem_t *)data;
-     guchar * nodeId = (guchar *)userdata; 
-     
-     //DEBUG_PC ("SNodeId (%s) nodeId (%s)", SNodeId->node.nodeId, nodeId);   
-        
-     if (!memcmp(SNodeId->node.nodeId, nodeId, strlen (SNodeId->node.nodeId)))
-     {
-		return (0);
-     }
-    return -1;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Explores the link between u and v
- * 
- *  @param u
- *  @param v 
- *	@param g
- *	@param s
- *  @param S
- *  @param Q
- *	@param mapNodes
- * 
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struct graph_t *g, 
-				struct service_t *s, GList **S, GList **Q, struct map_nodes_t *mapNodes, 
-				guint arg) { 
-	g_assert(g); g_assert(s); g_assert(mapNodes);
-
-	struct targetNodes_t *v = &(g->vertices[indexGraphU].targetedVertices[indexGraphV]);	
-    DEBUG_PC("Explored Link %s => %s)", u->node.nodeId, v->tVertice.nodeId);
-	//DEBUG_PC("\t %s => %s", u->node.nodeId, v->tVertice.nodeId);	
-    
-    // v already explored in S? then, discard it
-    GList *found = g_list_find_custom (*S, v->tVertice.nodeId, find_nodeId);
-    if (found != NULL) {
-        DEBUG_PC ("v (%s) in S, Discard", v->tVertice.nodeId);        
-        return 0;
-    }
-
-	// Get the set of constraints imposed by the service
-	struct path_constraints_t* path_constraints = get_path_constraints(s);
-    gdouble distance_through_u = INFINITY_COST ,latency_through_u = INFINITY_COST, power_through_u = INFINITY_COST;
-	gint i = 0, foundAvailBw = 0;
-    // BANDWIDTH requirement to be fulfilled on EDGE u->v        
-    gdouble edgeAvailBw = 0.0, edgeTotalBw = 0.0;
-    for (i = 0; i < v->numEdges; i++) {        
-        struct edges_t *e = &(v->edges[i]);
-		memcpy (&edgeAvailBw, &(e->availCap), sizeof (gdouble));
-		memcpy(&edgeTotalBw, &(e->totalCap), sizeof(gdouble));
-		DEBUG_PC("EDGE %s[%s] => %s[%s]", u->node.nodeId, e->aEndPointId, v->tVertice.nodeId, e->zEndPointId);
-        //DEBUG_PC ("\t %s[%s] =>", u->node.nodeId, e->aEndPointId);
-		//DEBUG_PC("\t => %s[%s]", v->tVertice.nodeId, e->zEndPointId);
-		DEBUG_PC("\t AvailBw: %f, TotalBw: %f", edgeAvailBw, edgeTotalBw);
-        // Check Service Bw constraint
-		if ((path_constraints->bw == TRUE) && (edgeAvailBw < path_constraints->bwConstraint))
-			continue;
-		else {
-			foundAvailBw = 1;
-			break;
-		}		
-    }
-	// BW constraint NOT MET, then DISCARD edge
-    if ((path_constraints->bw == TRUE) && (foundAvailBw == 0)) {
-        DEBUG_PC ("AvailBw: %f < path_constraint: %f -- Discard Edge", edgeAvailBw, path_constraints->bwConstraint);
-		g_free(path_constraints);
-        return 0;    
-    } 
-
-    gint indexEdge = i; // get the index for the explored edge
-    // Update distance, latency and availBw through u to reach v
-    gint map_uIndex = get_map_index_by_nodeId (u->node.nodeId, mapNodes);
-	struct map_t *u_map = &mapNodes->map[map_uIndex];
-    distance_through_u = u_map->distance + v->edges[indexEdge].cost;
-    latency_through_u = u_map->latency + v->edges[indexEdge].delay;
-	// Consumed power at v through u is the sum
-	// 1. Power from src to u
-	// 2. Power-idle at node u
-	// 3. power consumed over the edge between u and v, i.e. energy*usedBw
-	power_through_u = u_map->power + g->vertices[indexGraphU].power_idle + ((edgeTotalBw - edgeAvailBw + path_constraints->bwConstraint) * (v->edges[indexEdge].energy));
-    gdouble availBw_through_u = 0.0;
-
-	// ingress endpoint (u) is the src of the request
-    if (strcmp (u->node.nodeId, s->service_endpoints_id[0].device_uuid) == 0) {
-        //DEBUG_PC ("AvailBw %f on %s --> %s", edgeAvailBw, u->node.nodeId, v->tVertice.nodeId);        
-        memcpy (&availBw_through_u, &edgeAvailBw, sizeof (gdouble));        
-    }
-    else {
-        // Get the minimum available bandwidth between the src-->u and the new added edge u-->v
-        //DEBUG_PC ("Current AvailBw: %f from src to %s", u_map->avaiBandwidth, u->node.nodeId);
-        //DEBUG_PC ("AvailBw: %f %s --> %s", edgeAvailBw, u->node.nodeId, v->tVertice.nodeId);
-        if (u_map->avaiBandwidth <= edgeAvailBw) {
-            memcpy (&availBw_through_u, &u_map->avaiBandwidth, sizeof (gdouble));    
-		}
-		else {
-			memcpy (&availBw_through_u, &edgeAvailBw, sizeof (gdouble));
-		} 
-    }     
-    // Relax the link according to the pathCost, latency, and energy
-    gint map_vIndex = get_map_index_by_nodeId (v->tVertice.nodeId, mapNodes);
-	struct map_t *v_map = &mapNodes->map[map_vIndex];
-    // If cost dist (u, v) > dist (src, v) relax the link
-    if (distance_through_u > v_map->distance) {
-        //DEBUG_PC ("dist(src, u) + dist(u, v): %f > dist (src, v): %f --> Discard Link", distance_through_u, v_map->distance);  
-        return 0;
-    }
-	// If energy consumption optimization is requested
-	if (arg & ENERGY_EFFICIENT_ARGUMENT) {
-		if (distance_through_u == v_map->distance) {
-			if (power_through_u > v_map->power) {
-				DEBUG_PC("Energy (src -> u + u -> v: %f (Watts) >Energy (src, v): %f (Watts)--> DISCARD LINK", power_through_u, v_map->power);
-				return 0;
-			}
-			// same energy consumption, consider latency
-			if ((power_through_u == v_map->power) && (latency_through_u > v_map->latency)) {
-				return 0;
-			}
-			if ((power_through_u == v_map->power) && (latency_through_u == v_map->latency) && (availBw_through_u < v_map->avaiBandwidth)) {
-				return 0;
-			}
-		}
-	} // No optimization, rely on latency and available e2e bandwidth
-	else {
-		// If dist (src, u) + dist (u, v) = current dist(src, v), then use the latency as discarding criteria
-		if ((distance_through_u == v_map->distance) && (latency_through_u > v_map->latency)) {
-			//DEBUG_PC ("dist(src, u) + dist(u,v) = current dist(src, v), but latency (src,u) + latency (u, v) > current latency (src, v)");          
-			return 0;
-		}
-		// If dist (src, u) + dist (u,v) == current dist(src, v) AND latency (src, u) + latency (u, v) == current latency (src, v), the available bandwidth is the criteria
-		if ((distance_through_u == v_map->distance) && (latency_through_u == v_map->latency) && (availBw_through_u < v_map->avaiBandwidth)) {
-			return 0;
-		}
-	}
-    DEBUG_PC ("%s --> %s Relaxed", u->node.nodeId, v->tVertice.nodeId);
-    DEBUG_PC ("\t AvailBw: %f Mb/s, Cost: %f, Latency: %f ms, Energy: %f Watts", availBw_through_u, distance_through_u, latency_through_u, power_through_u);
-    
-    // Update Q list -- 
-    struct nodeItem_t *nodeItem = g_malloc0 (sizeof (struct nodeItem_t));
-    if (nodeItem == NULL) {
-		DEBUG_PC ("memory allocation failed\n");
-		exit (-1);    
-    }    
-    nodeItem->distance = distance_through_u;
-	memcpy(&nodeItem->distance, &distance_through_u, sizeof(gdouble));		     
-	memcpy(&nodeItem->latency, &latency_through_u, sizeof(gdouble));
-	memcpy(&nodeItem->power, &power_through_u, sizeof(gdouble));
-	duplicate_node_id (&v->tVertice, &nodeItem->node);	
-	// add node to the Q list
-	if (arg & ENERGY_EFFICIENT_ARGUMENT) {
-		*Q = g_list_insert_sorted(*Q, nodeItem, sort_by_energy);
-	}
-	else
-		*Q = g_list_insert_sorted (*Q, nodeItem, sort_by_distance);
-    
-	// Update the mapNodes for the specific reached tv   
-    v_map->distance = distance_through_u;
-	memcpy(&v_map->distance, &distance_through_u, sizeof(gdouble));
-    memcpy (&v_map->avaiBandwidth, &availBw_through_u, sizeof (gdouble));
-    memcpy (&v_map->latency, &latency_through_u, sizeof (gdouble));
-	memcpy(&v_map->power, &power_through_u, sizeof(gdouble));
-    // Duplicate the predecessor edge into the mapNodes 
-	struct edges_t *e1 = &(v_map->predecessor);
-	struct edges_t *e2 = &(v->edges[indexEdge]);
-	duplicate_edge(e1, e2);	
-	DEBUG_PC ("u->v Edge: %s(%s) --> %s(%s)", e2->aNodeId.nodeId, e2->aEndPointId, e2->zNodeId.nodeId, e2->zEndPointId);
-	//DEBUG_PC("v-pred aTopology: %s", e2->aTopologyId);
-	DEBUG_PC("v-pred zTopology: %s", e2->zTopologyId);
-
-    // Check whether v is dstPEId
-	//DEBUG_PC ("Targeted dstId: %s", s->service_endpoints_id[1].device_uuid);
-	//DEBUG_PC ("nodeId added to the map: %s", v_map->verticeId.nodeId);
-	//DEBUG_PC ("Q Length: %d", g_list_length(*Q));
-	g_free(path_constraints);
-    return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Check the feasability of a path wrt the constraints imposed by the request in terms of latency
- * 
- *  @param s
- *	@param p
- * 
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gboolean check_computed_path_feasability (struct service_t *s, struct compRouteOutputItem_t* p) {	
-	float epsilon = 0.0000001;
-	struct path_constraints_t* pathCons = get_path_constraints(s);
-	gboolean ret = TRUE;
-	if (pathCons->latency == TRUE) {
-		if ((pathCons->latencyConstraint - p->delay > 0.0) || (fabs(pathCons->latencyConstraint - p->delay) < epsilon)) {
-			DEBUG_PC("Computed Path (latency: %f) is feasible wrt Connection Demand: %f", p->delay, pathCons->latencyConstraint);
-		}
-		else {
-			DEBUG_PC("Computed Path (latency: %f) is NOT feasible wrt Connection Demand: %f", p->delay, pathCons->latencyConstraint);
-			g_free(pathCons);
-			return FALSE;
-		}
-	}
-	// Other constraints...		
-	g_free(pathCons);
-	return ret;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Sorting the GList Q items by distance 
- * 
- * @param a
- * @param b
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint sort_by_distance (gconstpointer a, gconstpointer b) {
-	//DEBUG_PC ("sort by distance a and b");	
-	g_assert(a != NULL);
-	g_assert(b != NULL);
-	
-	//DEBUG_PC ("sort by distance a and b");	  
-	struct nodeItem_t *node1 = (struct nodeItem_t *)a;
-	struct nodeItem_t *node2 = (struct nodeItem_t *)b;
-	g_assert (node1);
-	g_assert (node2);
-	 
-	//DEBUG_PC ("a->distance %u; b->distance %u", node1->distance, node2->distance);
-	//DEBUG_PC("a->latency: %f; b->latency: %f", node1->latency, node2->latency);
-	//1st criteria, sorting by lowest distance
-	if (node1->distance > node2->distance)
-		return 1;
-	else if (node1->distance < node2->distance)
-		return 0;
-	if (node1->distance == node2->distance) {
-		if (node1->latency > node2->latency)
-			return 1;
-		else if (node1->latency <= node2->latency)
-			return 0;
-	}
-	return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Sorting the GList Q items by distance
- * 
- * @param a
- * @param b
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-gint sort_by_energy(gconstpointer a, gconstpointer b) {	
-	g_assert(a != NULL);
-	g_assert(b != NULL);
-
-	//DEBUG_PC ("sort by distance a and b");	  
-	struct nodeItem_t* node1 = (struct nodeItem_t*)a;
-	struct nodeItem_t* node2 = (struct nodeItem_t*)b;
-	g_assert(node1);
-	g_assert(node2);
-	
-	//1st criteria: sorting by lowest distance
-	if (node1->distance > node2->distance)
-		return 1;
-	if (node1->distance < node2->distance)
-		return 0;
-
-	// 2nd Criteria: sorting by the lowest energy
-	if (node1->power > node2->power)
-		return 1;
-	if (node1->power < node1->power)
-		return 0;
-
-	// 3rd Criteria: by the latency 
-	if (node1->latency > node2->latency)
-		return 1;
-	if (node1->latency <= node2->latency)
-		return 0;
-	return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Allocate memory for graph
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct graph_t * create_graph () {
-	struct graph_t * g = g_malloc0 (sizeof (struct graph_t));
-	if (g == NULL) {
-		DEBUG_PC ("Memory Allocation Problem");
-		exit (-1);
-	}
-	return g;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Allocate memory for mapNodes
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-struct map_nodes_t * create_map_node ()	 {
-	struct map_nodes_t * mN = g_malloc0 (sizeof (struct map_nodes_t));
-	if (mN == NULL) {
-		DEBUG_PC ("Memory allocation failed");
-		exit (-1);
-	}
-	return mN;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Look up for the service in the servieList bound to a serviceUUID
- * 
- * @params serviceUUID
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct service_t* get_service_for_computed_path(gchar* serviceUUID) {
-	gint i = 0;
-	for(GList *listnode = g_list_first(serviceList);
-		listnode;
-		listnode = g_list_next(listnode), i++) {
-			struct service_t* s = (struct service_t*)(listnode->data);
-			if (strcmp(s->serviceId.service_uuid, serviceUUID) == 0)
-				return s;
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the service type
- * 
- * @param type
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_service_type(guint type) {
-	switch (type) {
-	case SERVICE_TYPE_UNKNOWN:
-			DEBUG_PC("Service Type UNKNOWN");
-			break;
-		case SERVICE_TYPE_L3NM:
-			DEBUG_PC("Service Type L3NM");
-			break;
-		case SERVICE_TYPE_L2NM:
-			DEBUG_PC("Service Type L2NM");
-			break;
-		case SERVICE_TYPE_TAPI:
-			DEBUG_PC("Service Type L2NM");
-			break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the port direction
- *
- * @param direction
- *
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_link_port_direction(guint direction) {
-	switch (direction) {
-		case LINK_PORT_DIRECTION_BIDIRECTIONAL:
-			//DEBUG_PC("Bidirectional Port Direction");
-			break;
-		case LINK_PORT_DIRECTION_INPUT:
-			//DEBUG_PC("Input Port Direction");
-			break;
-		case LINK_PORT_DIRECTION_OUTPUT:
-			//DEBUG_PC("Output Port Direction");
-			break;
-		case LINK_PORT_DIRECTION_UNKNOWN:
-			//DEBUG_PC("Unknown Port Direction");
-			break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the port termination direction
- *
- * @param direction
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_termination_direction(guint direction) {
-	switch (direction) {
-	case TERMINATION_DIRECTION_BIDIRECTIONAL:
-		//DEBUG_PC("Bidirectional Termination Direction");
-		break;
-	case TERMINATION_DIRECTION_SINK:
-		//DEBUG_PC("Input Termination Direction");
-		break;
-	case TERMINATION_DIRECTION_SOURCE:
-		//DEBUG_PC("Output Termination Direction");
-		break;
-	case TERMINATION_DIRECTION_UNKNOWN:
-		//DEBUG_PC("Unknown Termination Direction");
-		break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the termination state
- *
- * @param state 
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_termination_state(guint state)
-{
-	switch (state) {
-	case TERMINATION_STATE_CAN_NEVER_TERMINATE:
-		//DEBUG_PC("Can never Terminate");
-		break;
-	case TERMINATION_STATE_NOT_TERMINATED:
-		DEBUG_PC("Not terminated");
-		break;
-	case TERMINATION_STATE_TERMINATED_SERVER_TO_CLIENT_FLOW:
-		DEBUG_PC("Terminated server to client flow");
-		break;
-	case TERMINATION_STATE_TERMINATED_CLIENT_TO_SERVER_FLOW:
-		DEBUG_PC("Terminated client to server flow");
-		break;
-	case TERMINATION_STATE_TERMINATED_BIDIRECTIONAL:
-		//DEBUG_PC("Terminated bidirectional");
-		break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the capacity unit
- *
- * @param unit
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_capacity_unit(guint unit) {
-
-	switch (unit) {
-		case CAPACITY_UNIT_TB:
-			DEBUG_PC("Unit in TB");
-			break;
-		case CAPACITY_UNIT_TBPS:
-			DEBUG_PC("Unit in TB/s");
-			break;
-		case CAPACITY_UNIT_GB:
-			DEBUG_PC("Unit in GB");
-			break;
-		case CAPACITY_UNIT_GBPS:
-			DEBUG_PC("Unit in GB/s");
-			break;
-		case CAPACITY_UNIT_MB:
-			DEBUG_PC("Unit in MB");
-			break;
-		case CAPACITY_UNIT_MBPS:
-			//DEBUG_PC("Unit in MB/s");
-			break;
-		case CAPACITY_UNIT_KB:
-			DEBUG_PC("Unit in KB");
-			break;
-		case CAPACITY_UNIT_KBPS:
-			DEBUG_PC("Unit in KB/s");
-			break;
-		case CAPACITY_UNIT_GHZ: 
-			DEBUG_PC("Unit in GHz");
-			break;
-		case CAPACITY_UNIT_MHZ:
-			DEBUG_PC("Unit in MHz");
-			break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Friendly function to log the link forwarding direction
- *
- * @param linkFwDir
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_link_forwarding_direction(guint linkFwDir) {
-	switch (linkFwDir) {
-		case LINK_FORWARDING_DIRECTION_BIDIRECTIONAL:
-			DEBUG_PC("BIDIRECTIONAL LINK FORWARDING DIRECTION");
-			break;
-		case LINK_FORWARDING_DIRECTION_UNIDIRECTIONAL:
-			DEBUG_PC("UNIDIRECTIONAL LINK FORWARDING DIRECTION");
-			break;
-		case  LINK_FORWARDING_DIRECTION_UNKNOWN:
-			DEBUG_PC("UNKNOWN LINK FORWARDING DIRECTION");
-			break;
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Search a specific contextUuid element into the contextSet
- *
- * @param contextUuid
- * @param set
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct context_t* find_contextId_in_set(gchar* contextUuid, GList** set) {
-	//DEBUG_PC("Checking if contextId: %s in in the ContextSet??", contextUuid);
-	gint i = 0;
-	for (GList *ln = g_list_first(*set);
-		ln;
-		ln = g_list_next(ln)){
-		struct context_t* c = (struct context_t*)(ln->data);
-		//DEBUG_PC("Context Item [%d] Id: %s", i, c->contextId);
-		if (strcmp(contextUuid, c->contextId) == 0) {
-			//DEBUG_PC("contextId: %s is FOUND in the ContextSet_List", contextUuid);
-			return c;
-		}
-		i++;
-	}
-	//DEBUG_PC("contextId: %s NOT FOUND in the ContextSet_List", contextUuid);
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Add a specific context uuid into the context set
- *
- * @param contextUuid
- * @param set
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct context_t* add_contextId_in_set(gchar *contextUuid, GList** set) {
-
-	struct context_t* c = g_malloc0(sizeof(struct context_t));
-	if (c == NULL) {
-		DEBUG_PC("Memory Allocation Failure");
-		exit(-1);
-	}
-	duplicate_string(c->contextId, contextUuid);
-	// Add the context into the context set
-	//DEBUG_PC("Adding ContextId: %s", contextUuid);
-	//DEBUG_PC(" (BEFORE ADDING) Context Set Length: %d", g_list_length(*set));
-	*set = g_list_append(*set, c);
-	//DEBUG_PC(" (AFTER ADDING) Context Set Length: %d", g_list_length(*set));
-	return c;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Find a vertex in a specific graph
- *
- * @param contextUuid
- * @param set
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct vertices_t* find_vertex_in_graph_context(struct graph_t *g, gchar* deviceId) {
-	for (gint i = 0; i < g->numVertices; i++) {
-		struct vertices_t* v = &(g->vertices[i]);
-		if (strcmp(v->verticeId.nodeId, deviceId) == 0) {
-			return v;
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Adding a deviceId into a graph
- *
- * @param g
- * @param deviceId
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct vertices_t* add_vertex_in_graph(struct graph_t* g, struct device_t *d) {
-	g->numVertices++;
-	struct vertices_t* v = &(g->vertices[g->numVertices - 1]);
-	duplicate_string(v->verticeId.nodeId, d->deviceId);
-	memcpy(&v->power_idle, &d->power_idle, sizeof(gdouble));
-	return v;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Construct the graphs (vertices and edges) bound to every individual context
- *
- * @param cSet
- * @param activeFlag
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void build_contextSet_deviceList(GList** cSet, gint activeFlag) {
-	// Check every device their endpoints	
-	for (GList* listnode = g_list_first(deviceList); 
-		listnode; 
-		listnode = g_list_next(listnode)) {	
-		struct device_t* d = (struct device_t*)(listnode->data);
-		//DEBUG_PC("Exploring DeviceId: %s", d->deviceId);
-
-		if ((activeFlag == 1) && (d->operational_status != 2)) {
-			// it is only considered devices with operational status enabled, i.e., set to 2
-			continue;
-		}
-		// Check the associated endPoints
-		for (gint j = 0; j < d->numEndPoints; j++) {
-			struct endPoint_t* eP = &(d->endPoints[j]);
-			// Get endPointId (topology, context, device Id and endpoint uuid)
-			struct endPointId_t* ePid = &(eP->endPointId);  //end point id
-			//DEBUG_PC("   EndPointId: %s || Type: %s", eP->endPointId.endpoint_uuid, d->deviceType);
-			//DEBUG_PC("   TopologyId: %s || ContextId: %s", eP->endPointId.topology_id.topology_uuid, eP->endPointId.topology_id.contextId);
-			// Add contextId in ContextSet and the deviceId (+endpoint) into the vertex set
-			struct context_t *c = find_contextId_in_set(eP->endPointId.topology_id.contextId, cSet);
-			if (c == NULL) {
-				DEBUG_PC("   contextUuid: %s MUST BE ADDED to ContextSet", eP->endPointId.topology_id.contextId);
-				c = add_contextId_in_set(eP->endPointId.topology_id.contextId, cSet);
-			}
-			// Check if the deviceId and endPointUuid are already considered in the graph of the context c
-			struct vertices_t* v = find_vertex_in_graph_context(&c->g, d->deviceId);
-			if (v == NULL) {
-				//DEBUG_PC("  deviceId: %s MUST BE ADDED to the Context Graph", d->deviceId);
-				v = add_vertex_in_graph(&c->g, d);
-			}
-		}
-	}
-	//print_contextSet(cSet);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Determine whether a deviceId is in the targetNode list of a specific vertex v
- *
- * @param v
- * @param deviceId
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct targetNodes_t* find_targeted_vertex_in_graph_context(struct vertices_t* v, gchar *deviceId) {
-	for (gint k = 0; k < v->numTargetedVertices; k++) {
-		struct targetNodes_t* w = &(v->targetedVertices[k]);
-		if (strcmp(w->tVertice.nodeId, deviceId) == 0) {
-			return w;
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Add a deviceId a targetNode of a specific vertex v
- *
- * @param v
- * @param deviceId
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct targetNodes_t* add_targeted_vertex_in_graph_context(struct vertices_t* v, gchar* bDeviceId) {
-	v->numTargetedVertices++;
-	struct targetNodes_t* w = &(v->targetedVertices[v->numTargetedVertices - 1]);
-	duplicate_string(w->tVertice.nodeId, bDeviceId);
-	return w;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Returns the structure of a device endpoint bound to a specific deviceId and endPointId
- *
- * @param devId
- * @param endPointUuid
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct endPoint_t* find_device_tied_endpoint(gchar* devId, gchar* endPointUuid) {
-	//DEBUG_PC("devId: %s ePId: %s", devId, endPointUuid);
-	for (GList* ln = g_list_first(deviceList);
-		ln;
-		ln = g_list_next(ln)) {
-		struct device_t* d = (struct device_t*)(ln->data);
-		if (strcmp(d->deviceId, devId) != 0) {
-			continue;
-		}
-		// Iterate over the endpoints tied to the deviceId
-		for (gint j = 0; j < d->numEndPoints; j++) {
-			struct endPoint_t* eP = &(d->endPoints[j]);
-			//DEBUG_PC("looked endPointId: %s", eP->endPointId.endpoint_uuid);
-			if (strcmp(eP->endPointId.endpoint_uuid, endPointUuid) == 0) {
-				return eP;
-			}
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Adding the edge/linnk in the targetedNodes w list
- *
- * @param w
- * @param l
- * @param activeFlag
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void add_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l, gint activeFlag) {
-	//DEBUG_PC("\t targetedVertex: %s", w->tVertice.nodeId);
-
-	// Check if the activeFlag is 1. If YES, it is only added to the edges as long as the 
-	// associated endPoint is in status ENABLED, i.e., with operational status set to 2
-	// Get the endpoints (A and Z) of the link l (assumed P2P)
-	struct link_endpointId_t* aEndpointId = &(l->linkEndPointId[0]);
-	struct link_endpointId_t* zEndpointId = &(l->linkEndPointId[1]);
-	// Get the endPoint Information tied to the device bound to aEndPointId
-	struct endPoint_t* eP = find_device_tied_endpoint(aEndpointId->deviceId, aEndpointId->endPointId);
-	if (eP == NULL) {
-		DEBUG_PC("devId: %s endPointUuid: %s NOT in Device List!!--- Weird", aEndpointId->deviceId, aEndpointId->endPointId);
-		exit(-1);
-	}
-	// Check whether the port in that endPoint (eP) is Active upon the activeFlag being SET
-	if (activeFlag == 1) {
-		if (eP->operational_status != 2) // NOT ENABLED, then discard this link
-			return;
-	}
-
-	// Add the edge into the graph
-	w->numEdges++;
-	struct edges_t* e = &(w->edges[w->numEdges - 1]);
-	// Copy the link Id UUID
-	duplicate_string(e->linkId, l->linkId);
-	duplicate_string(e->aNodeId.nodeId, aEndpointId->deviceId);
-	duplicate_string(e->aEndPointId, aEndpointId->endPointId);
-	duplicate_string(e->aTopologyId, aEndpointId->topology_id.topology_uuid);	
-	duplicate_string(e->zNodeId.nodeId, zEndpointId->deviceId);
-	duplicate_string(e->zEndPointId, zEndpointId->endPointId);
-	duplicate_string(e->zTopologyId, zEndpointId->topology_id.topology_uuid);
-	
-	//Potential(total) and available capacity
-	e->unit = eP->potential_capacity.unit;
-	memcpy(&e->totalCap, &eP->potential_capacity.value, sizeof(gdouble));
-	memcpy(&e->availCap, &eP->available_capacity.value, sizeof(gdouble));
-	// Copy interdomain local/remote Ids
-	memcpy(e->interDomain_localId, eP->inter_domain_plug_in.inter_domain_plug_in_local_id, 
-		strlen(eP->inter_domain_plug_in.inter_domain_plug_in_local_id));
-	memcpy(e->interDomain_remoteId, eP->inter_domain_plug_in.inter_domain_plug_in_remote_id,
-		strlen(eP->inter_domain_plug_in.inter_domain_plug_in_remote_id));
-	// cost value
-	memcpy(&e->cost, &l->cost_characteristics.cost_value, sizeof(gdouble));
-	// latency ms
-	memcpy(&e->delay, &l->latency_characteristics.fixed_latency, sizeof(gdouble));
-	// energy J/bits ~ power
-	memcpy(&e->energy, &eP->energyConsumption, sizeof(gfloat));
-	
-	//DEBUG_PC("Edge - Total/Available Capacity: %f/%f; Cost: %f; Delay: %f, Energy: %f", eP->potential_capacity.value, eP->available_capacity.value,
-	//	l->cost_characteristics.cost_value, l->latency_characteristics.fixed_latency, l->energy_link);
-
-	//DEBUG_PC("Graph Edge - Total/Available Capacity: %f/%f; Cost: %f; Delay: %f, Energy: %f", e->totalCap, e->availCap,
-	//	e->cost, e->delay, e->energy);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Searching a specific edge/link by the linkId(UUID)
- *
- * @param w
- * @param l
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct edges_t* find_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l) {		
-	for (gint i = 0; i < w->numEdges; i++) {
-		struct edges_t* e = &(w->edges[i]);
-		if (strcmp(e->linkId, l->linkId) == 0) {
-			return e;
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief supporting the construction of the graph per context using the explicit
- * contents/info of the link list
- *
- * @param set
- * @param activeFlag
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void build_contextSet_linklList(GList** set, gint activeFlag) {	
-	// for each link in linkList:
-	// 1st- Retrieve endpoints A --> B feauture (context Id, device Id, endpoint Id)
-	// 2st - In the graph associated to the contextId, check wheter A (deviceId) is in the vertices list
-	// o No, this is weird ... exist
-	// o Yes, get the other link endpoint (i.e., B) and check whether it exists. If NOT add it, considering
-	// all the attributes; Otherwise, check whether the link is different from existing edges between A and B
-	gdouble epsilon = 0.1;
-	gint j = 0;
-	for (GList* ln = g_list_first(linkList);
-		ln;
-		ln = g_list_next(ln)) {
-		struct link_t* l = (struct link_t*)(ln->data);
-		j++;
-
-		// link assumed to be P2P A --> B; i.e. 2 endPoints; 1st specifies A and 2nd specifie B
-		struct link_endpointId_t* aEndpointId = &(l->linkEndPointId[0]);
-		struct topology_id_t* topologyId = &(aEndpointId->topology_id);
-		// get the contextId
-		gchar contextUuid[UUID_CHAR_LENGTH];
-		duplicate_string(contextUuid, topologyId->contextId);
-		DEBUG_PC("Link: %s in ContextId: %s", l->linkId, contextUuid);
-
-		// Check first contextUuid exists in the cSet
-		//DEBUG_PC("Length of Context: %d", g_list_length(set));
-		struct context_t* c = find_contextId_in_set(contextUuid, set);
-		if (c == NULL) {
-			DEBUG_PC("ContextId: %s does NOT exist... weird", contextUuid);
-			exit(-1);
-		}
-
-		// get the device ID of A
-		gchar aDeviceId[UUID_CHAR_LENGTH];
-		duplicate_string(aDeviceId, aEndpointId->deviceId);
-
-		struct graph_t* g = &(c->g); // get the graph associated to the context c
-		struct vertices_t* v = find_vertex_in_graph_context(g, aDeviceId);
-		if (v == NULL) {
-			DEBUG_PC("%s NOT a VERTEX of contextId: %s ... WEIRD", aDeviceId, contextUuid);
-			exit(-1);
-		}		
-		// get the bEndpointId
-		struct link_endpointId_t* bEndpointId = &(l->linkEndPointId[1]);
-		gchar bDeviceId[UUID_CHAR_LENGTH];
-		duplicate_string(bDeviceId, bEndpointId->deviceId);
-		DEBUG_PC("[%d] -- Link: %s [%s ==> %s]", j-1, l->linkId, aDeviceId, bDeviceId);
-		// Check whether device B is in the targeted Vertices from A (i.e., v)?
-		// If not, add B in the targeted vertices B + create the edge and add it
-		// If B exist, check whether the explored link/edge is already in the list of edges
-		struct targetNodes_t* w = find_targeted_vertex_in_graph_context(v, bDeviceId);
-		if (w == NULL) {
-			DEBUG_PC("[%s] is PEER of [%s]", bDeviceId, v->verticeId.nodeId);
-			w = add_targeted_vertex_in_graph_context(v, bDeviceId);
-			add_edge_in_targetedVertice_set(w, l, activeFlag);
-		}
-		else {
-			// w exists, it is needed to check whether the edge (link) should be added
-			struct edges_t* e = find_edge_in_targetedVertice_set(w, l);
-			if (e == NULL) {
-				// Add the link into the list
-				add_edge_in_targetedVertice_set(w, l, activeFlag);
-			}
-			else {
-				DEBUG_PC("The link already exists ...");
-				continue;
-			}
-		}
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Create the set of (distinct) contexts with the deviceList and linkList
- *
- * @param cSet
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void build_contextSet(GList** cSet) {
-	gint activeFlag = 0; // this means that all the devices/links (regardless they are active or not) are considered
-
-	// devices are tied to contexts, i.e. depending on the contextId of the devices
-	build_contextSet_deviceList(cSet, activeFlag);
-
-	DEBUG_PC("Length for the Context Set: %d", g_list_length(*cSet));
-
-	// Once the diverse contexts are created and the devices/endpoints asigned to the 
-	// respective graph tied to each context, it is needed to create the edges
-	build_contextSet_linklList(cSet, activeFlag);
-
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Create the set of (distinct) contexts with the deviceList and linkList with
- * operational status active
- *
- * @param cSet
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void build_contextSet_active(GList** cSet) {
-	gint activeFlag = 1; // this means that all the devices (regardless they are active or not) are considered
-
-	// devices are tied to contexts, i.e. depending on the contextId of the devices
-	build_contextSet_deviceList(cSet, activeFlag);
-
-	DEBUG_PC("Length for the Context Set: %d", g_list_length(*cSet));
-
-	// Once the diverse contexts are created and the devices/endpoints asigned to the 
-	// respective graph tied to each context, it is needed to create the edges
-	build_contextSet_linklList(cSet, activeFlag);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Print the contents of the ContextIds
- *
- * @param set
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_contextSet(GList* set) {
-
-	DEBUG_PC("Printing the ContextSet w/ number of Elements: %d", g_list_length(set));
-
-	for (GList* ln = g_list_first(set);
-		ln;
-		ln = g_list_next(ln)) {
-		struct context_t* c = (struct context_t*)(ln->data);
-		DEBUG_PC("-------------------------------------------------------------");
-		DEBUG_PC(" Context Id: %s", c->contextId);
-		DEBUG_PC("-------------------------------------------------------------");
-
-		struct graph_t* g = &(c->g);
-		for (gint j = 0; j < g->numVertices; j++) {
-			struct vertices_t* v = &(g->vertices[j]);
-			DEBUG_PC("  Head Device Id: %s", v->verticeId.nodeId);
-			for (gint k = 0; k < v->numTargetedVertices; k++) {
-				struct targetNodes_t* w = &(v->targetedVertices[k]);
-				DEBUG_PC("  [%d] --- Peer Device Id: %s", k, w->tVertice.nodeId);
-				for (gint l = 0; l < w->numEdges; l++) {
-					struct edges_t* e = &(w->edges[l]);
-					DEBUG_PC("   \t link Id: %s", e->linkId);
-					DEBUG_PC("   \t aEndPointId: %s", e->aEndPointId);
-					DEBUG_PC("   \t zEndPointId: %s", e->zEndPointId);
-					DEBUG_PC("   \t Available Capacity: %f, Latency: %f, Cost: %f", e->availCap, e->delay, e->cost);
-					DEBUG_PC("   \t aTopologyId: %s", e->aTopologyId);
-					DEBUG_PC("   \t zTopologyId: %s", e->zTopologyId);
-				}
-			}
-		}
-	}
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Check whether src and dst PE nodeId of the req are the same
- *
- *	@param r
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-gint same_src_dst_pe_nodeid(struct service_t* s)
-{
-	// Check that source PE and dst PE are NOT the same, i.e., different ingress and egress endpoints (iEp, eEp)
-	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
-	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
-
-	gchar* iEpUUID = iEp->endpoint_uuid;
-	gchar* eEpUUID = eEp->endpoint_uuid;
-	gchar* iDevUUID = iEp->device_uuid;
-	gchar* eDevUUID = eEp->device_uuid;
-
-	// Compare the device uuids
-	if (strcmp(iDevUUID, eDevUUID) != 0) {
-		DEBUG_PC("DIFFERENT --- iDevId: %s and eDevId: %s", iDevUUID, eDevUUID);
-		return 1;
-	}
-	// Compare the endpoints (ports)
-	if (strcmp(iEpUUID, eEpUUID) != 0) {
-		DEBUG_PC("DIFFERENT --- iEpUUID: %s and eEpUUID: %s", iEpUUID, eEpUUID);
-		return 1;
-	}
-	return 0;	
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Handles issues with the route computation
- *
- *	@param route
- *	@param s
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void comp_route_connection_issue_handler (struct compRouteOutput_t *path, struct service_t *s)
-{
-	g_assert(path); g_assert(s);
-
-	// Increase the number of computed routes/paths despite there was an issue to be reported		
-	path->numPaths++;	
-	// Copy the serviceId
-	copy_service_id(&(path->serviceId), &(s->serviceId));
-
-	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
-	for (gint i = 0; i < s->num_service_endpoints_id; i++) {
-		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
-		struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
-		copy_service_endpoint_id(oEp, iEp);
-	}
-	path->num_service_endpoints_id = s->num_service_endpoints_id;
-	path->noPathIssue = NO_PATH_CONS_ISSUE;
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief released the allocated memory fo compRouteOutputList_t
- *
- *	@param ro
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void destroy_compRouteOutputList (struct compRouteOutputList_t *ro)
-{
-	g_assert (ro);	
-	g_free (ro);	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief creates a copy of the underlying graph
- *
- *	@param originalGraph
- *	@param destGraph
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void duplicate_graph (struct graph_t *originalGraph, struct graph_t *destGraph)	{
-	g_assert (originalGraph); g_assert (destGraph);
-	
-	destGraph->numVertices = originalGraph->numVertices;
-	for (gint i = 0; i < originalGraph->numVertices; i++) {
-		struct vertices_t *oVertex = &(originalGraph->vertices[i]);
-		struct vertices_t *dVertex = &(destGraph->vertices[i]);
-		dVertex->numTargetedVertices = oVertex->numTargetedVertices;		
-		duplicate_node_id (&oVertex->verticeId, &dVertex->verticeId);
-		memcpy(&dVertex->power_idle, &oVertex->power_idle, sizeof(gdouble));
-		
-		for (gint j = 0; j < oVertex->numTargetedVertices; j++)	{
-			struct targetNodes_t *oTargetedVertex = &(oVertex->targetedVertices[j]);
-			struct targetNodes_t *dTargetedVertex = &(dVertex->targetedVertices[j]);
-			duplicate_node_id (&oTargetedVertex->tVertice, &dTargetedVertex->tVertice);
-			dTargetedVertex->numEdges = oTargetedVertex->numEdges;
-			
-			for (gint k = 0; k < oTargetedVertex->numEdges; k++) {
-				struct edges_t *oEdge = &(oTargetedVertex->edges[k]);
-				struct edges_t *dEdge = &(dTargetedVertex->edges[k]);
-				duplicate_edge (dEdge, oEdge);						
-			}
-		}	
-	}	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to retrieve from the graph the edge instance associated to the
- * pathLink (pL)
- *
- *	@param pL
- *	@parma g
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct edges_t* get_edge_from_graph_by_linkId(struct pathLink_t* pL, struct graph_t* g) {
-	g_assert(pL);
-	g_assert(g);
-
-	for (gint i = 0; i < g->numVertices; i++) {
-		struct vertices_t* v = &(g->vertices[i]);
-		for (gint j = 0; j < v->numTargetedVertices; j++) {
-			struct targetNodes_t* tv = &(v->targetedVertices[j]);
-			for (gint k = 0; k < tv->numEdges; k++) {
-				struct edges_t* e = &(tv->edges[k]);
-				if (strcmp(e->linkId, pL->linkId) == 0) {
-					return e;
-				}
-			}		
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to retrieve from the graph the reverse edge (rev_e) associated to an edge (e)
- *
- *	@param e
- *	@parma g
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-struct edges_t* get_reverse_edge_from_the_graph(struct edges_t* e, struct graph_t* g) {
-	g_assert(e);
-	g_assert(g);
-
-	for (gint i = 0; i < g->numVertices; i++) {
-		struct vertices_t* v = &(g->vertices[i]);
-		// Check Route Element zNodeId with the v->verticeId
-		if (compare_node_id(&e->zNodeId, &v->verticeId) != 0)
-			continue;
-		// Check Route Element zNodeis with any of reachable targeted vertices from v
-		gboolean foundTargVert = FALSE;
-		gint indexTargVert = -1;
-		for (gint j = 0; j < v->numTargetedVertices; j++) {
-			struct targetNodes_t* tv = &(v->targetedVertices[j]);
-			if (compare_node_id(&e->aNodeId, &tv->tVertice) == 0)
-			{
-				foundTargVert = TRUE;
-				indexTargVert = j;
-				break;
-			}
-		}
-		if (foundTargVert == FALSE) {
-			 continue;
-		}			
-
-		// The targeted vertice is found, then check matching with the endpoints
-		struct targetNodes_t* tv = &(v->targetedVertices[indexTargVert]);
-		for (gint k = 0; k < tv->numEdges; k++) {
-			struct edges_t* rev_e = &(tv->edges[k]);
-			if ((strcmp(rev_e->aEndPointId, e->zEndPointId) == 0) &&
-				(strcmp(rev_e->zEndPointId, e->aEndPointId) == 0)) {
-				return rev_e;
-			}				
-		}
-	}
-	return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to reflect in the graph the assigned/allocated resources contained in the path p
- * 	considering the needs (e.g., bandwidth) of service s
- *
- *	@param p
- *	@param s
- *	@parma g
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
-/////////////////////////////////////////////////////////////////////////////////////////
-void allocate_graph_resources (struct path_t *p, struct service_t *s, struct graph_t *g)
-{
-	g_assert (p); g_assert (s); g_assert (g);
-	// Retrieve the requested bw by the service
-	struct path_constraints_t* pathCons = get_path_constraints(s);
-
-	for (gint i = 0; i < p->numPathLinks; i++) {
-		struct pathLink_t* pL = &(p->pathLinks[i]);
-		// get the edge associated to the linkId in the graph
-		struct edges_t* e = get_edge_from_graph_by_linkId(pL, g);
-		if (e == NULL) {
-			DEBUG_PC("The linkId: %s is NOT found in the Graph!!!", pL->linkId);
-			exit(-1);
-		}
-		//Update the availBw in the edge
-		gdouble resBw = e->availCap - pathCons->bwConstraint;
-		DEBUG_PC("Updating the Avail Bw @ edge/link: %s", e->linkId);
-		DEBUG_PC("Initial avaiCap @ e/link: %f, demanded Bw: %f, resulting Avail Bw: %f", e->availCap, pathCons->bwConstraint, resBw);
-		memcpy(&e->availCap, &resBw, sizeof(gdouble));
-		DEBUG_PC("Final e/link avail Bw: %f", e->availCap);	
-	}
-	g_free(pathCons);	
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to reflect in the graph the assigned/allocated resources contained in the reverse direction of the path p
- * 	considering the needs (e.g., bandwidth) of service s
- *
- *	@param p
- *	@param s
- *	@parma g
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void allocate_graph_reverse_resources(struct path_t* p, struct service_t * s, struct graph_t* g)
-{
-	g_assert(p); g_assert(s); g_assert(g);
-
-	struct path_constraints_t* pathCons = get_path_constraints(s);
-	for (gint i = 0; i < p->numPathLinks; i++) {
-		struct pathLink_t* pL = &(p->pathLinks[i]);
-		struct edges_t* e = get_edge_from_graph_by_linkId(pL, g);
-		if (e == NULL) {
-			DEBUG_PC("The linkId: %s is NOT found in the Graph!!!", pL->linkId);
-			exit(-1);
-		}
-		struct edges_t* rev_e = get_reverse_edge_from_the_graph(e, g);
-		if (rev_e == NULL) {
-			DEBUG_PC("the reverse edge of linkId: %s is NOT found in the Graph!!!", pL->linkId);
-			exit(-1);
-		}
-		//Update the availBw in the edge
-		gdouble resBw = rev_e->availCap - pathCons->bwConstraint;
-		DEBUG_PC("Updating the Avail Bw @ reverse edge/link: %s", rev_e->linkId);
-		DEBUG_PC("Initial avaiCap @ reverse edge e/link: %f, demanded Bw: %f, resulting Avail Bw: %f", rev_e->availCap, pathCons->bwConstraint, resBw);
-		memcpy(&rev_e->availCap, &resBw, sizeof(gdouble));
-		DEBUG_PC("Final reverse edge e/link avail Bw: %f", rev_e->availCap);
-	}
-	g_free(pathCons);
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Function used to printall the computed paths for the requested network connectivity services
- *
- *	@param routeList
- *
- * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void print_path_connection_list(struct compRouteOutputList_t* routeList) {
-	g_assert(routeList);
-	for (gint i = 0; i < routeList->numCompRouteConnList; i++) {
-		DEBUG_PC("==================== Service instance: %d ===================", i);
-		struct compRouteOutput_t* rO = &(routeList->compRouteConnection[i]);
-		DEBUG_PC("num service endpoints: %d", rO->num_service_endpoints_id);
-		struct serviceId_t* s = &(rO->serviceId);
-		DEBUG_PC("ContextId: %s, ServiceId: %s", s->contextId, s->service_uuid);
-		DEBUG_PC("ingress - %s[%s]", rO->service_endpoints_id[0].device_uuid, 
-			rO->service_endpoints_id[0].endpoint_uuid);
-		DEBUG_PC("egress - %s [%s]", rO->service_endpoints_id[1].device_uuid,
-			rO->service_endpoints_id[1].endpoint_uuid);
-
-		if (rO->noPathIssue == NO_PATH_CONS_ISSUE) {
-			DEBUG_PC("NO PATH SUCCESSFULLY COMPUTED");
-			continue;
-		}
-		// Path
-		DEBUG_PC("Number of paths: %d", rO->numPaths);
-		for (gint j = 0; j < rO->numPaths; j++) {
-			struct path_t* p = &(rO->paths[j]);
-			print_path_t(p);
-		}
-	}
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief update statistics for the path computation operations
- *
- *  @param routeConnList
- *	@param d
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct timeval d, gint numSuccesPathComp, gint numPathCompIntents) {
-	g_assert(routeConnList);
-
-	total_path_comp_time.tv_sec = total_path_comp_time.tv_sec + d.tv_sec;
-	total_path_comp_time.tv_usec = total_path_comp_time.tv_usec + d.tv_usec;
-	total_path_comp_time = tv_adjust(total_path_comp_time);
-
-	gdouble path_comp_time_msec = (((total_path_comp_time.tv_sec) * 1000) + ((total_path_comp_time.tv_usec) / 1000));
-	gdouble av_alg_comp_time = ((path_comp_time_msec / numSuccesPathComp));
-	DEBUG_PC("\t --- STATS PATH COMP ----");
-	DEBUG_PC("Succesfully Comp: %d | Path Comp Requests: %d", numSuccesPathComp, numPathCompIntents);
-	DEBUG_PC("AV. PATH COMP ALG. TIME: %f ms", av_alg_comp_time);
-
-	gint i = 0;
-	for (GList* listnode = g_list_first(serviceList);
-		listnode;
-		listnode = g_list_next(listnode), i++) {
-		struct service_t* s = (struct service_t*)(listnode->data);
-		char* eptr;
-		for (gint j = 0; j < s->num_service_constraints; j++) {
-			struct constraint_t* constraints = &(s->constraints[j]);
-			if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) {
-				totalReqBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr));
-			}
-		}
-	}
-
-	for (gint k = 0; k < routeConnList->numCompRouteConnList; k++) {
-		struct compRouteOutput_t* rO = &(routeConnList->compRouteConnection[k]);
-		if (rO->noPathIssue == NO_PATH_CONS_ISSUE) {
-			continue;
-		}
-		// Get the requested service bw bound to that computed path
-		struct path_t* p = &(rO->paths[0]);
-		struct service_t* s = get_service_for_computed_path(rO->serviceId.service_uuid);
-		if (s == NULL) {
-			DEBUG_PC("Weird the service associated to a path is not found");
-			exit(-1);
-		}
-		for (gint l = 0; l < s->num_service_constraints; l++) {
-			struct constraint_t* constraints = &(s->constraints[l]);
-			char* eptr;
-			if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) {
-				totalServedBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr));
-			}
-		}
-	}
-	gdouble avServedRatio = totalServedBw / totalReqBw;
-	DEBUG_PC("AV. Served Ratio: %f", avServedRatio);
-	gdouble avBlockedBwRatio = (gdouble)(1.0 - avServedRatio);
-	DEBUG_PC("AV. BBE: %f", avBlockedBwRatio);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate active service	path
- *
- *  @param actServPath
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_active_service_path(struct activeServPath_t* actServPath) {
-	g_assert(actServPath);
-	g_free(actServPath);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate active service
- *
- *  @param actService
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_active_service(struct activeService_t* actService) {
-	g_assert(actService);
-	g_list_free_full(g_steal_pointer(&actService->activeServPath), (GDestroyNotify)destroy_active_service_path);
-	g_free(actService);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate a requested service 
- *
- *  @param s
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_requested_service(struct service_t* s) {
-	g_assert(s);
-	g_free(s);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate a device
- *
- *  @param d
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_device(struct device_t* d) {
-	g_assert(d);
-	g_free(d);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate a link	from the linkList
- *
- *  @param d
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_link(struct link_t* l) {
-	g_assert(l);
-	g_free(l);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Eliminate a context from the contextSet
- *
- *  @param d
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void destroy_context(struct context_t* c) {
-	g_assert(c);
-	g_free(c);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief Excecution Dijkstra algorithm
- *
- *  @param srcMapIndex
- *  @param dstMapIndex
- *	@param g
- *	@param s
- *  @param mapNodes
- *  @param SN
- *  @param RP
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void dijkstra(gint srcMapIndex, gint dstMapIndex, struct graph_t* g, struct service_t* s, 
-	struct map_nodes_t* mapNodes, struct nodes_t* SN, struct compRouteOutputItem_t* RP,
-	guint arg) {
-	g_assert(s);g_assert(g);
-
-	// Set params into mapNodes related to the source nodes of the request
-	mapNodes->map[srcMapIndex].distance = 0.0;
-	mapNodes->map[srcMapIndex].latency = 0.0;
-	mapNodes->map[srcMapIndex].avaiBandwidth = 0.0;
-	mapNodes->map[srcMapIndex].power = 0.0;
-
-	// Initialize the set Q and S
-	GList *S = NULL, *Q = NULL;
-	gint indexVertice = -1;
-
-	//  Add the source into the Q
-	struct nodeItem_t* nodeItem = g_malloc0(sizeof(struct nodeItem_t));
-	if (nodeItem == NULL) {
-		DEBUG_PC("memory allocation failed\n");
-		exit(-1);
-	}
-	// initialize some nodeItem attributes
-	nodeItem->distance = 0.0;
-	nodeItem->latency = 0.0;
-	nodeItem->power = 0.0;
-	duplicate_node_id(&mapNodes->map[srcMapIndex].verticeId, &nodeItem->node);
-
-	// Select the optimization process
-	if (arg & ENERGY_EFFICIENT_ARGUMENT)
-		Q = g_list_insert_sorted(Q, nodeItem, sort_by_energy);
-	// more "if" according to different optimization criteria ...
-	else
-		Q = g_list_insert_sorted(Q, nodeItem, sort_by_distance);
-
-	// Check whether there is spurNode (SN) and rootPath (RP)
-	if (SN != NULL && RP != NULL) {
-		struct routeElement_t* re;
-		for (gint j = 0; j < RP->numRouteElements; j++) {
-			// Get the source and target Nodes of the routeElement within the rootPath
-			re = &RP->routeElement[j];
-			DEBUG_PC("root Link: aNodeId: %s (%s) --> zNodeiId: %s (%s)", re->aNodeId.nodeId, re->aEndPointId, re->zNodeId.nodeId, re->zEndPointId);
-
-			// if ingress of the root link (aNodeId) is the spurNode, then stops
-			if (compare_node_id(&re->aNodeId, SN) == 0) {
-				DEBUG_PC("root Link: aNodeId: %s and spurNode: %s -- stop exploring the rootPath (RP)", re->aNodeId.nodeId, SN->nodeId);
-				break;
-			}
-			// Extract from Q
-			GList* listnode = g_list_first(Q);
-			struct nodeItem_t* node = (struct nodeItem_t*)(listnode->data);
-			Q = g_list_remove(Q, node);
-
-			//DEBUG_RL_RA ("Exploring node %s", node->node.nodeId);
-			indexVertice = graph_vertice_lookup(node->node.nodeId, g);
-			g_assert(indexVertice >= 0);
-
-			// Get the indexTargetedVertice
-			gint indexTVertice = -1;
-			indexTVertice = graph_targeted_vertice_lookup(indexVertice, re->zNodeId.nodeId, g);
-			gint done = check_link(node, indexVertice, indexTVertice, g, s, &S, &Q, mapNodes, arg);
-			(void)done;
-			// Add to the S list
-			S = g_list_append(S, node);
-		}
-		// Check that the first node in Q set is SpurNode, otherwise something went wrong ...
-		if (compare_node_id(&re->aNodeId, SN) != 0) {
-			//DEBUG_PC ("root Link: aNodeId: %s is NOT the spurNode: %s -- something wrong", re->aNodeId.nodeId, SN->nodeId);
-			g_list_free_full(g_steal_pointer(&S), g_free);
-			g_list_free_full(g_steal_pointer(&Q), g_free);
-			return;
-		}
-	}
-
-	while (g_list_length(Q) > 0) {
-		//Extract from Q set
-		GList* listnode = g_list_first(Q);
-		struct nodeItem_t* node = (struct nodeItem_t*)(listnode->data);
-		Q = g_list_remove(Q, node);
-		DEBUG_PC("Q length: %d", g_list_length(Q));
-		DEBUG_PC("DeviceId: %s", node->node.nodeId);
-
-		// visit all the links from u within the graph
-		indexVertice = graph_vertice_lookup(node->node.nodeId, g);
-		g_assert(indexVertice >= 0);
-
-		// Check the targeted vertices from u
-		for (gint i = 0; i < g->vertices[indexVertice].numTargetedVertices; i++) {
-			gint done = check_link(node, indexVertice, i, g, s, &S, &Q, mapNodes, arg);
-			(void)done;
-		}
-		// Add node into the S Set
-		S = g_list_append(S, node);
-		//DEBUG_PC ("S length: %d", g_list_length (S));              
-	}
-	g_list_free_full(g_steal_pointer(&S), g_free);
-	g_list_free_full(g_steal_pointer(&Q), g_free);
-	return;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief KSP computation using Dijkstra algorithm
- *
- *  @param pred
- *  @param g
- *	@param s
-  *	@param SN
- *	@param RP
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-gint ksp_comp(struct pred_t* pred, struct graph_t* g, struct service_t* s,
-	struct nodes_t* SN, struct compRouteOutputItem_t* RP, 
-	struct map_nodes_t* mapNodes, guint arg) {
-	g_assert(pred); g_assert(g); g_assert(s);
-
-	DEBUG_PC("Source: %s -- Destination: %s", s->service_endpoints_id[0].device_uuid, s->service_endpoints_id[1].device_uuid);
-
-	// Check the both ingress src and dst endpoints are in the graph
-	gint srcMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[0].device_uuid, mapNodes);
-	if (srcMapIndex == -1) {
-		DEBUG_PC("ingress DeviceId: %s NOT in the graph", s->service_endpoints_id[0].device_uuid);
-		return -1;
-	}
-	
-	gint dstMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
-	if (dstMapIndex == -1) {
-		DEBUG_PC("egress DeviceId: %s NOT in the graph", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-
-	//DEBUG_PC("srcMapIndex: %d (node: %s)", srcMapIndex, mapNodes->map[srcMapIndex].verticeId.nodeId);
-	//DEBUG_PC("dstMapIndex: %d (node: %s)", dstMapIndex, mapNodes->map[dstMapIndex].verticeId.nodeId);
-
-	// Compute the shortest path route
-	dijkstra(srcMapIndex, dstMapIndex, g, s, mapNodes, SN, RP, arg);
-
-	// Check that a feasible solution in term of latency and bandwidth is found
-	gint map_dstIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
-	struct map_t* dest_map = &mapNodes->map[map_dstIndex];
-	if (!(dest_map->distance < INFINITY_COST)) {
-		DEBUG_PC("destination: %s NOT reachable", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-
-	DEBUG_PC("AvailBw @ %s is %f", dest_map->verticeId.nodeId, dest_map->avaiBandwidth);
-	// Check that the computed available bandwidth is larger than 0.0
-	if (dest_map->avaiBandwidth <= (gfloat)0.0) {
-		DEBUG_PC("dst: %s NOT REACHABLE", s->service_endpoints_id[1].device_uuid);
-		return -1;
-	}
-	DEBUG_PC("dst: %s REACHABLE", s->service_endpoints_id[1].device_uuid);
-	// Handle predecessors
-	build_predecessors(pred, s, mapNodes);
-	return 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief set the path parameters (e.g., latency, cost, power, ...) to an under-constructed
- * path from the computed map vertex
- *
- *  @param p
- *  @param mapV
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void set_path_attributes(struct compRouteOutputItem_t* p, struct map_t* mapV) {
-	g_assert(p); g_assert(mapV);
-	memcpy(&p->cost, &mapV->distance, sizeof(gdouble));
-	memcpy(&p->availCap, &mapV->avaiBandwidth, sizeof(mapV->avaiBandwidth));
-	memcpy(&p->delay, &mapV->latency, sizeof(mapV->latency));
-	memcpy(&p->power, &mapV->power, sizeof(gdouble));
-	return;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-/**
- * 	@file pathComp_tools.c
- * 	@brief K-CSPF algorithm execution (YEN algorithm)
- *
- *  @param s
- *  @param path
- *  @param g
- *  @param optimization_flag
- *
- *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
- *	@date 2022
- */
- /////////////////////////////////////////////////////////////////////////////////////////
-void alg_comp(struct service_t* s, struct compRouteOutput_t* path, struct graph_t* g, guint arg) {
-	g_assert(s); g_assert(path); g_assert(g);
-
-	// create map of devices/nodes to handle the path computation using the context
-	struct map_nodes_t* mapNodes = create_map_node();
-	build_map_node(mapNodes, g);
-
-	// predecessors to store the computed path    
-	struct pred_t* predecessors = create_predecessors();
-	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
-	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
-
-	// Compute the 1st KSP path
-	gint done = ksp_comp(predecessors, g, s, NULL, NULL, mapNodes, arg);
-	if (done == -1) {
-		DEBUG_PC("NO PATH for %s[%s] --> %s[%s]", iEp->device_uuid, iEp->endpoint_uuid, eEp->device_uuid, eEp->endpoint_uuid);
-		comp_route_connection_issue_handler(path, s);
-		g_free(mapNodes); g_free(predecessors);
-		return;
-	}
-
-	// Construct the path from the computed predecessors
-	struct compRouteOutputItem_t* p = create_path_item();
-	//print_predecessors(predecessors);
-	build_path(p, predecessors, s);
-	gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
-	struct map_t* dst_map = &mapNodes->map[indexDest];
-	// Get the delay and cost
-	set_path_attributes(p, dst_map);		
-
-	// Add the computed path, it may be a not feasible path, but at the end it is
-	// checked all the feasible paths, and select the first one
-	print_path(p);
-	
-	// Copy the serviceId
-	copy_service_id(&path->serviceId, &s->serviceId);
-	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
-	for (gint i = 0; i < s->num_service_endpoints_id; i++) {
-		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
-		struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
-		copy_service_endpoint_id(oEp, iEp);
-	}
-	path->num_service_endpoints_id = s->num_service_endpoints_id;
-
-	DEBUG_PC("COMPUTE UP TO K Feasible Paths A[%d]", MAX_KSP_VALUE);	
-	// Create A and B sets of paths to handle the YEN algorithm
-	struct path_set_t *A = create_path_set(), *B = create_path_set();
-	// Add 1st Computed path into A->paths[0]	
-	duplicate_path(p, &A->paths[0]);
-	A->numPaths++;
-	g_free(predecessors); g_free(p);
-	for (gint k = 1; k < MAX_KSP_VALUE; k++) {
-		DEBUG_PC("*************************** kth (%d) ***********************************", k);
-		struct compRouteOutputItem_t* p = create_path_item();
-		duplicate_path(&A->paths[k - 1], p);
-		// The spurNode ranges from near-end node of the first link to the near-end of the last link forming the kth path
-		gint i = 0;
-		struct compRouteOutputItem_t* rootPath = create_path_item();
-		for (i = 0; i < p->numRouteElements; i++) {
-			struct nodes_t *spurNode = create_node(), *nextSpurNode = create_node();
-			struct routeElement_t* re = &(p->routeElement[i]);
-			// Create predecessors to store the computed path
-			struct pred_t* predecessors = create_predecessors();
-			// Clear previous mapNodes, i.e. create it again
-			g_free(mapNodes);
-			mapNodes = create_map_node();
-			build_map_node(mapNodes, g);
-			struct nodes_t* n = &re->aNodeId;
-			duplicate_node_id(n, spurNode);
-			n = &re->zNodeId;
-			duplicate_node_id(n, nextSpurNode);
-			DEBUG_PC("spurNode: %s --> nextSpurNode: %s", spurNode->nodeId, nextSpurNode->nodeId);
-
-			// rootPath contains a set of links of A[k-1] from the source Node till the SpurNode -> NextSpurNode
-			// Example: A[k-1] = {L1, L2, L3, L4}, i.e. " Node_a -- L1 --> Node_b -- L2 --> Node_c -- L3 --> Node_d -- L4 --> Node_e "
-			// E.g., for the ith iteration if the spurNode = Node_c and NextSpurNode = Node_d; then rootPath = {L1, L2, L3}			
-			add_routeElement_path_back(re, rootPath);
-			DEBUG_PC("\n");
-			DEBUG_PC("^^^^^^^rootPath^^^^^^^");
-			print_path(rootPath);
-
-			// For all existing and computed paths p in A check if from the source to the NextSpurNode
-			// the set of links matches with those contained in the rootPath
-			// If YES, remove from the auxiliary graph the next link in p from NextSpurNode
-			// Otherwise do nothing 
-			struct graph_t* gAux = create_graph();
-			duplicate_graph(g, gAux);
-			// Modified graph
-			modify_targeted_graph(gAux, A, rootPath, spurNode);
-
-			// Trigger the computation of the path from src to dst constrained to traverse all the links from src 
-			// to spurNode contained into rootPath over the resulting graph			
-			if (ksp_comp(predecessors, gAux, s, spurNode, rootPath, mapNodes, arg) == -1) {
-				DEBUG_PC("FAILED SP from %s via spurNode: %s to %s", iEp->device_uuid, spurNode->nodeId, eEp->device_uuid);
-				g_free(nextSpurNode); g_free(spurNode);
-				g_free(gAux); g_free(predecessors);
-				continue;
-			}
-			DEBUG_PC("SUCCESFUL SP from %s via spurNode: %s to %s", iEp->device_uuid, spurNode->nodeId, eEp->device_uuid);
-			// Create the node list from the predecessors
-			struct compRouteOutputItem_t* newKpath = create_path_item();
-			build_path(newKpath, predecessors, s);
-			DEBUG_PC("new K (for k: %d) Path is built", k);
-			gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
-			struct map_t* dst_map = &mapNodes->map[indexDest];
-			set_path_attributes(newKpath, dst_map);
-			DEBUG_PC("New PATH (@ kth: %d) ADDED to B[%d] - {Path Cost: %f, e2e latency: %f, bw: %f, Power: %f ", k, B->numPaths, newKpath->cost, 
-													newKpath->delay, newKpath->availCap, newKpath->power);
-			// Add the computed kth SP to the heap B
-			duplicate_path(newKpath, &B->paths[B->numPaths]);
-			B->numPaths++;
-			DEBUG_PC("Number of B paths: %d", B->numPaths);
-
-			g_free(newKpath); g_free(nextSpurNode); g_free(spurNode);
-			g_free(gAux); g_free(predecessors);
-		}
-		// If B is empty then stops
-		if (B->numPaths == 0) {
-			DEBUG_PC("B does not have any path ... the stops kth computation");
-			break;
-		}
-
-		// Sort the potential B paths according to different optimization parameters
-		sort_path_set(B, arg);
-		// Add the lowest path into A[k]		
-		DEBUG_PC("-------------------------------------------------------------");
-		DEBUG_PC("Append SP for B[0] to A[%d] --- Cost: %f, Latency: %f, Power: %f", A->numPaths, B->paths[0].cost, 
-																				B->paths[0].delay, B->paths[0].power);
-		duplicate_path(&B->paths[0], &A->paths[A->numPaths]);
-		A->numPaths++;
-		DEBUG_PC("A Set size: %d", A->numPaths);
-		DEBUG_PC("-------------------------------------------------------------");
-
-		// Remove/Pop front element from the path set B (i.e. remove B[0])
-		pop_front_path_set(B);
-		DEBUG_PC("B Set Size: %d", B->numPaths);
-	}
-
-	// Copy the serviceId
-	copy_service_id(&path->serviceId, &s->serviceId);
-	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
-	for (gint m = 0; m < s->num_service_endpoints_id; m++) {
-		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[m]);
-		struct service_endpoints_id_t* oEp = &(s->service_endpoints_id[m]);
-		copy_service_endpoint_id(oEp, iEp);
-	}
-
-	// Print all the paths i A
-	for (gint h = 0; h < A->numPaths; h++) {
-		DEBUG_PC("================== A[%d] =======================", h);
-		print_path(&A->paths[h]);
-	}
-	DEBUG_PC("Number of paths: %d", path->numPaths);
-	// For all the computed paths in A, pick the one being feasible wrt the service constraints
-	for (gint ksp = 0; ksp < A->numPaths; ksp++) {
-		if (ksp >= MAX_KSP_VALUE) {
-			DEBUG_PC("Number Requested paths (%d) REACHED - STOP", ksp);
-			break;
-		}
-		gdouble feasibleRoute = check_computed_path_feasability(s, &A->paths[ksp]);
-		if (feasibleRoute == TRUE) {
-			DEBUG_PC("A[%d] available: %f, pathCost: %f; latency: %f, Power: %f", ksp, A->paths[ksp].availCap, A->paths[ksp].cost, A->paths[ksp].delay, A->paths[ksp].power);
-			struct compRouteOutputItem_t* pathaux = &A->paths[ksp];
-			path->numPaths++;
-			struct path_t* targetedPath = &path->paths[path->numPaths - 1];
-			duplicate_path_t(pathaux, targetedPath);
-			print_path_t(targetedPath);
-			remove_path_set(A);
-			remove_path_set(B);
-			return;
-		}
-	}
-	remove_path_set(A);
-	remove_path_set(B);
-	// No paths found --> Issue	
-	DEBUG_PC("K-SP failed!!!");
-	comp_route_connection_issue_handler(path, s);
-	return;
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	# Copyright 2022 Centre Tecnològic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Author: CTTC/CERCA PONS RU Ricardo Martínez (ricardo.martinez@cttc.es)
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h> 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <glib.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <strings.h>
+#include <time.h>
+#include <math.h>
+#include <fcntl.h>
+#include <uuid/uuid.h>
+#include <errno.h>
+
+#include "pathComp_log.h"
+#include "pathComp.h"
+#include "pathComp_tools.h"
+
+gint numPathCompIntents = 0;  // number of events triggering the path computation
+//gint numSuccesPathComp = 0; // number of events resulting in succesfully path computations fulfilling the constraints
+struct timeval total_path_comp_time;
+gdouble totalReqBw = 0.0;
+gdouble totalServedBw = 0.0;
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function for time processing
+ *
+ * 	@param a
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ ////////////////////////////////////////////////////////////////////////////////////////
+struct timeval tv_adjust (struct timeval a) {
+	while (a.tv_usec >= 1000000) {
+		a.tv_usec -= 1000000;
+		a.tv_sec++;
+	}
+	while (a.tv_usec < 0) {
+		a.tv_usec += 1000000;
+		a.tv_sec--;
+	}
+	return a;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief friendly function to copy safely strings
+ *
+ * 	@param dst
+ *  @param src
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ ////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_string(gchar* dst, gchar* src) {
+	g_assert(dst); g_assert(src);
+	strcpy(dst, src);
+	dst[strlen(dst)] = '\0';
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to print the computed the path
+ *
+ *	@param path
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void print_path (struct compRouteOutputItem_t *p) {
+	g_assert(p);	
+	DEBUG_PC ("=========== COMPUTED PATH =======================");
+	DEBUG_PC ("E2E Avail. Bw: %f, Latency: %f, Cost: %f, Consumed Power (in W): %f", p->availCap, p->delay, p->cost, p->power);
+	for (gint k = 0; k < p->numRouteElements; k++) {
+		DEBUG_PC ("%s[%s] --> %s[%s]", p->routeElement[k].aNodeId.nodeId, p->routeElement[k].aEndPointId,
+																p->routeElement[k].zNodeId.nodeId, p->routeElement[k].zEndPointId);
+		DEBUG_PC("\t linkId: %s", p->routeElement[k].linkId);
+		DEBUG_PC("\t aTopologyId: %s", p->routeElement[k].aTopologyId);
+		DEBUG_PC("\t zTopologyId: %s", p->routeElement[k].zTopologyId);
+	}
+	DEBUG_PC ("==================================================================");		
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to print the output path formed by link Ids
+ *
+ *	@param p
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_path_t(struct path_t* p) {
+	g_assert(p);
+	DEBUG_PC(" ============ COMPUTED OUTPUT PATH =================");
+	DEBUG_PC("Path AvailBw: %f, Cost: %f, Latency: %f, Power: %f", p->path_capacity.value,
+			p->path_cost.cost_value, p->path_latency.fixed_latency, p->path_power.power);
+	DEBUG_PC("number of links of path %d", p->numPathLinks);
+	for (gint k = 0; k < p->numPathLinks; k++) {
+		DEBUG_PC("Link: %s", p->pathLinks[k].linkId);
+		for (gint l = 0; l < p->pathLinks[k].numLinkTopologies; l++) {
+			DEBUG_PC("end Link [%d] TopologyId: %s", l, p->pathLinks[k].linkTopologies[l].topologyId);
+		}
+		DEBUG_PC(" ContextId: %s", p->pathLinks[k].topologyId.contextId);
+		DEBUG_PC(" TopologyUUid: %s", p->pathLinks[k].topologyId.topology_uuid);
+		DEBUG_PC(" aDeviceId: %s", p->pathLinks[k].aDeviceId);
+		DEBUG_PC(" aEndpointId: %s", p->pathLinks[k].aEndPointId);
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used allocate memory for struct path_t
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ ////////////////////////////////////////////////////////////////////////////////////////
+struct path_t* create_path() {
+	struct path_t* p = g_malloc0(sizeof(struct path_t));
+	if (p == NULL) {
+		DEBUG_PC("Memory allocation failure");
+		exit(-1);
+	}
+	return(p);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Returns the char (36 bytes) format of a uuid
+ *
+ *	@param uuid
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+gchar* get_uuid_char(uuid_t uuid) {
+	gchar* uuidChar = g_malloc0(16); // uuid has 36 chars
+	if (uuidChar == NULL) {
+		DEBUG_PC("Memory Allocation failure");
+		exit(-1);
+	}
+	uuid_unparse(uuid, (char *)uuidChar);
+	return uuidChar;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Makes a copy of the service identifier (including the context)
+ *
+ *	@param o
+ *  @param i
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void copy_service_id(struct serviceId_t* o, struct serviceId_t* i) {
+	g_assert(o); g_assert(i);
+	memcpy(o->contextId, i->contextId, sizeof(i->contextId));
+	memcpy(o->service_uuid, i->service_uuid, sizeof(i->service_uuid));
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Makes a copy of the service endpoint identifier (including the topology (contect and topology id), device and endpoint (port))
+ *
+ *	@param oEp
+ *  @param iEp
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void copy_service_endpoint_id(struct service_endpoints_id_t* oEp, struct service_endpoints_id_t* iEp) {
+	g_assert(oEp); g_assert(iEp);
+
+	// copy topology information
+	memcpy(oEp->topology_id.contextId, iEp->topology_id.contextId, sizeof(iEp->topology_id.contextId));
+	memcpy(oEp->topology_id.topology_uuid, iEp->topology_id.topology_uuid, sizeof(iEp->topology_id.topology_uuid));
+
+	// copy the endpoint
+	memcpy(oEp->device_uuid, iEp->device_uuid, sizeof(iEp->device_uuid));
+	memcpy(oEp->endpoint_uuid, iEp->endpoint_uuid, sizeof(iEp->endpoint_uuid));
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief From the set of contexts, it is returned the graph associated to that context matching
+ *	with the passed contextId.
+ *
+ *	@param Set
+ *  @param contextId
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct graph_t* get_graph_by_contextId(GList* set, gchar* contextId) {
+	g_assert(contextId);
+
+	// iterate over the set of context. Pick the one matching with contextId, and return the graph.
+	// If not found, return NULL
+	struct graph_t* g = NULL;
+	for (GList *ln = g_list_first(set);
+		ln;
+		ln = g_list_next(ln)){
+		struct context_t* context = (struct context_t*)(ln->data);
+		if (strcmp(context->contextId, contextId) == 0) {
+			g = &(context->g);
+			return g;
+		}
+	}
+	return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Process the service constraint and maps them into the path constraints
+ * to be fulfilled
+ *
+ *  @param path_constraints
+ *  @param s
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct path_constraints_t * get_path_constraints(struct service_t* s) {
+	g_assert(s);
+	
+	struct path_constraints_t* path_constraints = g_malloc0(sizeof(struct path_constraints_t));
+	if (path_constraints == NULL) {
+		DEBUG_PC("Memory Allocation Failure");
+		exit(-1);
+	}
+
+	char* eptr;
+	for (gint i = 0; i < s->num_service_constraints; i++) {
+		struct constraint_t* constraint = &(s->constraints[i]);;
+		if (strncmp((const char*)constraint->constraint_type, "bandwidth", 9) == 0) {
+			path_constraints->bwConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
+			path_constraints->bw = TRUE;
+			//DEBUG_PC("Path Constraint Bw: %f", path_constraints->bwConstraint);
+		}
+		if (strncmp((const char*)constraint->constraint_type, "cost", 4) == 0) {
+			path_constraints->costConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
+			path_constraints->cost = TRUE;
+			//DEBUG_PC("Path Constraint Cost: %f", path_constraints->costConstraint);
+		}
+		if (strncmp((const char*)constraint->constraint_type, "latency", 7) == 0) {
+			path_constraints->latencyConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
+			path_constraints->latency = TRUE;
+			//DEBUG_PC("Path Constraint Latency: %f", path_constraints->latencyConstraint);
+		}
+		if (strncmp((const char*)constraint->constraint_type, "energy", 6) == 0) {
+			path_constraints->energyConstraint = (gdouble)(strtod((char*)constraint->constraint_value, &eptr));
+			path_constraints->energy = TRUE;
+			//DEBUG_PC("Path Constraint Energy: %f", path_constraints->energyConstraint);
+		}
+	}
+	return path_constraints;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Creates the predecessors to keep the computed path
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct pred_t * create_predecessors () {
+	struct pred_t *predecessors = g_malloc0 (sizeof (struct pred_t));
+	if (predecessors == NULL) {
+		DEBUG_PC ("memory allocation failed\n");
+		exit (-1);
+	}   
+	return predecessors;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief create edge
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct edges_t* create_edge() {
+	struct edges_t* e = g_malloc0(sizeof(struct edges_t));
+	if (e == NULL) {
+		DEBUG_PC("Memory allocation failed\n");
+		exit(-1);
+	}
+	return e;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Prints the list of the predecessors for a given computed Shortest Path
+ *
+ *	@param p 
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void print_predecessors (struct pred_t *p)
+{
+	g_assert (p);
+	DEBUG_PC ("Number of Predecessors: %d", p->numPredComp);
+	for (gint i = 0; i < p->numPredComp; i++) {
+		struct pred_comp_t *pComp = &(p->predComp[i]);
+		DEBUG_PC ("deviceId: %s", pComp->v.nodeId);		
+		struct edges_t *e = &(pComp->e);
+		DEBUG_PC("Edge[#%d] (linkId): %s", i, e->linkId);
+		DEBUG_PC ("\t %s[%s] ===>", e->aNodeId.nodeId, e->aEndPointId);
+		DEBUG_PC("\t %s[%s]", e->zNodeId.nodeId, e->zEndPointId);
+		DEBUG_PC("\t aTopologyId: %s", e->aTopologyId);
+		DEBUG_PC("\t zTopologyId: %s", e->zTopologyId);
+	}	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Builds the list of predecessors for the request destination using the computed Shortest Path
+ *	being stored in map
+ *
+ *	@param p 
+ *	@param s
+ *	@param map
+ *	
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void build_predecessors (struct pred_t *p, struct service_t *s, struct map_nodes_t *map) {
+	g_assert (p); g_assert (s); g_assert (map);
+	
+	struct nodes_t *v = create_node();
+	duplicate_string(v->nodeId, s->service_endpoints_id[1].device_uuid);
+	
+	struct edges_t *e = create_edge();	
+	get_edge_from_map_by_node (e, v, map);
+			
+	// Get u (being source of edge e)
+	struct nodes_t u;	
+	duplicate_node_id (&e->aNodeId, &u);
+		
+	// Add to the predecessors list
+	struct pred_comp_t *pred = &(p->predComp[p->numPredComp]);
+	duplicate_node_id (&u, &pred->v);	
+	struct edges_t *e1 = &(pred->e);	
+	duplicate_edge (e1, e);
+	p->numPredComp++;	
+	// Back-trace edges till reaching the srcPEId
+	struct nodes_t* srcNode = create_node();
+	duplicate_string(srcNode->nodeId, s->service_endpoints_id[0].device_uuid);
+
+	while (compare_node_id (&u, srcNode) != 0) 	{		
+		duplicate_node_id (&u, v);
+		get_edge_from_map_by_node (e, v, map);		
+		// Get the u (being source of edge e)		
+		duplicate_node_id (&e->aNodeId, &u);		
+		// Get the new predecessor
+		struct pred_comp_t *pred = &p->predComp[p->numPredComp];			
+		// Add to the predecessors list					
+		duplicate_node_id (&u, &pred->v);		
+		struct edges_t *e1 = &(pred->e);
+		duplicate_edge (e1, e);
+		p->numPredComp++;		
+	}
+	print_predecessors (p);
+    g_free (e); g_free(v); g_free(srcNode);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief It creates a struct nodes_t
+ *
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct nodes_t * create_node ()
+{
+	struct nodes_t *n = g_malloc0 (sizeof (struct nodes_t));
+	if (n == NULL) {
+		DEBUG_PC ("memory allocation problem");
+		exit (-1);
+	}
+	return n;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief It creates a routeElement_t
+ *
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct routeElement_t * create_routeElement () {
+	struct routeElement_t *rE = g_malloc0 (sizeof (struct routeElement_t));
+	if (rE == NULL)	{
+		DEBUG_PC ("memory allocation problem");
+		exit (-1);		
+	}
+	return rE;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief copy node ids
+ *
+ *	@param src
+ *  @param dst
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_node_id (struct nodes_t *src, struct nodes_t *dst) {	
+	g_assert (src);
+	g_assert (dst);	
+	//DEBUG_PC ("Duplicate nodeId for %s", src->nodeId);	
+	strcpy (dst->nodeId, src->nodeId);	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief compares a pair of node Ids
+ *
+ *	@param a
+ *  @param b
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint compare_node_id (struct nodes_t *a, struct nodes_t *b) {
+	g_assert (a);
+	g_assert (b);	
+	return (memcmp (&a->nodeId, b->nodeId, strlen (b->nodeId)));	
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief duplicate two routeElement_t
+ *
+ *	@param src
+ *  @param dst
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_routeElement (struct routeElement_t *src, struct routeElement_t *dst)
+{
+	g_assert (src);
+	g_assert (dst);
+	
+	duplicate_node_id (&(src->aNodeId), &(dst->aNodeId));
+	duplicate_node_id (&(src->zNodeId), &(dst->zNodeId));
+	duplicate_string(dst->aEndPointId, src->aEndPointId);
+	duplicate_string(dst->zEndPointId, src->zEndPointId);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief duplicate two edges
+ *
+ *	@param e1 (destination)
+ *  @param e2 (source)
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_edge (struct edges_t *e1, struct edges_t *e2) {
+	g_assert (e1); g_assert (e2);
+		
+	duplicate_node_id (&e2->aNodeId, &e1->aNodeId);
+	duplicate_node_id (&e2->zNodeId, &e1->zNodeId);
+	//DEBUG_PC ("e->aNodeId: %s --->  e->zNodeId: %s", e1->aNodeId.nodeId, e1->zNodeId.nodeId);
+	duplicate_string(e1->aEndPointId, e2->aEndPointId);
+	duplicate_string(e1->zEndPointId, e2->zEndPointId);
+	duplicate_string(e1->linkId, e2->linkId);
+	duplicate_string(e1->interDomain_localId, e2->interDomain_localId);
+	duplicate_string(e1->interDomain_remoteId, e2->interDomain_remoteId);
+	duplicate_string(e1->aTopologyId, e2->aTopologyId);
+	duplicate_string(e1->zTopologyId, e2->zTopologyId);
+	
+	e1->unit = e2->unit;
+	memcpy(&e1->totalCap, &e2->totalCap, sizeof(gdouble));
+	memcpy(&e1->availCap, &e2->availCap, sizeof(gdouble));
+
+	memcpy (&e1->cost, &e2->cost, sizeof (gdouble));
+    memcpy (&e1->delay, &e2->delay, sizeof (gdouble));
+	memcpy(&e1->energy, &e2->energy, sizeof(gdouble));
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Duplicate path 
+ *
+ *	@param a - original
+ *  @param b - copy
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_path (struct compRouteOutputItem_t *a, struct compRouteOutputItem_t *b) {		
+	g_assert (a); 	g_assert (b);
+	memcpy(&b->availCap, &a->availCap, sizeof (gdouble));		
+	memcpy(&b->cost, &a->cost, sizeof(gdouble));	
+	memcpy(&b->delay, &a->delay, sizeof (gdouble));
+	memcpy(&b->power, &a->power, sizeof(gdouble));
+	b->numRouteElements = a->numRouteElements;
+	for (gint k = 0; k < a->numRouteElements; k++) {			
+		//DEBUG_PC ("aNodeId: %s // zNodeId: %s", a->routeElement[k].aNodeId.nodeId, a->routeElement[k].zNodeId.nodeId);
+		// aNodeId duplication
+		struct nodes_t *n1 = &(a->routeElement[k].aNodeId);
+		struct nodes_t *n2 = &(b->routeElement[k].aNodeId);			
+		duplicate_node_id (n1, n2);					
+		//zNodeId duplication
+		n1 = &(a->routeElement[k].zNodeId);
+		n2 = &(b->routeElement[k].zNodeId);			
+		duplicate_node_id (n1, n2);
+		duplicate_string(b->routeElement[k].aEndPointId, a->routeElement[k].aEndPointId);
+		duplicate_string(b->routeElement[k].zEndPointId, a->routeElement[k].zEndPointId);
+		duplicate_string(b->routeElement[k].linkId, a->routeElement[k].linkId);
+		duplicate_string(b->routeElement[k].aTopologyId, a->routeElement[k].aTopologyId);
+		duplicate_string(b->routeElement[k].zTopologyId, a->routeElement[k].zTopologyId);
+	}	
+	return;	
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Duplicate path from compRouteOutputItem_t to path_t
+ *
+ *	@param a - original
+ *  @param b - copy
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_path_t(struct compRouteOutputItem_t* a, struct path_t* b) {
+	g_assert(a); g_assert(b);
+
+	// transfer path characteristics ...
+	memcpy(&b->path_capacity.value, &a->availCap, sizeof(gdouble));
+	memcpy(&b->path_cost.cost_value, &a->cost, sizeof(gdouble));
+	memcpy(&b->path_latency.fixed_latency, &a->delay, sizeof(gdouble));
+	memcpy(&b->path_power.power, &a->power, sizeof(gdouble));
+
+	b->numPathLinks = a->numRouteElements;
+
+	for (gint k = 0; k < a->numRouteElements; k++) {
+		struct routeElement_t* rE = &(a->routeElement[k]);
+		struct pathLink_t* pL = &(b->pathLinks[k]);
+
+		// copy the aDeviceId and aEndpointId, zDeviceId and zEndPointId
+		duplicate_string(pL->aDeviceId, rE->aNodeId.nodeId);
+		duplicate_string(pL->zDeviceId, rE->zNodeId.nodeId);
+		duplicate_string(pL->aEndPointId, rE->aEndPointId);
+		duplicate_string(pL->zEndPointId, rE->zEndPointId);
+
+		duplicate_string(pL->topologyId.topology_uuid, rE->aTopologyId);
+		duplicate_string(pL->topologyId.contextId, rE->contextId);
+
+		//copy the linkId
+		duplicate_string(pL->linkId, rE->linkId);
+		pL->numLinkTopologies++;
+		duplicate_string(pL->linkTopologies[pL->numLinkTopologies - 1].topologyId, rE->aTopologyId);
+		pL->numLinkTopologies++;
+		duplicate_string(pL->linkTopologies[pL->numLinkTopologies - 1].topologyId, rE->zTopologyId);
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Return the index into mapN related nodeId
+ * 
+ *  @param nodeId
+ *  @para mapN
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint get_map_index_by_nodeId (gchar *nodeId, struct map_nodes_t * mapN) {
+    gint i = 0;    
+    for (i = 0; i < mapN->numMapNodes; i++) {
+		//DEBUG_PC ("i: %d; current: %s // targeted: %s", i, mapN->map[i].verticeId.nodeId, nodeId);
+        if (memcmp (mapN->map[i].verticeId.nodeId, nodeId, strlen (nodeId)) == 0) {
+			//DEBUG_PC ("Index: %d", i);
+			return i;            
+        }
+    }
+	//DEBUG_PC ("Index: %d", index);
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Get the edge e enabling reaching the computed v in mapNodes
+ * 
+ *  @param e
+ *  @param v
+ *  @param mapN
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void get_edge_from_map_by_node (struct edges_t *e, struct nodes_t* v, struct map_nodes_t *mapN) {	
+	//DEBUG_PC ("Get the Edge into map from node v: %s", v.nodeId);	
+	// Get the edge reaching the node v from mapNodes
+	gint map_vIndex = get_map_index_by_nodeId (v->nodeId, mapN);	
+	//DEBUG_PC ("aNodeId: %s --> zNodeId: %s", mapN->map[map_vIndex].predecessor.aNodeId.nodeId, mapN->map[map_vIndex].predecessor.zNodeId.nodeId);	
+	struct edges_t *te = &(mapN->map[map_vIndex].predecessor);	
+	duplicate_edge (e, te);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Get the edge from the predecessors array for a given node n
+ * 
+ *  @param e
+ *  @param n
+ *  @param predecessors
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void get_edge_from_predecessors (struct edges_t *e, struct nodes_t* n, struct pred_t *predecessors) {
+	g_assert(predecessors);
+	DEBUG_PC ("Get edge outgoing node %s from predecessors list", n->nodeId);
+	//print_predecessors (predecessors);
+	for (gint i = 0; i < predecessors->numPredComp; i++) {
+		struct pred_comp_t *pred = &(predecessors->predComp[i]);
+		if (compare_node_id (n, &pred->v) == 0) {
+			// Add to the predecessors list
+			struct edges_t *te = &(pred->e);
+			DEBUG_PC("add e (linkId): %s", te->linkId);
+			duplicate_edge (e, te);
+			return;
+		}	
+	}	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Construct the path using the predecessors list
+ * 
+ *  @param path
+ *  @param predecessors
+ *	@param s
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, struct service_t *s) {
+	// Get the source device Id	of the network connectivity service
+	struct nodes_t *v = create_node();
+	// Src Node of the Service set to v
+	duplicate_string(v->nodeId, s->service_endpoints_id[0].device_uuid);
+								  	
+	// Get the edge for v in predecessors
+	struct edges_t* e = create_edge();
+	get_edge_from_predecessors (e, v, predecessors);	
+	// Get the target for e
+	struct nodes_t u;	
+	duplicate_node_id (&e->zNodeId, &u);
+	//DEBUG_PC ("u: %s", u.nodeId);
+	struct path_constraints_t* pathCons = get_path_constraints(s);		
+
+	// Add route element to the path being constructed
+	gint k = 0;
+	duplicate_node_id (&e->aNodeId, &p->routeElement[k].aNodeId);
+	duplicate_node_id (&e->zNodeId, &p->routeElement[k].zNodeId);
+	duplicate_string(p->routeElement[k].aEndPointId, e->aEndPointId);
+	duplicate_string(p->routeElement[k].zEndPointId, e->zEndPointId);
+	duplicate_string(p->routeElement[k].linkId, e->linkId);
+	duplicate_string(p->routeElement[k].aTopologyId, e->aTopologyId);
+	duplicate_string(p->routeElement[k].zTopologyId, e->zTopologyId);
+	duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId);
+	p->numRouteElements++;
+
+	// Get Dst Node of connectivity service
+	struct nodes_t* dst = create_node();
+	duplicate_string(dst->nodeId, s->service_endpoints_id[1].device_uuid);
+	while (compare_node_id (&u, dst) != 0) {
+		k++; 
+		p->numRouteElements++;			
+		duplicate_node_id (&u, v);
+		get_edge_from_predecessors (e, v, predecessors);
+		// Get the target u		
+		duplicate_node_id (&e->zNodeId, &u);
+		// Add route element to the path being constructed		
+		duplicate_node_id (&e->aNodeId, &p->routeElement[k].aNodeId);
+		duplicate_node_id (&e->zNodeId, &p->routeElement[k].zNodeId);
+		duplicate_string(p->routeElement[k].aEndPointId, e->aEndPointId);
+		duplicate_string(p->routeElement[k].zEndPointId, e->zEndPointId);
+		duplicate_string(p->routeElement[k].linkId, e->linkId);
+		duplicate_string(p->routeElement[k].aTopologyId, e->aTopologyId);
+		duplicate_string(p->routeElement[k].zTopologyId, e->zTopologyId);
+		duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId);		
+	}		
+	g_free(e); g_free(v); g_free(pathCons);
+	//DEBUG_PC ("Path is constructed");	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Print the graph for DEBUG_PCging purposes
+ * 
+ *  @param g
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void print_graph (struct graph_t *g) {
+	g_assert(g);
+    DEBUG_PC ("================================================================");
+    DEBUG_PC ("===========================   GRAPH   ==========================");
+    DEBUG_PC ("================================================================");
+	DEBUG_PC("Graph Num Vertices: %d", g->numVertices);    
+    
+    for (gint i = 0; i < g->numVertices; i++) {
+        DEBUG_PC ("Head Vertice [%s]", g->vertices[i].verticeId.nodeId);
+        for (gint j = 0; j < g->vertices[i].numTargetedVertices; j++)
+        {
+            DEBUG_PC ("  Tail Vertice: %s", g->vertices[i].targetedVertices[j].tVertice.nodeId);
+            for (gint k = 0; k < g->vertices[i].targetedVertices[j].numEdges; k++)
+            {
+                struct edges_t *e = &(g->vertices[i].targetedVertices[j].edges[k]);
+				DEBUG_PC ("%s(%s) --> %s(%s) [C: %f, Bw: %f b/s, Delay: %f ms]", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, 
+								e->zEndPointId, e->cost, e->availCap, e->delay);				
+           }
+        }       
+    }     
+    return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Look for a given edge into the graph
+ *
+ *  @param verticeIndex
+ *	@param targetedVerticeIndex
+ *  @param e
+ *  @param g
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint graph_edge_lookup (gint verticeIndex, gint targetedVerticeIndex, struct edges_t *e, struct graph_t *g)	{
+	gint indexEdge = -1;
+	
+	for (gint j = 0; j < g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex].numEdges; j++) {
+		struct edges_t *e2 = &(g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex].edges[j]);
+		if ((compare_node_id (&e->aNodeId, &e2->aNodeId) == 0) &&
+			(compare_node_id (&e->zNodeId, &e2->zNodeId) == 0) &&
+			(strcmp (e->aEndPointId, e2->aEndPointId) == 0) &&
+			(strcmp (e->zEndPointId, e2->zEndPointId) == 0) &&
+			(strcmp(e->linkId, e2->linkId) == 0)) {
+			DEBUG_PC ("%s (%s) --> %s (%s) [linkId: %s] FOUND in the Graph at index: %d", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, 
+							e->zEndPointId, e->linkId, j);
+			indexEdge = j;
+			return indexEdge;
+		}		
+	}	
+	return indexEdge;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Look for a given vertice within the graph using the nodeId
+ *
+ *  @param nodeId
+ *	@param g
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint graph_vertice_lookup (gchar *nodeId, struct graph_t *g)
+{
+    gint index = -1; 
+	//DEBUG_PC("Searching Node: %s", nodeId);
+    for (gint i = 0; i < g->numVertices; i++) {
+		//DEBUG_PC("Checked Graph Node: %s", g->vertices[i].verticeId.nodeId);
+		if (memcmp (g->vertices[i].verticeId.nodeId, nodeId, strlen (nodeId)) == 0)
+        {
+            index = i;
+            //DEBUG_PC ("%s is found in the graph vertice [%d]", nodeId, index);
+            break;
+        }     
+    }  
+    return (index);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Check if a nodeId is already considered into the set of targeted vertices from a given vertice
+ *
+ *  @param nodeId
+ *  @param vIndex
+ *  @param g
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint graph_targeted_vertice_lookup (gint vIndex, gchar *nodeId, struct graph_t *g)
+{
+    gint addedTargetedVerticeIndex = -1;
+    gint i = 0;
+    
+    if (g->vertices[vIndex].numTargetedVertices == 0)
+    {
+        return (addedTargetedVerticeIndex);
+    }
+    
+    for (i = 0; i < g->vertices[vIndex].numTargetedVertices; i++)
+    {
+        if (memcmp (g->vertices[vIndex].targetedVertices[i].tVertice.nodeId, nodeId, strlen (nodeId)) == 0)
+        {
+            DEBUG_PC ("Targeted %s reachable from %s", nodeId, g->vertices[vIndex].verticeId.nodeId);
+            addedTargetedVerticeIndex = i;
+            return (addedTargetedVerticeIndex);
+        }        
+    }    
+    // not found ...    
+    return (addedTargetedVerticeIndex);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Check if a nodeId is already considered into the set of targeted vertices from a given vertice, if not to be added
+ *
+ *  @param nodeId
+ *  @param vIndex
+ *  @param g
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint graph_targeted_vertice_add (gint vIndex, gchar *nodeId, struct graph_t *g)
+{
+    gint addedTargetedVerticeIndex = -1;
+    gint i = 0;
+    
+    if (g->vertices[vIndex].numTargetedVertices == 0)
+    {
+        //DEBUG_PC ("targeted vertice %s being reachable from vertice %s", nodeId, g->vertices[vIndex].verticeId.nodeId);        
+        addedTargetedVerticeIndex = 0;
+        return (addedTargetedVerticeIndex);
+    }
+    
+    for (i = 0; i < g->vertices[vIndex].numTargetedVertices; i++)
+    {        
+		if (memcmp (g->vertices[vIndex].targetedVertices[i].tVertice.nodeId, nodeId, strlen (nodeId)) == 0)
+        {
+            //DEBUG_PC ("Targeted vertice %s is already considered in the reachable from vertice %s", nodeId, g->vertices[vIndex].verticeId.nodeId);
+            addedTargetedVerticeIndex = -1;
+            return (addedTargetedVerticeIndex);
+        }        
+    }    
+    // It is not found, next to be added at i position
+    addedTargetedVerticeIndex = i;
+    return (addedTargetedVerticeIndex);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Remove edge from the graph
+ *
+ *  @param g
+ *  @param e
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+void remove_edge_from_graph (struct graph_t *g, struct edges_t *e) {
+	// Find the ingress vertice into the graph
+	DEBUG_PC ("Removing from Graph %s[%s]) ---> %s[%s] (linkId: %s)", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, e->aEndPointId, e->linkId);
+	gint verticeIndex = -1;		
+	verticeIndex = graph_vertice_lookup (e->aNodeId.nodeId, g);
+	if (verticeIndex == -1)	{
+		DEBUG_PC ("Edge w/ %s is NOT in the Graph!!", e->aNodeId.nodeId);
+		return;
+	}
+	
+	// Find the targeted vertice from vertice Id
+	gint targetedVerticeIndex = -1;
+	targetedVerticeIndex = graph_targeted_vertice_lookup (verticeIndex, e->zNodeId.nodeId, g);
+	if (targetedVerticeIndex == -1)	{
+		DEBUG_PC ("%s --> %s NOT in the Graph!!", e->aNodeId.nodeId, e->zNodeId.nodeId);
+		return;
+	}	
+	//DEBUG_PC ("%s --> %s found in the Graph", e->aNodeId.nodeId, e->zNodeId.nodeId);
+	
+	// Get the edge position
+	gint edgeIndex = -1;
+	edgeIndex = graph_edge_lookup (verticeIndex, targetedVerticeIndex, e, g);
+	if (edgeIndex == -1) {
+		DEBUG_PC ("%s --> %s NOT in the Graph!!", e->aNodeId.nodeId, e->zNodeId.nodeId);
+		return;
+	}
+	
+	//DEBUG_PC ("%s --> %s FOUND in Graph w/ edgeIndex: %d", e->aNodeId.nodeId, e->zNodeId.nodeId, edgeIndex);
+	
+	// Remove the edge
+	//DEBUG_PC ("Start Removing %s --> %s from Graph", e->aNodeId.nodeId, e->zNodeId.nodeId);	
+	struct targetNodes_t *v = &(g->vertices[verticeIndex].targetedVertices[targetedVerticeIndex]);	
+	for (gint j = edgeIndex; j < v->numEdges; j++) {	
+		struct edges_t *e1 = &(v->edges[j]);
+		struct edges_t *e2 = &(v->edges[j+1]);		
+		duplicate_edge (e1, e2);
+	}
+	v->numEdges --;
+	DEBUG_PC ("Number of Edges between %s and %s is %d", e->aNodeId.nodeId, e->zNodeId.nodeId, v->numEdges);	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief create the pointer for keeping a set of the paths (struct compRouteOutput_t)
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct path_set_t * create_path_set () {
+	struct path_set_t * p = g_malloc0 (sizeof (struct path_set_t));
+	if (p == NULL) {
+		DEBUG_PC ("Memory allocation problem");
+		exit (-1);		
+	}
+	return p;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Remove the path set
+ *
+ * @param p
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2021
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void remove_path_set(struct path_set_t* p) {
+	g_assert(p); g_free(p);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Create map of nodes to handle the path computation
+ *
+ * 	@param mapN
+ *  @param g
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void build_map_node (struct map_nodes_t *mapN, struct graph_t *g) {
+	//DEBUG_PC ("Construction of the Map of Nodes");               
+    for (gint i = 0; i < g->numVertices; i++) {	
+		duplicate_node_id (&g->vertices[i].verticeId, &mapN->map[i].verticeId);
+        mapN->map[i].distance = INFINITY_COST;
+        mapN->map[i].avaiBandwidth = 0.0;
+        mapN->map[i].latency = INFINITY_COST;
+		mapN->map[i].power = INFINITY_COST;
+        mapN->numMapNodes++;
+    }
+    //DEBUG_PC ("mapNodes formed by %d Nodes", mapN->numMapNodes);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Allocate memory for path of struct compRouteOutputList_t *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct compRouteOutputList_t * create_route_list () {
+	struct compRouteOutputList_t *p = g_malloc0 (sizeof (struct compRouteOutputList_t));
+	if (p == NULL) {
+		DEBUG_PC ("Memory Allocation Problem");
+		exit (-1);
+	}
+	return p;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Copy all the attributes defining a path
+ *
+ * @param dst_path
+ * @param src_path
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void copy_path(struct path_t* dst_path, struct path_t* src_path) {
+	g_assert(dst_path);
+	g_assert(src_path);
+
+	// Path capacity
+	dst_path->path_capacity.unit = src_path->path_capacity.unit;
+	memcpy(&dst_path->path_capacity.value, &src_path->path_capacity.value, sizeof(gdouble));
+
+	// Path latency
+	memcpy(&dst_path->path_latency.fixed_latency, &src_path->path_latency.fixed_latency, sizeof(gdouble));
+
+	// Path cost
+	duplicate_string(dst_path->path_cost.cost_name, src_path->path_cost.cost_name);
+	memcpy(&dst_path->path_cost.cost_value, &src_path->path_cost.cost_value, sizeof(gdouble));
+	memcpy(&dst_path->path_cost.cost_algorithm, &src_path->path_cost.cost_algorithm, sizeof(gdouble));
+
+	// Path links
+	dst_path->numPathLinks = src_path->numPathLinks;
+	for (gint i = 0; i < dst_path->numPathLinks; i++) {
+		struct pathLink_t* dPathLink = &(dst_path->pathLinks[i]);
+		struct pathLink_t* sPathLink = &(src_path->pathLinks[i]);
+
+		duplicate_string(dPathLink->linkId, sPathLink->linkId);
+		duplicate_string(dPathLink->aDeviceId, sPathLink->aDeviceId);
+		duplicate_string(dPathLink->zDeviceId, sPathLink->zDeviceId);
+		duplicate_string(dPathLink->aEndPointId, sPathLink->aEndPointId);
+		duplicate_string(dPathLink->zEndPointId, sPathLink->zEndPointId);
+
+		duplicate_string(dPathLink->topologyId.contextId, sPathLink->topologyId.contextId);
+		duplicate_string(dPathLink->topologyId.topology_uuid, sPathLink->topologyId.topology_uuid);
+
+		dPathLink->numLinkTopologies = sPathLink->numLinkTopologies;
+		for (gint j = 0; j < dPathLink->numLinkTopologies; j++) {
+			struct linkTopology_t* dLinkTop = &(dPathLink->linkTopologies[j]);
+			struct linkTopology_t* sLinkTop = &(sPathLink->linkTopologies[j]);
+
+			duplicate_string(dLinkTop->topologyId, sLinkTop->topologyId);
+		}
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Duplicate the route output instance
+ *
+ * @param dst_ro
+ * @param src_ro
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_compRouteOuput(struct compRouteOutput_t* dst_ro, struct compRouteOutput_t* src_ro) {
+	g_assert(dst_ro); g_assert(src_ro); 
+		
+	// Copy the serviceId
+	copy_service_id(&dst_ro->serviceId, &src_ro->serviceId);
+	dst_ro->num_service_endpoints_id = src_ro->num_service_endpoints_id;
+
+	for (gint j = 0; j < dst_ro->num_service_endpoints_id; j++) {
+		struct service_endpoints_id_t* iEp = &(src_ro->service_endpoints_id[j]);
+		struct service_endpoints_id_t* oEp = &(dst_ro->service_endpoints_id[j]);
+		copy_service_endpoint_id(oEp, iEp);
+	}
+
+	// Copy paths
+	dst_ro->numPaths = src_ro->numPaths;
+	for (gint j = 0; j < dst_ro->numPaths; j++) {
+		struct path_t* dst_path = &(dst_ro->paths[j]);
+		struct path_t* src_path = &(src_ro->paths[j]);
+		copy_path(dst_path, src_path);
+	}
+	// copy no path issue value
+	dst_ro->noPathIssue = src_ro->noPathIssue;
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Duplicate the computation route output list
+ * 
+ * @param dst
+ * @param src
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_route_list(struct compRouteOutputList_t* dst, struct compRouteOutputList_t* src) {
+	g_assert(src); g_assert(dst);
+
+	dst->numCompRouteConnList = src->numCompRouteConnList;
+	dst->compRouteOK = src->compRouteOK;
+	memcpy(&dst->compRouteConnAvBandwidth, &src->compRouteConnAvBandwidth, sizeof(gdouble));
+	memcpy(&dst->compRouteConnAvPathLength, &src->compRouteConnAvPathLength, sizeof(gdouble));
+	for (gint i = 0; i < src->numCompRouteConnList; i++) {
+		struct compRouteOutput_t* src_ro = &(src->compRouteConnection[i]);
+		struct compRouteOutput_t* dst_ro = &(dst->compRouteConnection[i]);
+		duplicate_compRouteOuput(dst_ro, src_ro);
+	}	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Allocate memory for path of struct compRouteOutputItem_t *
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct compRouteOutputItem_t *create_path_item () {
+	struct compRouteOutputItem_t *p = g_malloc0 (sizeof (struct compRouteOutputItem_t));
+	if (p == NULL) 	{
+		DEBUG_PC ("Memory Allocation Problem");
+		exit (-1);
+	}
+	return p;	
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Sort the set of paths the AvailBw, Cost and Delay
+ *
+ *	@params setP
+ *  @params args
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void sort_path_set(struct path_set_t* setP, guint args) {
+	g_assert(setP);
+	// Sort the paths contained in setP by:
+	// 1st Criteria: The path cost (maybe bound to link distance)
+	// 2nd Criteria: The consumed path power 
+	// 3nd Criteria: The path latency
+	// 3rd Criteria: The available Bw
+	float epsilon = 0.1;
+
+	for (gint i = 0; i < setP->numPaths; i++) {
+		for (gint j = 0; j < (setP->numPaths - i - 1); j++)	{
+			struct compRouteOutputItem_t* path1 = &setP->paths[j];
+			struct compRouteOutputItem_t* path2 = &setP->paths[j + 1];			
+			struct compRouteOutputItem_t* pathTmp = create_path_item();
+			//////////////////////// Criterias ////////////////////////////////////////
+			// 1st Criteria (Cost)
+			if (path2->cost < path1->cost) {
+				duplicate_path(path1, pathTmp);
+				duplicate_path(path2, path1);
+				duplicate_path(pathTmp, path2);
+				g_free(pathTmp);
+				continue;
+			}
+			if (path2->cost == path1->cost) {
+				// 2nd Criteria (Energy)
+				if (args & ENERGY_EFFICIENT_ARGUMENT) {
+					if (path2->power < path1->power) {
+						duplicate_path(path1, pathTmp);
+						duplicate_path(path2, path1);
+						duplicate_path(pathTmp, path2);
+						g_free(pathTmp);
+						continue;
+					}
+					else {	  // path1->power < path2->power
+						g_free(pathTmp);
+						continue;
+					}
+				}
+				else { // No enery efficient argument
+					// 3rd Criteria (latency)
+					if (path2->delay < path1->delay) {
+						duplicate_path(path1, pathTmp);
+						duplicate_path(path2, path1);
+						duplicate_path(pathTmp, path2);
+						g_free(pathTmp);
+						continue;
+					}
+					else if (path1->delay < path2->delay) {
+						g_free(pathTmp);
+						continue;
+					}
+					else { // path1->delay == path2->delay
+						// 4th Criteria (available bw)
+						if (path2->availCap > path1->availCap) {
+							duplicate_path(path1, pathTmp);
+							duplicate_path(path2, path1);
+							duplicate_path(pathTmp, path2);
+							g_free(pathTmp);
+							continue;
+						}
+						else {
+							g_free(pathTmp);
+							continue;
+						}
+					}
+				}
+			}
+			else {	// path1->cost < path2->cost
+				g_free(pathTmp);
+				continue;
+			}				
+		}
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Remove first element from the path sets 
+ *
+ *	@params setP
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void pop_front_path_set (struct path_set_t *setP) {
+	for (gint j = 0; j < setP->numPaths - 1; j++) {
+		struct compRouteOutputItem_t *path1 = &setP->paths[j];
+		struct compRouteOutputItem_t *path2 = &setP->paths[j+1];		
+		duplicate_path (path2, path1);		
+	}
+	setP->numPaths--;	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Add routeElement to the back of the path
+ *
+ * 	@param rE
+ * 	@param p
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void add_routeElement_path_back (struct routeElement_t *rE, struct compRouteOutputItem_t *p) {
+	//DEBUG_PC ("p->numRouteElements: %d", p->numRouteElements);
+	p->numRouteElements++;
+	gint index = p->numRouteElements - 1;
+	
+	struct nodes_t *pn = &(p->routeElement[index].aNodeId);
+	struct nodes_t *rEn = &(rE->aNodeId);
+	
+	// duplicate aNodeId
+	duplicate_node_id (rEn, pn);	
+	pn = &(p->routeElement[index].zNodeId);
+	rEn = &(rE->zNodeId);
+	duplicate_node_id (rEn, pn);
+	duplicate_string(p->routeElement[index].aEndPointId, rE->aEndPointId);
+	duplicate_string(p->routeElement[index].zEndPointId, rE->zEndPointId);
+	duplicate_string(p->routeElement[index].linkId, rE->linkId);
+	duplicate_string(p->routeElement[index].aTopologyId, rE->aTopologyId);
+	duplicate_string(p->routeElement[index].zTopologyId, rE->zTopologyId);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief This function compares ap and rootPath. If all the links are equal between both ap and rootPath till the sN, then the link from sN to next node 
+ * 	ap is returned
+ * 
+ * @params ap
+ * @params p
+ * @params sN
+ * @params e
+ * 
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gboolean matching_path_rootPath (struct compRouteOutputItem_t *ap, struct compRouteOutputItem_t *rootPath, struct nodes_t *sN, struct edges_t *e) {
+	gint j = 0;
+	gboolean ret = FALSE;
+	while ((j < ap->numRouteElements) && (j < rootPath->numRouteElements)) {
+		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0) &&
+			//(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) != 0) &&
+			(memcmp (sN->nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0)) {						
+			duplicate_node_id (&ap->routeElement[j].aNodeId, &e->aNodeId);
+			duplicate_node_id (&ap->routeElement[j].zNodeId, &e->zNodeId);
+			duplicate_string(e->aEndPointId, ap->routeElement[j].aEndPointId);
+			duplicate_string(e->zEndPointId, ap->routeElement[j].zEndPointId);
+			duplicate_string(e->linkId, ap->routeElement[j].linkId);
+			return TRUE;			
+		}		
+		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) == 0) && 
+			(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) == 0)) {
+			j++;			
+			continue;			
+		}
+		
+		if ((memcmp (ap->routeElement[j].aNodeId.nodeId, rootPath->routeElement[j].aNodeId.nodeId, sizeof (ap->routeElement[j].aNodeId.nodeId)) != 0) || 
+			(memcmp (ap->routeElement[j].zNodeId.nodeId, rootPath->routeElement[j].zNodeId.nodeId, sizeof (ap->routeElement[j].zNodeId.nodeId)) != 0)) {
+			//DEBUG_PC ("ap and rootPath not in the same path");
+			return ret;
+		}
+	}	
+	return ret;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief This function is used to modify the graph to be used for running the subsequent SP computations acording to the YEN algorithm principles
+ * 
+ * @params g
+ * @params A
+ * @params rootPath
+ * @params spurNode
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void modify_targeted_graph (struct graph_t *g, struct path_set_t *A, struct compRouteOutputItem_t * rootPath, struct nodes_t * spurNode) {
+	//DEBUG_PC ("Modify the Targeted graph according to the Yen algorithm principles");
+	for (gint j = 0; j < A->numPaths; j++) {
+		struct compRouteOutputItem_t *ap = &A->paths[j];
+		struct edges_t *e = create_edge();
+		gboolean ret =  FALSE;
+		ret = matching_path_rootPath (ap, rootPath, spurNode, e);		
+		if (ret == TRUE) {
+			DEBUG_PC ("Removal %s[%s] --> %s[%s] from the graph", e->aNodeId.nodeId, e->aEndPointId, e->zNodeId.nodeId, e->aEndPointId);
+			remove_edge_from_graph (g, e);
+			//DEBUG_PC ("Print Resulting Graph");
+			print_graph (g);
+			g_free (e);			
+		}
+		if (ret == FALSE) {
+			g_free (e);
+			continue;
+		}						
+	}	
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Supporting fucntion to Check if a nodeId is already in the items of a given GList
+ * 
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint find_nodeId (gconstpointer data, gconstpointer userdata)
+{
+     /** check values */
+     g_assert(data != NULL);
+     g_assert(userdata != NULL);
+ 
+     struct nodeItem_t *SNodeId = (struct nodeItem_t *)data;
+     guchar * nodeId = (guchar *)userdata; 
+     
+     //DEBUG_PC ("SNodeId (%s) nodeId (%s)", SNodeId->node.nodeId, nodeId);   
+        
+     if (!memcmp(SNodeId->node.nodeId, nodeId, strlen (SNodeId->node.nodeId)))
+     {
+		return (0);
+     }
+    return -1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Explores the link between u and v
+ * 
+ *  @param u
+ *  @param v 
+ *	@param g
+ *	@param s
+ *  @param S
+ *  @param Q
+ *	@param mapNodes
+ * 
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struct graph_t *g, 
+				struct service_t *s, GList **S, GList **Q, struct map_nodes_t *mapNodes, 
+				guint arg) { 
+	g_assert(g); g_assert(s); g_assert(mapNodes);
+
+	struct targetNodes_t *v = &(g->vertices[indexGraphU].targetedVertices[indexGraphV]);	
+    DEBUG_PC("Explored Link %s => %s)", u->node.nodeId, v->tVertice.nodeId);
+	//DEBUG_PC("\t %s => %s", u->node.nodeId, v->tVertice.nodeId);	
+    
+    // v already explored in S? then, discard it
+    GList *found = g_list_find_custom (*S, v->tVertice.nodeId, find_nodeId);
+    if (found != NULL) {
+        DEBUG_PC ("v (%s) in S, Discard", v->tVertice.nodeId);        
+        return 0;
+    }
+
+	// Get the set of constraints imposed by the service
+	struct path_constraints_t* path_constraints = get_path_constraints(s);
+    gdouble distance_through_u = INFINITY_COST ,latency_through_u = INFINITY_COST, power_through_u = INFINITY_COST;
+	gint i = 0, foundAvailBw = 0;
+    // BANDWIDTH requirement to be fulfilled on EDGE u->v        
+    gdouble edgeAvailBw = 0.0, edgeTotalBw = 0.0;
+    for (i = 0; i < v->numEdges; i++) {        
+        struct edges_t *e = &(v->edges[i]);
+		memcpy (&edgeAvailBw, &(e->availCap), sizeof (gdouble));
+		memcpy(&edgeTotalBw, &(e->totalCap), sizeof(gdouble));
+		DEBUG_PC("EDGE %s[%s] => %s[%s]", u->node.nodeId, e->aEndPointId, v->tVertice.nodeId, e->zEndPointId);
+        //DEBUG_PC ("\t %s[%s] =>", u->node.nodeId, e->aEndPointId);
+		//DEBUG_PC("\t => %s[%s]", v->tVertice.nodeId, e->zEndPointId);
+		DEBUG_PC("\t AvailBw: %f, TotalBw: %f", edgeAvailBw, edgeTotalBw);
+        // Check Service Bw constraint
+		if ((path_constraints->bw == TRUE) && (edgeAvailBw < path_constraints->bwConstraint))
+			continue;
+		else {
+			foundAvailBw = 1;
+			break;
+		}		
+    }
+	// BW constraint NOT MET, then DISCARD edge
+    if ((path_constraints->bw == TRUE) && (foundAvailBw == 0)) {
+        DEBUG_PC ("AvailBw: %f < path_constraint: %f -- Discard Edge", edgeAvailBw, path_constraints->bwConstraint);
+		g_free(path_constraints);
+        return 0;    
+    } 
+
+    gint indexEdge = i; // get the index for the explored edge
+    // Update distance, latency and availBw through u to reach v
+    gint map_uIndex = get_map_index_by_nodeId (u->node.nodeId, mapNodes);
+	struct map_t *u_map = &mapNodes->map[map_uIndex];
+    distance_through_u = u_map->distance + v->edges[indexEdge].cost;
+    latency_through_u = u_map->latency + v->edges[indexEdge].delay;
+	// Consumed power at v through u is the sum
+	// 1. Power from src to u
+	// 2. Power-idle at node u
+	// 3. power consumed over the edge between u and v, i.e. energy*usedBw
+	power_through_u = u_map->power + g->vertices[indexGraphU].power_idle + ((edgeTotalBw - edgeAvailBw + path_constraints->bwConstraint) * (v->edges[indexEdge].energy));
+    gdouble availBw_through_u = 0.0;
+
+	// ingress endpoint (u) is the src of the request
+    if (strcmp (u->node.nodeId, s->service_endpoints_id[0].device_uuid) == 0) {
+        //DEBUG_PC ("AvailBw %f on %s --> %s", edgeAvailBw, u->node.nodeId, v->tVertice.nodeId);        
+        memcpy (&availBw_through_u, &edgeAvailBw, sizeof (gdouble));        
+    }
+    else {
+        // Get the minimum available bandwidth between the src-->u and the new added edge u-->v
+        //DEBUG_PC ("Current AvailBw: %f from src to %s", u_map->avaiBandwidth, u->node.nodeId);
+        //DEBUG_PC ("AvailBw: %f %s --> %s", edgeAvailBw, u->node.nodeId, v->tVertice.nodeId);
+        if (u_map->avaiBandwidth <= edgeAvailBw) {
+            memcpy (&availBw_through_u, &u_map->avaiBandwidth, sizeof (gdouble));    
+		}
+		else {
+			memcpy (&availBw_through_u, &edgeAvailBw, sizeof (gdouble));
+		} 
+    }     
+    // Relax the link according to the pathCost, latency, and energy
+    gint map_vIndex = get_map_index_by_nodeId (v->tVertice.nodeId, mapNodes);
+	struct map_t *v_map = &mapNodes->map[map_vIndex];
+    // If cost dist (u, v) > dist (src, v) relax the link
+    if (distance_through_u > v_map->distance) {
+        //DEBUG_PC ("dist(src, u) + dist(u, v): %f > dist (src, v): %f --> Discard Link", distance_through_u, v_map->distance);  
+        return 0;
+    }
+	// If energy consumption optimization is requested
+	if (arg & ENERGY_EFFICIENT_ARGUMENT) {
+		if (distance_through_u == v_map->distance) {
+			if (power_through_u > v_map->power) {
+				DEBUG_PC("Energy (src -> u + u -> v: %f (Watts) >Energy (src, v): %f (Watts)--> DISCARD LINK", power_through_u, v_map->power);
+				return 0;
+			}
+			// same energy consumption, consider latency
+			if ((power_through_u == v_map->power) && (latency_through_u > v_map->latency)) {
+				return 0;
+			}
+			if ((power_through_u == v_map->power) && (latency_through_u == v_map->latency) && (availBw_through_u < v_map->avaiBandwidth)) {
+				return 0;
+			}
+		}
+	} // No optimization, rely on latency and available e2e bandwidth
+	else {
+		// If dist (src, u) + dist (u, v) = current dist(src, v), then use the latency as discarding criteria
+		if ((distance_through_u == v_map->distance) && (latency_through_u > v_map->latency)) {
+			//DEBUG_PC ("dist(src, u) + dist(u,v) = current dist(src, v), but latency (src,u) + latency (u, v) > current latency (src, v)");          
+			return 0;
+		}
+		// If dist (src, u) + dist (u,v) == current dist(src, v) AND latency (src, u) + latency (u, v) == current latency (src, v), the available bandwidth is the criteria
+		if ((distance_through_u == v_map->distance) && (latency_through_u == v_map->latency) && (availBw_through_u < v_map->avaiBandwidth)) {
+			return 0;
+		}
+	}
+    DEBUG_PC ("%s --> %s Relaxed", u->node.nodeId, v->tVertice.nodeId);
+    DEBUG_PC ("\t AvailBw: %f Mb/s, Cost: %f, Latency: %f ms, Energy: %f Watts", availBw_through_u, distance_through_u, latency_through_u, power_through_u);
+    
+    // Update Q list -- 
+    struct nodeItem_t *nodeItem = g_malloc0 (sizeof (struct nodeItem_t));
+    if (nodeItem == NULL) {
+		DEBUG_PC ("memory allocation failed\n");
+		exit (-1);    
+    }    
+    nodeItem->distance = distance_through_u;
+	memcpy(&nodeItem->distance, &distance_through_u, sizeof(gdouble));		     
+	memcpy(&nodeItem->latency, &latency_through_u, sizeof(gdouble));
+	memcpy(&nodeItem->power, &power_through_u, sizeof(gdouble));
+	duplicate_node_id (&v->tVertice, &nodeItem->node);	
+	// add node to the Q list
+	if (arg & ENERGY_EFFICIENT_ARGUMENT) {
+		*Q = g_list_insert_sorted(*Q, nodeItem, sort_by_energy);
+	}
+	else
+		*Q = g_list_insert_sorted (*Q, nodeItem, sort_by_distance);
+    
+	// Update the mapNodes for the specific reached tv   
+    v_map->distance = distance_through_u;
+	memcpy(&v_map->distance, &distance_through_u, sizeof(gdouble));
+    memcpy (&v_map->avaiBandwidth, &availBw_through_u, sizeof (gdouble));
+    memcpy (&v_map->latency, &latency_through_u, sizeof (gdouble));
+	memcpy(&v_map->power, &power_through_u, sizeof(gdouble));
+    // Duplicate the predecessor edge into the mapNodes 
+	struct edges_t *e1 = &(v_map->predecessor);
+	struct edges_t *e2 = &(v->edges[indexEdge]);
+	duplicate_edge(e1, e2);	
+	DEBUG_PC ("u->v Edge: %s(%s) --> %s(%s)", e2->aNodeId.nodeId, e2->aEndPointId, e2->zNodeId.nodeId, e2->zEndPointId);
+	//DEBUG_PC("v-pred aTopology: %s", e2->aTopologyId);
+	DEBUG_PC("v-pred zTopology: %s", e2->zTopologyId);
+
+    // Check whether v is dstPEId
+	//DEBUG_PC ("Targeted dstId: %s", s->service_endpoints_id[1].device_uuid);
+	//DEBUG_PC ("nodeId added to the map: %s", v_map->verticeId.nodeId);
+	//DEBUG_PC ("Q Length: %d", g_list_length(*Q));
+	g_free(path_constraints);
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Check the feasability of a path wrt the constraints imposed by the request in terms of latency
+ * 
+ *  @param s
+ *	@param p
+ * 
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gboolean check_computed_path_feasability (struct service_t *s, struct compRouteOutputItem_t* p) {	
+	float epsilon = 0.0000001;
+	struct path_constraints_t* pathCons = get_path_constraints(s);
+	gboolean ret = TRUE;
+	if (pathCons->latency == TRUE) {
+		if ((pathCons->latencyConstraint - p->delay > 0.0) || (fabs(pathCons->latencyConstraint - p->delay) < epsilon)) {
+			DEBUG_PC("Computed Path (latency: %f) is feasible wrt Connection Demand: %f", p->delay, pathCons->latencyConstraint);
+		}
+		else {
+			DEBUG_PC("Computed Path (latency: %f) is NOT feasible wrt Connection Demand: %f", p->delay, pathCons->latencyConstraint);
+			g_free(pathCons);
+			return FALSE;
+		}
+	}
+	// Other constraints...		
+	g_free(pathCons);
+	return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Sorting the GList Q items by distance 
+ * 
+ * @param a
+ * @param b
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint sort_by_distance (gconstpointer a, gconstpointer b) {
+	//DEBUG_PC ("sort by distance a and b");	
+	g_assert(a != NULL);
+	g_assert(b != NULL);
+	
+	//DEBUG_PC ("sort by distance a and b");	  
+	struct nodeItem_t *node1 = (struct nodeItem_t *)a;
+	struct nodeItem_t *node2 = (struct nodeItem_t *)b;
+	g_assert (node1);
+	g_assert (node2);
+	 
+	//DEBUG_PC ("a->distance %u; b->distance %u", node1->distance, node2->distance);
+	//DEBUG_PC("a->latency: %f; b->latency: %f", node1->latency, node2->latency);
+	//1st criteria, sorting by lowest distance
+	if (node1->distance > node2->distance)
+		return 1;
+	else if (node1->distance < node2->distance)
+		return 0;
+	if (node1->distance == node2->distance) {
+		if (node1->latency > node2->latency)
+			return 1;
+		else if (node1->latency <= node2->latency)
+			return 0;
+	}
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Sorting the GList Q items by distance
+ * 
+ * @param a
+ * @param b
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+gint sort_by_energy(gconstpointer a, gconstpointer b) {	
+	g_assert(a != NULL);
+	g_assert(b != NULL);
+
+	//DEBUG_PC ("sort by distance a and b");	  
+	struct nodeItem_t* node1 = (struct nodeItem_t*)a;
+	struct nodeItem_t* node2 = (struct nodeItem_t*)b;
+	g_assert(node1);
+	g_assert(node2);
+	
+	//1st criteria: sorting by lowest distance
+	if (node1->distance > node2->distance)
+		return 1;
+	if (node1->distance < node2->distance)
+		return 0;
+
+	// 2nd Criteria: sorting by the lowest energy
+	if (node1->power > node2->power)
+		return 1;
+	if (node1->power < node1->power)
+		return 0;
+
+	// 3rd Criteria: by the latency 
+	if (node1->latency > node2->latency)
+		return 1;
+	if (node1->latency <= node2->latency)
+		return 0;
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Allocate memory for graph
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct graph_t * create_graph () {
+	struct graph_t * g = g_malloc0 (sizeof (struct graph_t));
+	if (g == NULL) {
+		DEBUG_PC ("Memory Allocation Problem");
+		exit (-1);
+	}
+	return g;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Allocate memory for mapNodes
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+struct map_nodes_t * create_map_node ()	 {
+	struct map_nodes_t * mN = g_malloc0 (sizeof (struct map_nodes_t));
+	if (mN == NULL) {
+		DEBUG_PC ("Memory allocation failed");
+		exit (-1);
+	}
+	return mN;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Look up for the service in the servieList bound to a serviceUUID
+ * 
+ * @params serviceUUID
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct service_t* get_service_for_computed_path(gchar* serviceUUID) {
+	gint i = 0;
+	for(GList *listnode = g_list_first(serviceList);
+		listnode;
+		listnode = g_list_next(listnode), i++) {
+			struct service_t* s = (struct service_t*)(listnode->data);
+			if (strcmp(s->serviceId.service_uuid, serviceUUID) == 0)
+				return s;
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the service type
+ * 
+ * @param type
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_service_type(guint type) {
+	switch (type) {
+	case SERVICE_TYPE_UNKNOWN:
+			DEBUG_PC("Service Type UNKNOWN");
+			break;
+		case SERVICE_TYPE_L3NM:
+			DEBUG_PC("Service Type L3NM");
+			break;
+		case SERVICE_TYPE_L2NM:
+			DEBUG_PC("Service Type L2NM");
+			break;
+		case SERVICE_TYPE_TAPI:
+			DEBUG_PC("Service Type L2NM");
+			break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the port direction
+ *
+ * @param direction
+ *
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_link_port_direction(guint direction) {
+	switch (direction) {
+		case LINK_PORT_DIRECTION_BIDIRECTIONAL:
+			//DEBUG_PC("Bidirectional Port Direction");
+			break;
+		case LINK_PORT_DIRECTION_INPUT:
+			//DEBUG_PC("Input Port Direction");
+			break;
+		case LINK_PORT_DIRECTION_OUTPUT:
+			//DEBUG_PC("Output Port Direction");
+			break;
+		case LINK_PORT_DIRECTION_UNKNOWN:
+			//DEBUG_PC("Unknown Port Direction");
+			break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the port termination direction
+ *
+ * @param direction
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_termination_direction(guint direction) {
+	switch (direction) {
+	case TERMINATION_DIRECTION_BIDIRECTIONAL:
+		//DEBUG_PC("Bidirectional Termination Direction");
+		break;
+	case TERMINATION_DIRECTION_SINK:
+		//DEBUG_PC("Input Termination Direction");
+		break;
+	case TERMINATION_DIRECTION_SOURCE:
+		//DEBUG_PC("Output Termination Direction");
+		break;
+	case TERMINATION_DIRECTION_UNKNOWN:
+		//DEBUG_PC("Unknown Termination Direction");
+		break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the termination state
+ *
+ * @param state 
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_termination_state(guint state)
+{
+	switch (state) {
+	case TERMINATION_STATE_CAN_NEVER_TERMINATE:
+		//DEBUG_PC("Can never Terminate");
+		break;
+	case TERMINATION_STATE_NOT_TERMINATED:
+		DEBUG_PC("Not terminated");
+		break;
+	case TERMINATION_STATE_TERMINATED_SERVER_TO_CLIENT_FLOW:
+		DEBUG_PC("Terminated server to client flow");
+		break;
+	case TERMINATION_STATE_TERMINATED_CLIENT_TO_SERVER_FLOW:
+		DEBUG_PC("Terminated client to server flow");
+		break;
+	case TERMINATION_STATE_TERMINATED_BIDIRECTIONAL:
+		//DEBUG_PC("Terminated bidirectional");
+		break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the capacity unit
+ *
+ * @param unit
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_capacity_unit(guint unit) {
+
+	switch (unit) {
+		case CAPACITY_UNIT_TB:
+			DEBUG_PC("Unit in TB");
+			break;
+		case CAPACITY_UNIT_TBPS:
+			DEBUG_PC("Unit in TB/s");
+			break;
+		case CAPACITY_UNIT_GB:
+			DEBUG_PC("Unit in GB");
+			break;
+		case CAPACITY_UNIT_GBPS:
+			DEBUG_PC("Unit in GB/s");
+			break;
+		case CAPACITY_UNIT_MB:
+			DEBUG_PC("Unit in MB");
+			break;
+		case CAPACITY_UNIT_MBPS:
+			//DEBUG_PC("Unit in MB/s");
+			break;
+		case CAPACITY_UNIT_KB:
+			DEBUG_PC("Unit in KB");
+			break;
+		case CAPACITY_UNIT_KBPS:
+			DEBUG_PC("Unit in KB/s");
+			break;
+		case CAPACITY_UNIT_GHZ: 
+			DEBUG_PC("Unit in GHz");
+			break;
+		case CAPACITY_UNIT_MHZ:
+			DEBUG_PC("Unit in MHz");
+			break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Friendly function to log the link forwarding direction
+ *
+ * @param linkFwDir
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_link_forwarding_direction(guint linkFwDir) {
+	switch (linkFwDir) {
+		case LINK_FORWARDING_DIRECTION_BIDIRECTIONAL:
+			DEBUG_PC("BIDIRECTIONAL LINK FORWARDING DIRECTION");
+			break;
+		case LINK_FORWARDING_DIRECTION_UNIDIRECTIONAL:
+			DEBUG_PC("UNIDIRECTIONAL LINK FORWARDING DIRECTION");
+			break;
+		case  LINK_FORWARDING_DIRECTION_UNKNOWN:
+			DEBUG_PC("UNKNOWN LINK FORWARDING DIRECTION");
+			break;
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Search a specific contextUuid element into the contextSet
+ *
+ * @param contextUuid
+ * @param set
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct context_t* find_contextId_in_set(gchar* contextUuid, GList** set) {
+	//DEBUG_PC("Checking if contextId: %s in in the ContextSet??", contextUuid);
+	gint i = 0;
+	for (GList *ln = g_list_first(*set);
+		ln;
+		ln = g_list_next(ln)){
+		struct context_t* c = (struct context_t*)(ln->data);
+		//DEBUG_PC("Context Item [%d] Id: %s", i, c->contextId);
+		if (strcmp(contextUuid, c->contextId) == 0) {
+			//DEBUG_PC("contextId: %s is FOUND in the ContextSet_List", contextUuid);
+			return c;
+		}
+		i++;
+	}
+	//DEBUG_PC("contextId: %s NOT FOUND in the ContextSet_List", contextUuid);
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Add a specific context uuid into the context set
+ *
+ * @param contextUuid
+ * @param set
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct context_t* add_contextId_in_set(gchar *contextUuid, GList** set) {
+
+	struct context_t* c = g_malloc0(sizeof(struct context_t));
+	if (c == NULL) {
+		DEBUG_PC("Memory Allocation Failure");
+		exit(-1);
+	}
+	duplicate_string(c->contextId, contextUuid);
+	// Add the context into the context set
+	//DEBUG_PC("Adding ContextId: %s", contextUuid);
+	//DEBUG_PC(" (BEFORE ADDING) Context Set Length: %d", g_list_length(*set));
+	*set = g_list_append(*set, c);
+	//DEBUG_PC(" (AFTER ADDING) Context Set Length: %d", g_list_length(*set));
+	return c;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Find a vertex in a specific graph
+ *
+ * @param contextUuid
+ * @param set
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct vertices_t* find_vertex_in_graph_context(struct graph_t *g, gchar* deviceId) {
+	for (gint i = 0; i < g->numVertices; i++) {
+		struct vertices_t* v = &(g->vertices[i]);
+		if (strcmp(v->verticeId.nodeId, deviceId) == 0) {
+			return v;
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Adding a deviceId into a graph
+ *
+ * @param g
+ * @param deviceId
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct vertices_t* add_vertex_in_graph(struct graph_t* g, struct device_t *d) {
+	g->numVertices++;
+	struct vertices_t* v = &(g->vertices[g->numVertices - 1]);
+	duplicate_string(v->verticeId.nodeId, d->deviceId);
+	memcpy(&v->power_idle, &d->power_idle, sizeof(gdouble));
+	return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Construct the graphs (vertices and edges) bound to every individual context
+ *
+ * @param cSet
+ * @param activeFlag
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void build_contextSet_deviceList(GList** cSet, gint activeFlag) {
+	// Check every device their endpoints	
+	for (GList* listnode = g_list_first(deviceList); 
+		listnode; 
+		listnode = g_list_next(listnode)) {	
+		struct device_t* d = (struct device_t*)(listnode->data);
+		//DEBUG_PC("Exploring DeviceId: %s", d->deviceId);
+
+		if ((activeFlag == 1) && (d->operational_status != 2)) {
+			// it is only considered devices with operational status enabled, i.e., set to 2
+			continue;
+		}
+		// Check the associated endPoints
+		for (gint j = 0; j < d->numEndPoints; j++) {
+			struct endPoint_t* eP = &(d->endPoints[j]);
+			// Get endPointId (topology, context, device Id and endpoint uuid)
+			struct endPointId_t* ePid = &(eP->endPointId);  //end point id
+			//DEBUG_PC("   EndPointId: %s || Type: %s", eP->endPointId.endpoint_uuid, d->deviceType);
+			//DEBUG_PC("   TopologyId: %s || ContextId: %s", eP->endPointId.topology_id.topology_uuid, eP->endPointId.topology_id.contextId);
+			// Add contextId in ContextSet and the deviceId (+endpoint) into the vertex set
+			struct context_t *c = find_contextId_in_set(eP->endPointId.topology_id.contextId, cSet);
+			if (c == NULL) {
+				DEBUG_PC("   contextUuid: %s MUST BE ADDED to ContextSet", eP->endPointId.topology_id.contextId);
+				c = add_contextId_in_set(eP->endPointId.topology_id.contextId, cSet);
+			}
+			// Check if the deviceId and endPointUuid are already considered in the graph of the context c
+			struct vertices_t* v = find_vertex_in_graph_context(&c->g, d->deviceId);
+			if (v == NULL) {
+				//DEBUG_PC("  deviceId: %s MUST BE ADDED to the Context Graph", d->deviceId);
+				v = add_vertex_in_graph(&c->g, d);
+			}
+		}
+	}
+	//print_contextSet(cSet);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Determine whether a deviceId is in the targetNode list of a specific vertex v
+ *
+ * @param v
+ * @param deviceId
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct targetNodes_t* find_targeted_vertex_in_graph_context(struct vertices_t* v, gchar *deviceId) {
+	for (gint k = 0; k < v->numTargetedVertices; k++) {
+		struct targetNodes_t* w = &(v->targetedVertices[k]);
+		if (strcmp(w->tVertice.nodeId, deviceId) == 0) {
+			return w;
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Add a deviceId a targetNode of a specific vertex v
+ *
+ * @param v
+ * @param deviceId
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct targetNodes_t* add_targeted_vertex_in_graph_context(struct vertices_t* v, gchar* bDeviceId) {
+	v->numTargetedVertices++;
+	struct targetNodes_t* w = &(v->targetedVertices[v->numTargetedVertices - 1]);
+	duplicate_string(w->tVertice.nodeId, bDeviceId);
+	return w;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Returns the structure of a device endpoint bound to a specific deviceId and endPointId
+ *
+ * @param devId
+ * @param endPointUuid
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct endPoint_t* find_device_tied_endpoint(gchar* devId, gchar* endPointUuid) {
+	//DEBUG_PC("devId: %s ePId: %s", devId, endPointUuid);
+	for (GList* ln = g_list_first(deviceList);
+		ln;
+		ln = g_list_next(ln)) {
+		struct device_t* d = (struct device_t*)(ln->data);
+		if (strcmp(d->deviceId, devId) != 0) {
+			continue;
+		}
+		// Iterate over the endpoints tied to the deviceId
+		for (gint j = 0; j < d->numEndPoints; j++) {
+			struct endPoint_t* eP = &(d->endPoints[j]);
+			//DEBUG_PC("looked endPointId: %s", eP->endPointId.endpoint_uuid);
+			if (strcmp(eP->endPointId.endpoint_uuid, endPointUuid) == 0) {
+				return eP;
+			}
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Adding the edge/linnk in the targetedNodes w list
+ *
+ * @param w
+ * @param l
+ * @param activeFlag
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void add_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l, gint activeFlag) {
+	//DEBUG_PC("\t targetedVertex: %s", w->tVertice.nodeId);
+
+	// Check if the activeFlag is 1. If YES, it is only added to the edges as long as the 
+	// associated endPoint is in status ENABLED, i.e., with operational status set to 2
+	// Get the endpoints (A and Z) of the link l (assumed P2P)
+	struct link_endpointId_t* aEndpointId = &(l->linkEndPointId[0]);
+	struct link_endpointId_t* zEndpointId = &(l->linkEndPointId[1]);
+	// Get the endPoint Information tied to the device bound to aEndPointId
+	struct endPoint_t* eP = find_device_tied_endpoint(aEndpointId->deviceId, aEndpointId->endPointId);
+	if (eP == NULL) {
+		DEBUG_PC("devId: %s endPointUuid: %s NOT in Device List!!--- Weird", aEndpointId->deviceId, aEndpointId->endPointId);
+		exit(-1);
+	}
+	// Check whether the port in that endPoint (eP) is Active upon the activeFlag being SET
+	if (activeFlag == 1) {
+		if (eP->operational_status != 2) // NOT ENABLED, then discard this link
+			return;
+	}
+
+	// Add the edge into the graph
+	w->numEdges++;
+	struct edges_t* e = &(w->edges[w->numEdges - 1]);
+	// Copy the link Id UUID
+	duplicate_string(e->linkId, l->linkId);
+	duplicate_string(e->aNodeId.nodeId, aEndpointId->deviceId);
+	duplicate_string(e->aEndPointId, aEndpointId->endPointId);
+	duplicate_string(e->aTopologyId, aEndpointId->topology_id.topology_uuid);	
+	duplicate_string(e->zNodeId.nodeId, zEndpointId->deviceId);
+	duplicate_string(e->zEndPointId, zEndpointId->endPointId);
+	duplicate_string(e->zTopologyId, zEndpointId->topology_id.topology_uuid);
+	
+	//Potential(total) and available capacity
+	e->unit = eP->potential_capacity.unit;
+	memcpy(&e->totalCap, &eP->potential_capacity.value, sizeof(gdouble));
+	memcpy(&e->availCap, &eP->available_capacity.value, sizeof(gdouble));
+	// Copy interdomain local/remote Ids
+	memcpy(e->interDomain_localId, eP->inter_domain_plug_in.inter_domain_plug_in_local_id, 
+		strlen(eP->inter_domain_plug_in.inter_domain_plug_in_local_id));
+	memcpy(e->interDomain_remoteId, eP->inter_domain_plug_in.inter_domain_plug_in_remote_id,
+		strlen(eP->inter_domain_plug_in.inter_domain_plug_in_remote_id));
+	// cost value
+	memcpy(&e->cost, &l->cost_characteristics.cost_value, sizeof(gdouble));
+	// latency ms
+	memcpy(&e->delay, &l->latency_characteristics.fixed_latency, sizeof(gdouble));
+	// energy J/bits ~ power
+	memcpy(&e->energy, &eP->energyConsumption, sizeof(gfloat));
+	
+	//DEBUG_PC("Edge - Total/Available Capacity: %f/%f; Cost: %f; Delay: %f, Energy: %f", eP->potential_capacity.value, eP->available_capacity.value,
+	//	l->cost_characteristics.cost_value, l->latency_characteristics.fixed_latency, l->energy_link);
+
+	//DEBUG_PC("Graph Edge - Total/Available Capacity: %f/%f; Cost: %f; Delay: %f, Energy: %f", e->totalCap, e->availCap,
+	//	e->cost, e->delay, e->energy);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Searching a specific edge/link by the linkId(UUID)
+ *
+ * @param w
+ * @param l
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct edges_t* find_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l) {		
+	for (gint i = 0; i < w->numEdges; i++) {
+		struct edges_t* e = &(w->edges[i]);
+		if (strcmp(e->linkId, l->linkId) == 0) {
+			return e;
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief supporting the construction of the graph per context using the explicit
+ * contents/info of the link list
+ *
+ * @param set
+ * @param activeFlag
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void build_contextSet_linklList(GList** set, gint activeFlag) {	
+	// for each link in linkList:
+	// 1st- Retrieve endpoints A --> B feauture (context Id, device Id, endpoint Id)
+	// 2st - In the graph associated to the contextId, check wheter A (deviceId) is in the vertices list
+	// o No, this is weird ... exist
+	// o Yes, get the other link endpoint (i.e., B) and check whether it exists. If NOT add it, considering
+	// all the attributes; Otherwise, check whether the link is different from existing edges between A and B
+	gdouble epsilon = 0.1;
+	gint j = 0;
+	for (GList* ln = g_list_first(linkList);
+		ln;
+		ln = g_list_next(ln)) {
+		struct link_t* l = (struct link_t*)(ln->data);
+		j++;
+
+		// link assumed to be P2P A --> B; i.e. 2 endPoints; 1st specifies A and 2nd specifie B
+		struct link_endpointId_t* aEndpointId = &(l->linkEndPointId[0]);
+		struct topology_id_t* topologyId = &(aEndpointId->topology_id);
+		// get the contextId
+		gchar contextUuid[UUID_CHAR_LENGTH];
+		duplicate_string(contextUuid, topologyId->contextId);
+		DEBUG_PC("Link: %s in ContextId: %s", l->linkId, contextUuid);
+
+		// Check first contextUuid exists in the cSet
+		//DEBUG_PC("Length of Context: %d", g_list_length(set));
+		struct context_t* c = find_contextId_in_set(contextUuid, set);
+		if (c == NULL) {
+			DEBUG_PC("ContextId: %s does NOT exist... weird", contextUuid);
+			exit(-1);
+		}
+
+		// get the device ID of A
+		gchar aDeviceId[UUID_CHAR_LENGTH];
+		duplicate_string(aDeviceId, aEndpointId->deviceId);
+
+		struct graph_t* g = &(c->g); // get the graph associated to the context c
+		struct vertices_t* v = find_vertex_in_graph_context(g, aDeviceId);
+		if (v == NULL) {
+			DEBUG_PC("%s NOT a VERTEX of contextId: %s ... WEIRD", aDeviceId, contextUuid);
+			exit(-1);
+		}		
+		// get the bEndpointId
+		struct link_endpointId_t* bEndpointId = &(l->linkEndPointId[1]);
+		gchar bDeviceId[UUID_CHAR_LENGTH];
+		duplicate_string(bDeviceId, bEndpointId->deviceId);
+		DEBUG_PC("[%d] -- Link: %s [%s ==> %s]", j-1, l->linkId, aDeviceId, bDeviceId);
+		// Check whether device B is in the targeted Vertices from A (i.e., v)?
+		// If not, add B in the targeted vertices B + create the edge and add it
+		// If B exist, check whether the explored link/edge is already in the list of edges
+		struct targetNodes_t* w = find_targeted_vertex_in_graph_context(v, bDeviceId);
+		if (w == NULL) {
+			DEBUG_PC("[%s] is PEER of [%s]", bDeviceId, v->verticeId.nodeId);
+			w = add_targeted_vertex_in_graph_context(v, bDeviceId);
+			add_edge_in_targetedVertice_set(w, l, activeFlag);
+		}
+		else {
+			// w exists, it is needed to check whether the edge (link) should be added
+			struct edges_t* e = find_edge_in_targetedVertice_set(w, l);
+			if (e == NULL) {
+				// Add the link into the list
+				add_edge_in_targetedVertice_set(w, l, activeFlag);
+			}
+			else {
+				DEBUG_PC("The link already exists ...");
+				continue;
+			}
+		}
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Create the set of (distinct) contexts with the deviceList and linkList
+ *
+ * @param cSet
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void build_contextSet(GList** cSet) {
+	gint activeFlag = 0; // this means that all the devices/links (regardless they are active or not) are considered
+
+	// devices are tied to contexts, i.e. depending on the contextId of the devices
+	build_contextSet_deviceList(cSet, activeFlag);
+
+	DEBUG_PC("Length for the Context Set: %d", g_list_length(*cSet));
+
+	// Once the diverse contexts are created and the devices/endpoints asigned to the 
+	// respective graph tied to each context, it is needed to create the edges
+	build_contextSet_linklList(cSet, activeFlag);
+
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Create the set of (distinct) contexts with the deviceList and linkList with
+ * operational status active
+ *
+ * @param cSet
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void build_contextSet_active(GList** cSet) {
+	gint activeFlag = 1; // this means that all the devices (regardless they are active or not) are considered
+
+	// devices are tied to contexts, i.e. depending on the contextId of the devices
+	build_contextSet_deviceList(cSet, activeFlag);
+
+	DEBUG_PC("Length for the Context Set: %d", g_list_length(*cSet));
+
+	// Once the diverse contexts are created and the devices/endpoints asigned to the 
+	// respective graph tied to each context, it is needed to create the edges
+	build_contextSet_linklList(cSet, activeFlag);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Print the contents of the ContextIds
+ *
+ * @param set
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_contextSet(GList* set) {
+
+	DEBUG_PC("Printing the ContextSet w/ number of Elements: %d", g_list_length(set));
+
+	for (GList* ln = g_list_first(set);
+		ln;
+		ln = g_list_next(ln)) {
+		struct context_t* c = (struct context_t*)(ln->data);
+		DEBUG_PC("-------------------------------------------------------------");
+		DEBUG_PC(" Context Id: %s", c->contextId);
+		DEBUG_PC("-------------------------------------------------------------");
+
+		struct graph_t* g = &(c->g);
+		for (gint j = 0; j < g->numVertices; j++) {
+			struct vertices_t* v = &(g->vertices[j]);
+			DEBUG_PC("  Head Device Id: %s", v->verticeId.nodeId);
+			for (gint k = 0; k < v->numTargetedVertices; k++) {
+				struct targetNodes_t* w = &(v->targetedVertices[k]);
+				DEBUG_PC("  [%d] --- Peer Device Id: %s", k, w->tVertice.nodeId);
+				for (gint l = 0; l < w->numEdges; l++) {
+					struct edges_t* e = &(w->edges[l]);
+					DEBUG_PC("   \t link Id: %s", e->linkId);
+					DEBUG_PC("   \t aEndPointId: %s", e->aEndPointId);
+					DEBUG_PC("   \t zEndPointId: %s", e->zEndPointId);
+					DEBUG_PC("   \t Available Capacity: %f, Latency: %f, Cost: %f", e->availCap, e->delay, e->cost);
+					DEBUG_PC("   \t aTopologyId: %s", e->aTopologyId);
+					DEBUG_PC("   \t zTopologyId: %s", e->zTopologyId);
+				}
+			}
+		}
+	}
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Check whether src and dst PE nodeId of the req are the same
+ *
+ *	@param r
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+gint same_src_dst_pe_nodeid(struct service_t* s)
+{
+	// Check that source PE and dst PE are NOT the same, i.e., different ingress and egress endpoints (iEp, eEp)
+	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
+	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
+
+	gchar* iEpUUID = iEp->endpoint_uuid;
+	gchar* eEpUUID = eEp->endpoint_uuid;
+	gchar* iDevUUID = iEp->device_uuid;
+	gchar* eDevUUID = eEp->device_uuid;
+
+	// Compare the device uuids
+	if (strcmp(iDevUUID, eDevUUID) != 0) {
+		DEBUG_PC("DIFFERENT --- iDevId: %s and eDevId: %s", iDevUUID, eDevUUID);
+		return 1;
+	}
+	// Compare the endpoints (ports)
+	if (strcmp(iEpUUID, eEpUUID) != 0) {
+		DEBUG_PC("DIFFERENT --- iEpUUID: %s and eEpUUID: %s", iEpUUID, eEpUUID);
+		return 1;
+	}
+	return 0;	
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Handles issues with the route computation
+ *
+ *	@param route
+ *	@param s
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void comp_route_connection_issue_handler (struct compRouteOutput_t *path, struct service_t *s)
+{
+	g_assert(path); g_assert(s);
+
+	// Increase the number of computed routes/paths despite there was an issue to be reported		
+	path->numPaths++;	
+	// Copy the serviceId
+	copy_service_id(&(path->serviceId), &(s->serviceId));
+
+	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
+	for (gint i = 0; i < s->num_service_endpoints_id; i++) {
+		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
+		struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
+		copy_service_endpoint_id(oEp, iEp);
+	}
+	path->num_service_endpoints_id = s->num_service_endpoints_id;
+	path->noPathIssue = NO_PATH_CONS_ISSUE;
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief released the allocated memory fo compRouteOutputList_t
+ *
+ *	@param ro
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void destroy_compRouteOutputList (struct compRouteOutputList_t *ro)
+{
+	g_assert (ro);	
+	g_free (ro);	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief creates a copy of the underlying graph
+ *
+ *	@param originalGraph
+ *	@param destGraph
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void duplicate_graph (struct graph_t *originalGraph, struct graph_t *destGraph)	{
+	g_assert (originalGraph); g_assert (destGraph);
+	
+	destGraph->numVertices = originalGraph->numVertices;
+	for (gint i = 0; i < originalGraph->numVertices; i++) {
+		struct vertices_t *oVertex = &(originalGraph->vertices[i]);
+		struct vertices_t *dVertex = &(destGraph->vertices[i]);
+		dVertex->numTargetedVertices = oVertex->numTargetedVertices;		
+		duplicate_node_id (&oVertex->verticeId, &dVertex->verticeId);
+		memcpy(&dVertex->power_idle, &oVertex->power_idle, sizeof(gdouble));
+		
+		for (gint j = 0; j < oVertex->numTargetedVertices; j++)	{
+			struct targetNodes_t *oTargetedVertex = &(oVertex->targetedVertices[j]);
+			struct targetNodes_t *dTargetedVertex = &(dVertex->targetedVertices[j]);
+			duplicate_node_id (&oTargetedVertex->tVertice, &dTargetedVertex->tVertice);
+			dTargetedVertex->numEdges = oTargetedVertex->numEdges;
+			
+			for (gint k = 0; k < oTargetedVertex->numEdges; k++) {
+				struct edges_t *oEdge = &(oTargetedVertex->edges[k]);
+				struct edges_t *dEdge = &(dTargetedVertex->edges[k]);
+				duplicate_edge (dEdge, oEdge);						
+			}
+		}	
+	}	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to retrieve from the graph the edge instance associated to the
+ * pathLink (pL)
+ *
+ *	@param pL
+ *	@parma g
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct edges_t* get_edge_from_graph_by_linkId(struct pathLink_t* pL, struct graph_t* g) {
+	g_assert(pL);
+	g_assert(g);
+
+	for (gint i = 0; i < g->numVertices; i++) {
+		struct vertices_t* v = &(g->vertices[i]);
+		for (gint j = 0; j < v->numTargetedVertices; j++) {
+			struct targetNodes_t* tv = &(v->targetedVertices[j]);
+			for (gint k = 0; k < tv->numEdges; k++) {
+				struct edges_t* e = &(tv->edges[k]);
+				if (strcmp(e->linkId, pL->linkId) == 0) {
+					return e;
+				}
+			}		
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to retrieve from the graph the reverse edge (rev_e) associated to an edge (e)
+ *
+ *	@param e
+ *	@parma g
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+struct edges_t* get_reverse_edge_from_the_graph(struct edges_t* e, struct graph_t* g) {
+	g_assert(e);
+	g_assert(g);
+
+	for (gint i = 0; i < g->numVertices; i++) {
+		struct vertices_t* v = &(g->vertices[i]);
+		// Check Route Element zNodeId with the v->verticeId
+		if (compare_node_id(&e->zNodeId, &v->verticeId) != 0)
+			continue;
+		// Check Route Element zNodeis with any of reachable targeted vertices from v
+		gboolean foundTargVert = FALSE;
+		gint indexTargVert = -1;
+		for (gint j = 0; j < v->numTargetedVertices; j++) {
+			struct targetNodes_t* tv = &(v->targetedVertices[j]);
+			if (compare_node_id(&e->aNodeId, &tv->tVertice) == 0)
+			{
+				foundTargVert = TRUE;
+				indexTargVert = j;
+				break;
+			}
+		}
+		if (foundTargVert == FALSE) {
+			 continue;
+		}			
+
+		// The targeted vertice is found, then check matching with the endpoints
+		struct targetNodes_t* tv = &(v->targetedVertices[indexTargVert]);
+		for (gint k = 0; k < tv->numEdges; k++) {
+			struct edges_t* rev_e = &(tv->edges[k]);
+			if ((strcmp(rev_e->aEndPointId, e->zEndPointId) == 0) &&
+				(strcmp(rev_e->zEndPointId, e->aEndPointId) == 0)) {
+				return rev_e;
+			}				
+		}
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to reflect in the graph the assigned/allocated resources contained in the path p
+ * 	considering the needs (e.g., bandwidth) of service s
+ *
+ *	@param p
+ *	@param s
+ *	@parma g
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void allocate_graph_resources (struct path_t *p, struct service_t *s, struct graph_t *g)
+{
+	g_assert (p); g_assert (s); g_assert (g);
+	// Retrieve the requested bw by the service
+	struct path_constraints_t* pathCons = get_path_constraints(s);
+
+	for (gint i = 0; i < p->numPathLinks; i++) {
+		struct pathLink_t* pL = &(p->pathLinks[i]);
+		// get the edge associated to the linkId in the graph
+		struct edges_t* e = get_edge_from_graph_by_linkId(pL, g);
+		if (e == NULL) {
+			DEBUG_PC("The linkId: %s is NOT found in the Graph!!!", pL->linkId);
+			exit(-1);
+		}
+		//Update the availBw in the edge
+		gdouble resBw = e->availCap - pathCons->bwConstraint;
+		DEBUG_PC("Updating the Avail Bw @ edge/link: %s", e->linkId);
+		DEBUG_PC("Initial avaiCap @ e/link: %f, demanded Bw: %f, resulting Avail Bw: %f", e->availCap, pathCons->bwConstraint, resBw);
+		memcpy(&e->availCap, &resBw, sizeof(gdouble));
+		DEBUG_PC("Final e/link avail Bw: %f", e->availCap);	
+	}
+	g_free(pathCons);	
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to reflect in the graph the assigned/allocated resources contained in the reverse direction of the path p
+ * 	considering the needs (e.g., bandwidth) of service s
+ *
+ *	@param p
+ *	@param s
+ *	@parma g
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void allocate_graph_reverse_resources(struct path_t* p, struct service_t * s, struct graph_t* g)
+{
+	g_assert(p); g_assert(s); g_assert(g);
+
+	struct path_constraints_t* pathCons = get_path_constraints(s);
+	for (gint i = 0; i < p->numPathLinks; i++) {
+		struct pathLink_t* pL = &(p->pathLinks[i]);
+		struct edges_t* e = get_edge_from_graph_by_linkId(pL, g);
+		if (e == NULL) {
+			DEBUG_PC("The linkId: %s is NOT found in the Graph!!!", pL->linkId);
+			exit(-1);
+		}
+		struct edges_t* rev_e = get_reverse_edge_from_the_graph(e, g);
+		if (rev_e == NULL) {
+			DEBUG_PC("the reverse edge of linkId: %s is NOT found in the Graph!!!", pL->linkId);
+			exit(-1);
+		}
+		//Update the availBw in the edge
+		gdouble resBw = rev_e->availCap - pathCons->bwConstraint;
+		DEBUG_PC("Updating the Avail Bw @ reverse edge/link: %s", rev_e->linkId);
+		DEBUG_PC("Initial avaiCap @ reverse edge e/link: %f, demanded Bw: %f, resulting Avail Bw: %f", rev_e->availCap, pathCons->bwConstraint, resBw);
+		memcpy(&rev_e->availCap, &resBw, sizeof(gdouble));
+		DEBUG_PC("Final reverse edge e/link avail Bw: %f", rev_e->availCap);
+	}
+	g_free(pathCons);
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Function used to printall the computed paths for the requested network connectivity services
+ *
+ *	@param routeList
+ *
+ * 	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void print_path_connection_list(struct compRouteOutputList_t* routeList) {
+	g_assert(routeList);
+	for (gint i = 0; i < routeList->numCompRouteConnList; i++) {
+		DEBUG_PC("==================== Service instance: %d ===================", i);
+		struct compRouteOutput_t* rO = &(routeList->compRouteConnection[i]);
+		DEBUG_PC("num service endpoints: %d", rO->num_service_endpoints_id);
+		struct serviceId_t* s = &(rO->serviceId);
+		DEBUG_PC("ContextId: %s, ServiceId: %s", s->contextId, s->service_uuid);
+		DEBUG_PC("ingress - %s[%s]", rO->service_endpoints_id[0].device_uuid, 
+			rO->service_endpoints_id[0].endpoint_uuid);
+		DEBUG_PC("egress - %s [%s]", rO->service_endpoints_id[1].device_uuid,
+			rO->service_endpoints_id[1].endpoint_uuid);
+
+		if (rO->noPathIssue == NO_PATH_CONS_ISSUE) {
+			DEBUG_PC("NO PATH SUCCESSFULLY COMPUTED");
+			continue;
+		}
+		// Path
+		DEBUG_PC("Number of paths: %d", rO->numPaths);
+		for (gint j = 0; j < rO->numPaths; j++) {
+			struct path_t* p = &(rO->paths[j]);
+			print_path_t(p);
+		}
+	}
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief update statistics for the path computation operations
+ *
+ *  @param routeConnList
+ *	@param d
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct timeval d, gint numSuccesPathComp, gint numPathCompIntents) {
+	g_assert(routeConnList);
+
+	total_path_comp_time.tv_sec = total_path_comp_time.tv_sec + d.tv_sec;
+	total_path_comp_time.tv_usec = total_path_comp_time.tv_usec + d.tv_usec;
+	total_path_comp_time = tv_adjust(total_path_comp_time);
+
+	gdouble path_comp_time_msec = (((total_path_comp_time.tv_sec) * 1000) + ((total_path_comp_time.tv_usec) / 1000));
+	gdouble av_alg_comp_time = ((path_comp_time_msec / numSuccesPathComp));
+	DEBUG_PC("\t --- STATS PATH COMP ----");
+	DEBUG_PC("Succesfully Comp: %d | Path Comp Requests: %d", numSuccesPathComp, numPathCompIntents);
+	DEBUG_PC("AV. PATH COMP ALG. TIME: %f ms", av_alg_comp_time);
+
+	gint i = 0;
+	for (GList* listnode = g_list_first(serviceList);
+		listnode;
+		listnode = g_list_next(listnode), i++) {
+		struct service_t* s = (struct service_t*)(listnode->data);
+		char* eptr;
+		for (gint j = 0; j < s->num_service_constraints; j++) {
+			struct constraint_t* constraints = &(s->constraints[j]);
+			if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) {
+				totalReqBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr));
+			}
+		}
+	}
+
+	for (gint k = 0; k < routeConnList->numCompRouteConnList; k++) {
+		struct compRouteOutput_t* rO = &(routeConnList->compRouteConnection[k]);
+		if (rO->noPathIssue == NO_PATH_CONS_ISSUE) {
+			continue;
+		}
+		// Get the requested service bw bound to that computed path
+		struct path_t* p = &(rO->paths[0]);
+		struct service_t* s = get_service_for_computed_path(rO->serviceId.service_uuid);
+		if (s == NULL) {
+			DEBUG_PC("Weird the service associated to a path is not found");
+			exit(-1);
+		}
+		for (gint l = 0; l < s->num_service_constraints; l++) {
+			struct constraint_t* constraints = &(s->constraints[l]);
+			char* eptr;
+			if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) {
+				totalServedBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr));
+			}
+		}
+	}
+	gdouble avServedRatio = totalServedBw / totalReqBw;
+	DEBUG_PC("AV. Served Ratio: %f", avServedRatio);
+	gdouble avBlockedBwRatio = (gdouble)(1.0 - avServedRatio);
+	DEBUG_PC("AV. BBE: %f", avBlockedBwRatio);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate active service	path
+ *
+ *  @param actServPath
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_active_service_path(struct activeServPath_t* actServPath) {
+	g_assert(actServPath);
+	g_free(actServPath);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate active service
+ *
+ *  @param actService
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_active_service(struct activeService_t* actService) {
+	g_assert(actService);
+	g_list_free_full(g_steal_pointer(&actService->activeServPath), (GDestroyNotify)destroy_active_service_path);
+	g_free(actService);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate a requested service 
+ *
+ *  @param s
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_requested_service(struct service_t* s) {
+	g_assert(s);
+	g_free(s);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate a device
+ *
+ *  @param d
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_device(struct device_t* d) {
+	g_assert(d);
+	g_free(d);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate a link	from the linkList
+ *
+ *  @param d
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_link(struct link_t* l) {
+	g_assert(l);
+	g_free(l);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Eliminate a context from the contextSet
+ *
+ *  @param d
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void destroy_context(struct context_t* c) {
+	g_assert(c);
+	g_free(c);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief Excecution Dijkstra algorithm
+ *
+ *  @param srcMapIndex
+ *  @param dstMapIndex
+ *	@param g
+ *	@param s
+ *  @param mapNodes
+ *  @param SN
+ *  @param RP
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void dijkstra(gint srcMapIndex, gint dstMapIndex, struct graph_t* g, struct service_t* s, 
+	struct map_nodes_t* mapNodes, struct nodes_t* SN, struct compRouteOutputItem_t* RP,
+	guint arg) {
+	g_assert(s);g_assert(g);
+
+	// Set params into mapNodes related to the source nodes of the request
+	mapNodes->map[srcMapIndex].distance = 0.0;
+	mapNodes->map[srcMapIndex].latency = 0.0;
+	mapNodes->map[srcMapIndex].avaiBandwidth = 0.0;
+	mapNodes->map[srcMapIndex].power = 0.0;
+
+	// Initialize the set Q and S
+	GList *S = NULL, *Q = NULL;
+	gint indexVertice = -1;
+
+	//  Add the source into the Q
+	struct nodeItem_t* nodeItem = g_malloc0(sizeof(struct nodeItem_t));
+	if (nodeItem == NULL) {
+		DEBUG_PC("memory allocation failed\n");
+		exit(-1);
+	}
+	// initialize some nodeItem attributes
+	nodeItem->distance = 0.0;
+	nodeItem->latency = 0.0;
+	nodeItem->power = 0.0;
+	duplicate_node_id(&mapNodes->map[srcMapIndex].verticeId, &nodeItem->node);
+
+	// Select the optimization process
+	if (arg & ENERGY_EFFICIENT_ARGUMENT)
+		Q = g_list_insert_sorted(Q, nodeItem, sort_by_energy);
+	// more "if" according to different optimization criteria ...
+	else
+		Q = g_list_insert_sorted(Q, nodeItem, sort_by_distance);
+
+	// Check whether there is spurNode (SN) and rootPath (RP)
+	if (SN != NULL && RP != NULL) {
+		struct routeElement_t* re;
+		for (gint j = 0; j < RP->numRouteElements; j++) {
+			// Get the source and target Nodes of the routeElement within the rootPath
+			re = &RP->routeElement[j];
+			DEBUG_PC("root Link: aNodeId: %s (%s) --> zNodeiId: %s (%s)", re->aNodeId.nodeId, re->aEndPointId, re->zNodeId.nodeId, re->zEndPointId);
+
+			// if ingress of the root link (aNodeId) is the spurNode, then stops
+			if (compare_node_id(&re->aNodeId, SN) == 0) {
+				DEBUG_PC("root Link: aNodeId: %s and spurNode: %s -- stop exploring the rootPath (RP)", re->aNodeId.nodeId, SN->nodeId);
+				break;
+			}
+			// Extract from Q
+			GList* listnode = g_list_first(Q);
+			struct nodeItem_t* node = (struct nodeItem_t*)(listnode->data);
+			Q = g_list_remove(Q, node);
+
+			//DEBUG_RL_RA ("Exploring node %s", node->node.nodeId);
+			indexVertice = graph_vertice_lookup(node->node.nodeId, g);
+			g_assert(indexVertice >= 0);
+
+			// Get the indexTargetedVertice
+			gint indexTVertice = -1;
+			indexTVertice = graph_targeted_vertice_lookup(indexVertice, re->zNodeId.nodeId, g);
+			gint done = check_link(node, indexVertice, indexTVertice, g, s, &S, &Q, mapNodes, arg);
+			(void)done;
+			// Add to the S list
+			S = g_list_append(S, node);
+		}
+		// Check that the first node in Q set is SpurNode, otherwise something went wrong ...
+		if (compare_node_id(&re->aNodeId, SN) != 0) {
+			//DEBUG_PC ("root Link: aNodeId: %s is NOT the spurNode: %s -- something wrong", re->aNodeId.nodeId, SN->nodeId);
+			g_list_free_full(g_steal_pointer(&S), g_free);
+			g_list_free_full(g_steal_pointer(&Q), g_free);
+			return;
+		}
+	}
+
+	while (g_list_length(Q) > 0) {
+		//Extract from Q set
+		GList* listnode = g_list_first(Q);
+		struct nodeItem_t* node = (struct nodeItem_t*)(listnode->data);
+		Q = g_list_remove(Q, node);
+		DEBUG_PC("Q length: %d", g_list_length(Q));
+		DEBUG_PC("DeviceId: %s", node->node.nodeId);
+
+		// visit all the links from u within the graph
+		indexVertice = graph_vertice_lookup(node->node.nodeId, g);
+		g_assert(indexVertice >= 0);
+
+		// Check the targeted vertices from u
+		for (gint i = 0; i < g->vertices[indexVertice].numTargetedVertices; i++) {
+			gint done = check_link(node, indexVertice, i, g, s, &S, &Q, mapNodes, arg);
+			(void)done;
+		}
+		// Add node into the S Set
+		S = g_list_append(S, node);
+		//DEBUG_PC ("S length: %d", g_list_length (S));              
+	}
+	g_list_free_full(g_steal_pointer(&S), g_free);
+	g_list_free_full(g_steal_pointer(&Q), g_free);
+	return;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief KSP computation using Dijkstra algorithm
+ *
+ *  @param pred
+ *  @param g
+ *	@param s
+  *	@param SN
+ *	@param RP
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+gint ksp_comp(struct pred_t* pred, struct graph_t* g, struct service_t* s,
+	struct nodes_t* SN, struct compRouteOutputItem_t* RP, 
+	struct map_nodes_t* mapNodes, guint arg) {
+	g_assert(pred); g_assert(g); g_assert(s);
+
+	DEBUG_PC("Source: %s -- Destination: %s", s->service_endpoints_id[0].device_uuid, s->service_endpoints_id[1].device_uuid);
+
+	// Check the both ingress src and dst endpoints are in the graph
+	gint srcMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[0].device_uuid, mapNodes);
+	if (srcMapIndex == -1) {
+		DEBUG_PC("ingress DeviceId: %s NOT in the graph", s->service_endpoints_id[0].device_uuid);
+		return -1;
+	}
+	
+	gint dstMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
+	if (dstMapIndex == -1) {
+		DEBUG_PC("egress DeviceId: %s NOT in the graph", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+
+	//DEBUG_PC("srcMapIndex: %d (node: %s)", srcMapIndex, mapNodes->map[srcMapIndex].verticeId.nodeId);
+	//DEBUG_PC("dstMapIndex: %d (node: %s)", dstMapIndex, mapNodes->map[dstMapIndex].verticeId.nodeId);
+
+	// Compute the shortest path route
+	dijkstra(srcMapIndex, dstMapIndex, g, s, mapNodes, SN, RP, arg);
+
+	// Check that a feasible solution in term of latency and bandwidth is found
+	gint map_dstIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes);
+	struct map_t* dest_map = &mapNodes->map[map_dstIndex];
+	if (!(dest_map->distance < INFINITY_COST)) {
+		DEBUG_PC("destination: %s NOT reachable", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+
+	DEBUG_PC("AvailBw @ %s is %f", dest_map->verticeId.nodeId, dest_map->avaiBandwidth);
+	// Check that the computed available bandwidth is larger than 0.0
+	if (dest_map->avaiBandwidth <= (gfloat)0.0) {
+		DEBUG_PC("dst: %s NOT REACHABLE", s->service_endpoints_id[1].device_uuid);
+		return -1;
+	}
+	DEBUG_PC("dst: %s REACHABLE", s->service_endpoints_id[1].device_uuid);
+	// Handle predecessors
+	build_predecessors(pred, s, mapNodes);
+	return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief set the path parameters (e.g., latency, cost, power, ...) to an under-constructed
+ * path from the computed map vertex
+ *
+ *  @param p
+ *  @param mapV
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void set_path_attributes(struct compRouteOutputItem_t* p, struct map_t* mapV) {
+	g_assert(p); g_assert(mapV);
+	memcpy(&p->cost, &mapV->distance, sizeof(gdouble));
+	memcpy(&p->availCap, &mapV->avaiBandwidth, sizeof(mapV->avaiBandwidth));
+	memcpy(&p->delay, &mapV->latency, sizeof(mapV->latency));
+	memcpy(&p->power, &mapV->power, sizeof(gdouble));
+	return;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	@file pathComp_tools.c
+ * 	@brief K-CSPF algorithm execution (YEN algorithm)
+ *
+ *  @param s
+ *  @param path
+ *  @param g
+ *  @param optimization_flag
+ *
+ *	@author Ricardo Martínez <ricardo.martinez@cttc.es>
+ *	@date 2022
+ */
+ /////////////////////////////////////////////////////////////////////////////////////////
+void alg_comp(struct service_t* s, struct compRouteOutput_t* path, struct graph_t* g, guint arg) {
+	g_assert(s); g_assert(path); g_assert(g);
+
+	// create map of devices/nodes to handle the path computation using the context
+	struct map_nodes_t* mapNodes = create_map_node();
+	build_map_node(mapNodes, g);
+
+	// predecessors to store the computed path    
+	struct pred_t* predecessors = create_predecessors();
+	struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]);
+	struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]);
+
+	// Compute the 1st KSP path
+	gint done = ksp_comp(predecessors, g, s, NULL, NULL, mapNodes, arg);
+	if (done == -1) {
+		DEBUG_PC("NO PATH for %s[%s] --> %s[%s]", iEp->device_uuid, iEp->endpoint_uuid, eEp->device_uuid, eEp->endpoint_uuid);
+		comp_route_connection_issue_handler(path, s);
+		g_free(mapNodes); g_free(predecessors);
+		return;
+	}
+
+	// Construct the path from the computed predecessors
+	struct compRouteOutputItem_t* p = create_path_item();
+	//print_predecessors(predecessors);
+	build_path(p, predecessors, s);
+	gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
+	struct map_t* dst_map = &mapNodes->map[indexDest];
+	// Get the delay and cost
+	set_path_attributes(p, dst_map);		
+
+	// Add the computed path, it may be a not feasible path, but at the end it is
+	// checked all the feasible paths, and select the first one
+	print_path(p);
+	
+	// Copy the serviceId
+	copy_service_id(&path->serviceId, &s->serviceId);
+	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
+	for (gint i = 0; i < s->num_service_endpoints_id; i++) {
+		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]);
+		struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]);
+		copy_service_endpoint_id(oEp, iEp);
+	}
+	path->num_service_endpoints_id = s->num_service_endpoints_id;
+
+	DEBUG_PC("COMPUTE UP TO K Feasible Paths A[%d]", MAX_KSP_VALUE);	
+	// Create A and B sets of paths to handle the YEN algorithm
+	struct path_set_t *A = create_path_set(), *B = create_path_set();
+	// Add 1st Computed path into A->paths[0]	
+	duplicate_path(p, &A->paths[0]);
+	A->numPaths++;
+	g_free(predecessors); g_free(p);
+	for (gint k = 1; k < MAX_KSP_VALUE; k++) {
+		DEBUG_PC("*************************** kth (%d) ***********************************", k);
+		struct compRouteOutputItem_t* p = create_path_item();
+		duplicate_path(&A->paths[k - 1], p);
+		// The spurNode ranges from near-end node of the first link to the near-end of the last link forming the kth path
+		gint i = 0;
+		struct compRouteOutputItem_t* rootPath = create_path_item();
+		for (i = 0; i < p->numRouteElements; i++) {
+			struct nodes_t *spurNode = create_node(), *nextSpurNode = create_node();
+			struct routeElement_t* re = &(p->routeElement[i]);
+			// Create predecessors to store the computed path
+			struct pred_t* predecessors = create_predecessors();
+			// Clear previous mapNodes, i.e. create it again
+			g_free(mapNodes);
+			mapNodes = create_map_node();
+			build_map_node(mapNodes, g);
+			struct nodes_t* n = &re->aNodeId;
+			duplicate_node_id(n, spurNode);
+			n = &re->zNodeId;
+			duplicate_node_id(n, nextSpurNode);
+			DEBUG_PC("spurNode: %s --> nextSpurNode: %s", spurNode->nodeId, nextSpurNode->nodeId);
+
+			// rootPath contains a set of links of A[k-1] from the source Node till the SpurNode -> NextSpurNode
+			// Example: A[k-1] = {L1, L2, L3, L4}, i.e. " Node_a -- L1 --> Node_b -- L2 --> Node_c -- L3 --> Node_d -- L4 --> Node_e "
+			// E.g., for the ith iteration if the spurNode = Node_c and NextSpurNode = Node_d; then rootPath = {L1, L2, L3}			
+			add_routeElement_path_back(re, rootPath);
+			DEBUG_PC("\n");
+			DEBUG_PC("^^^^^^^rootPath^^^^^^^");
+			print_path(rootPath);
+
+			// For all existing and computed paths p in A check if from the source to the NextSpurNode
+			// the set of links matches with those contained in the rootPath
+			// If YES, remove from the auxiliary graph the next link in p from NextSpurNode
+			// Otherwise do nothing 
+			struct graph_t* gAux = create_graph();
+			duplicate_graph(g, gAux);
+			// Modified graph
+			modify_targeted_graph(gAux, A, rootPath, spurNode);
+
+			// Trigger the computation of the path from src to dst constrained to traverse all the links from src 
+			// to spurNode contained into rootPath over the resulting graph			
+			if (ksp_comp(predecessors, gAux, s, spurNode, rootPath, mapNodes, arg) == -1) {
+				DEBUG_PC("FAILED SP from %s via spurNode: %s to %s", iEp->device_uuid, spurNode->nodeId, eEp->device_uuid);
+				g_free(nextSpurNode); g_free(spurNode);
+				g_free(gAux); g_free(predecessors);
+				continue;
+			}
+			DEBUG_PC("SUCCESFUL SP from %s via spurNode: %s to %s", iEp->device_uuid, spurNode->nodeId, eEp->device_uuid);
+			// Create the node list from the predecessors
+			struct compRouteOutputItem_t* newKpath = create_path_item();
+			build_path(newKpath, predecessors, s);
+			DEBUG_PC("new K (for k: %d) Path is built", k);
+			gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes);
+			struct map_t* dst_map = &mapNodes->map[indexDest];
+			set_path_attributes(newKpath, dst_map);
+			DEBUG_PC("New PATH (@ kth: %d) ADDED to B[%d] - {Path Cost: %f, e2e latency: %f, bw: %f, Power: %f ", k, B->numPaths, newKpath->cost, 
+													newKpath->delay, newKpath->availCap, newKpath->power);
+			// Add the computed kth SP to the heap B
+			duplicate_path(newKpath, &B->paths[B->numPaths]);
+			B->numPaths++;
+			DEBUG_PC("Number of B paths: %d", B->numPaths);
+
+			g_free(newKpath); g_free(nextSpurNode); g_free(spurNode);
+			g_free(gAux); g_free(predecessors);
+		}
+		// If B is empty then stops
+		if (B->numPaths == 0) {
+			DEBUG_PC("B does not have any path ... the stops kth computation");
+			break;
+		}
+
+		// Sort the potential B paths according to different optimization parameters
+		sort_path_set(B, arg);
+		// Add the lowest path into A[k]		
+		DEBUG_PC("-------------------------------------------------------------");
+		DEBUG_PC("Append SP for B[0] to A[%d] --- Cost: %f, Latency: %f, Power: %f", A->numPaths, B->paths[0].cost, 
+																				B->paths[0].delay, B->paths[0].power);
+		duplicate_path(&B->paths[0], &A->paths[A->numPaths]);
+		A->numPaths++;
+		DEBUG_PC("A Set size: %d", A->numPaths);
+		DEBUG_PC("-------------------------------------------------------------");
+
+		// Remove/Pop front element from the path set B (i.e. remove B[0])
+		pop_front_path_set(B);
+		DEBUG_PC("B Set Size: %d", B->numPaths);
+	}
+
+	// Copy the serviceId
+	copy_service_id(&path->serviceId, &s->serviceId);
+	// copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services)
+	for (gint m = 0; m < s->num_service_endpoints_id; m++) {
+		struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[m]);
+		struct service_endpoints_id_t* oEp = &(s->service_endpoints_id[m]);
+		copy_service_endpoint_id(oEp, iEp);
+	}
+
+	// Print all the paths i A
+	for (gint h = 0; h < A->numPaths; h++) {
+		DEBUG_PC("================== A[%d] =======================", h);
+		print_path(&A->paths[h]);
+	}
+	DEBUG_PC("Number of paths: %d", path->numPaths);
+	// For all the computed paths in A, pick the one being feasible wrt the service constraints
+	for (gint ksp = 0; ksp < A->numPaths; ksp++) {
+		if (ksp >= MAX_KSP_VALUE) {
+			DEBUG_PC("Number Requested paths (%d) REACHED - STOP", ksp);
+			break;
+		}
+		gdouble feasibleRoute = check_computed_path_feasability(s, &A->paths[ksp]);
+		if (feasibleRoute == TRUE) {
+			DEBUG_PC("A[%d] available: %f, pathCost: %f; latency: %f, Power: %f", ksp, A->paths[ksp].availCap, A->paths[ksp].cost, A->paths[ksp].delay, A->paths[ksp].power);
+			struct compRouteOutputItem_t* pathaux = &A->paths[ksp];
+			path->numPaths++;
+			struct path_t* targetedPath = &path->paths[path->numPaths - 1];
+			duplicate_path_t(pathaux, targetedPath);
+			print_path_t(targetedPath);
+			remove_path_set(A);
+			remove_path_set(B);
+			return;
+		}
+	}
+	remove_path_set(A);
+	remove_path_set(B);
+	// No paths found --> Issue	
+	DEBUG_PC("K-SP failed!!!");
+	comp_route_connection_issue_handler(path, s);
+	return;
 }
\ No newline at end of file
diff --git a/src/pathcomp/backend/pathComp_tools.h b/src/pathcomp/backend/pathComp_tools.h
index 84334eb5e1d47199e8a71bb09c3b541625d66af2..ce78f009bd487bc6d8d9276adca4a9c4b9b1b427 100644
--- a/src/pathcomp/backend/pathComp_tools.h
+++ b/src/pathcomp/backend/pathComp_tools.h
@@ -1,620 +1,624 @@
-/*
- * Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _PATHCOMP_TOOLS_H
-#define _PATHCOMP_TOOLS_H
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib-2.0/glib/gtypes.h>
-#include <uuid/uuid.h>
-
-// External variables
-extern GList* contextSet;
-extern GList* linkList;
-extern GList* deviceList;
-extern GList* serviceList;
-extern GList* activeServList;
-
-//////////////////////////////////////////////////////////
-// Optimization computation argument 
-//////////////////////////////////////////////////////////
-#define NO_OPTIMIZATION_ARGUMENT		0x00000000
-#define ENERGY_EFFICIENT_ARGUMENT		0x00000001
-
-#define INFINITY_COST                   0xFFFFFFFF
-#define MAX_NUM_PRED					100
-
-#define MAX_KSP_VALUE					3
-
-// HTTP RETURN CODES
-#define HTTP_CODE_OK					200
-#define HTTP_CODE_CREATED 				201
-#define HTTP_CODE_BAD_REQUEST    		400
-#define HTTP_CODE_UNAUTHORIZED   		401
-#define HTTP_CODE_FORBIDDEN      		403
-#define HTTP_CODE_NOT_FOUND				404
-#define HTTP_CODE_NOT_ACCEPTABLE		406
-
-#define MAX_NODE_ID_SIZE				37 // UUID 128 Bits - In hexadecimal requires 36 char
-#define MAX_CONTEXT_ID					37
-//#define UUID_CHAR_LENGTH				37
-#define UUID_CHAR_LENGTH				100
-struct nodes_t {
-	gchar nodeId[UUID_CHAR_LENGTH];
-};
-
-struct nodeItem_t {
-    struct nodes_t node;
-    gdouble distance; // traversed distance
-	gdouble latency; // incured latency
-	gdouble power; //consumed power
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Structures for collecting the RL topology including: intra WAN topology and inter-WAN links
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#define MAX_INTER_DOMAIN_PLUG_IN_SIZE					128
-struct edges_t {	
-	//aNodeId/Device Id
-	struct nodes_t aNodeId;	
-	//zNodeId/Device Id
-	struct nodes_t zNodeId;	
-	
-	// UUID of the endPointIds
-	gchar aEndPointId[UUID_CHAR_LENGTH];
-	gchar zEndPointId[UUID_CHAR_LENGTH];
-
-	// UUID of the link
-	gchar linkId[UUID_CHAR_LENGTH];
-
-	// Potential(total) and available capacity
-	gint unit;
-	gdouble totalCap, availCap;
-	
-	gdouble cost;	
-	gdouble delay;
-	gdouble energy;
-
-	// inter-domain local and remote Ids
-	gchar interDomain_localId[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
-	gchar interDomain_remoteId[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
-
-	gchar aTopologyId[UUID_CHAR_LENGTH];
-	gchar zTopologyId[UUID_CHAR_LENGTH];
-};
-
-// Structure to handle the path computation
-struct pred_comp_t {
-	struct nodes_t v;
-	struct edges_t e;	
-};
-
-struct pred_t {
-    struct pred_comp_t predComp[MAX_NUM_PRED];
-    gint numPredComp;
-};
-
-// Structures for the managing the path computation algorithm
-struct map_t {
-	struct nodes_t verticeId;
-	struct edges_t predecessor;
-	gdouble distance;
-	gdouble avaiBandwidth;
-	gdouble latency;
-	gdouble power;
-};
-
-#define MAX_MAP_NODE_SIZE				100
-struct map_nodes_t {
-    struct map_t map[MAX_MAP_NODE_SIZE];
-    gint numMapNodes;
-};
-
-#define MAX_NUM_VERTICES				100 // 100 # LGR: reduced from 100 to 20 to divide by 5 the memory used
-#define MAX_NUM_EDGES					5 // 100 # LGR: reduced from 100 to 5 to divide by 20 the memory used
-// Structures for the graph composition
-struct targetNodes_t {
-	// remote / targeted node
-	struct nodes_t tVertice;
-	// edge conencting a pair of vertices
-	struct edges_t edges[MAX_NUM_EDGES];	
-	gint numEdges; 
-};
-
-struct vertices_t {
-	struct targetNodes_t targetedVertices[MAX_NUM_VERTICES];
-	gint numTargetedVertices;
-    struct nodes_t verticeId;
-	gdouble power_idle; // power idle of the device (due to the fans, etc.)
-};
-
-struct graph_t {
-	struct vertices_t vertices[MAX_NUM_VERTICES];
-	gint numVertices;	
-};
-
-////////////////////////////////////////////////////
-// Structure for the Set of Contexts
-///////////////////////////////////////////////////
-struct context_t {
-	gchar contextId[UUID_CHAR_LENGTH]; // UUID char format 36 chars
-	// conext Id has a graph associated
-	struct graph_t g;
-};
-
-#define MAX_ALG_ID_LENGTH		10
-////////////////////////////////////////////////////
-// External Variables
-///////////////////////////////////////////////////
-extern gchar algId[MAX_ALG_ID_LENGTH];
-
-////////////////////////////////////////////////////
-// Structure for the Requested Transport Connectivity Services
-///////////////////////////////////////////////////
-#define SERVICE_TYPE_UNKNOWN			0
-#define SERVICE_TYPE_L3NM				1
-#define SERVICE_TYPE_L2NM				2
-#define SERVICE_TYPE_TAPI				3
-
-///////////////////////////////////////////////////////////////////
-// Structure for the topology_id
-///////////////////////////////////////////////////////////////////
-struct topology_id_t {
-	gchar contextId[UUID_CHAR_LENGTH];
-	gchar topology_uuid[UUID_CHAR_LENGTH];
-};
-
-struct inter_domain_plug_in_t {
-	gchar inter_domain_plug_in_local_id[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
-	gchar inter_domain_plug_in_remote_id[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the endPointId
-///////////////////////////////////////////////////////////////////
-struct endPointId_t {
-	struct topology_id_t topology_id;
-	gchar device_id[UUID_CHAR_LENGTH];
-	gchar endpoint_uuid[UUID_CHAR_LENGTH];
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the endPoint
-///////////////////////////////////////////////////////////////////
-#define CAPACITY_UNIT_TB									0
-#define CAPACITY_UNIT_TBPS									1
-#define CAPACITY_UNIT_GB									2
-#define CAPACITY_UNIT_GBPS									3
-#define CAPACITY_UNIT_MB									4
-#define CAPACITY_UNIT_MBPS									5
-#define CAPACITY_UNIT_KB									6
-#define CAPACITY_UNIT_KBPS									7
-#define CAPACITY_UNIT_GHZ									8
-#define CAPACITY_UNIT_MHZ									9
-struct capacity_t {
-	gdouble value;
-	gint unit;
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the endPoint
-///////////////////////////////////////////////////////////////////
-#define MAX_ENDPOINT_TYPE_SIZE								128
-// Link Port Direction
-#define LINK_PORT_DIRECTION_BIDIRECTIONAL					0
-#define LINK_PORT_DIRECTION_INPUT							1
-#define LINK_PORT_DIRECTION_OUTPUT							2
-#define LINK_PORT_DIRECTION_UNKNOWN							3
-// Termination Direction
-#define TERMINATION_DIRECTION_BIDIRECTIONAL					0
-#define TERMINATION_DIRECTION_SINK							1
-#define TERMINATION_DIRECTION_SOURCE						2
-#define TERMINATION_DIRECTION_UNKNOWN						3
-// Termination State
-#define TERMINATION_STATE_CAN_NEVER_TERMINATE				0
-#define TERMINATION_STATE_NOT_TERMINATED					1
-#define TERMINATION_STATE_TERMINATED_SERVER_TO_CLIENT_FLOW	2
-#define TERMINATION_STATE_TERMINATED_CLIENT_TO_SERVER_FLOW	3
-#define TERMINATION_STATE_TERMINATED_BIDIRECTIONAL			4
-
-struct endPoint_t {
-	struct endPointId_t endPointId;
-	gchar endpointType[MAX_ENDPOINT_TYPE_SIZE];
-	guint link_port_direction;
-	guint termination_direction;
-	guint termination_state;
-	struct capacity_t potential_capacity;
-	struct capacity_t available_capacity;
-	// inter-domain identifiers
-	struct inter_domain_plug_in_t inter_domain_plug_in;
-	gfloat energyConsumption; // in nJ/bit
-	gint operational_status; // 0 Undefined, 1 Disabled, 2 Enabled
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the device contents
-///////////////////////////////////////////////////////////////////
-#define MAX_DEV_TYPE_SIZE				128
-#define MAX_DEV_ENDPOINT_LENGTH			100	// 10 # LGR: controllers might have large number of endpoints
-struct device_t {
-	gdouble power_idle; // power idle (baseline) of the switch in Watts
-	gint operational_status; // 0 - Undefined, 1 - Disabled, 2 - Enabled
-	gchar deviceId[UUID_CHAR_LENGTH]; // device ID using UUID (128 bits)
-	gchar deviceType[MAX_DEV_TYPE_SIZE]; // Specifies the device type
-	// define the endpoints attached to the device
-	gint numEndPoints;
-	struct endPoint_t endPoints[MAX_DEV_ENDPOINT_LENGTH];
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the link EndPoint Id
-///////////////////////////////////////////////////////////////////
-struct link_endpointId_t {
-	struct topology_id_t topology_id;
-	gchar deviceId[UUID_CHAR_LENGTH];  // Device UUID
-	gchar endPointId[UUID_CHAR_LENGTH];	// Link EndPoint UUID
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the link cost characteristics
-///////////////////////////////////////////////////////////////////
-#define LINK_COST_NAME_SIZE								128
-struct cost_characteristics_t {
-	gchar cost_name[LINK_COST_NAME_SIZE];
-	gdouble cost_value;
-	gdouble cost_algorithm;
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the latency characteristics of the link
-///////////////////////////////////////////////////////////////////
-struct latency_characteristics_t {
-	gdouble fixed_latency;
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the latency characteristics of the link
-///////////////////////////////////////////////////////////////////
-struct power_characteristics_t {
-	gdouble power;
-};
-
-///////////////////////////////////////////////////////////////////
-// Structure for the link 
-///////////////////////////////////////////////////////////////////
-#define MAX_NUM_LINK_ENDPOINT_IDS								2
-
-#define LINK_FORWARDING_DIRECTION_BIDIRECTIONAL					0
-#define LINK_FORWARDING_DIRECTION_UNIDIRECTIONAL				1
-#define LINK_FORWARDING_DIRECTION_UNKNOWN						2
-struct link_t {
-	gchar linkId[UUID_CHAR_LENGTH]; // link Id using UUID (128 bits)
-	//gdouble energy_link; // in nJ/bit
-	//gint operational_status; // 0 Undefined, 1 Disabled, 2 Enabled
-	gint numLinkEndPointIds;
-	struct link_endpointId_t linkEndPointId[MAX_NUM_LINK_ENDPOINT_IDS];
-	guint forwarding_direction;
-	struct capacity_t potential_capacity;
-	struct capacity_t available_capacity;
-	struct cost_characteristics_t cost_characteristics;
-	struct latency_characteristics_t latency_characteristics;
-};
-
-////////////////////////////////////////////////////
-// Structure for service Identifier
-///////////////////////////////////////////////////
-struct serviceId_t {
-	gchar contextId[UUID_CHAR_LENGTH];
-	gchar service_uuid[UUID_CHAR_LENGTH];
-};
-
-////////////////////////////////////////////////////
-// Structure the service endpoint ids
-///////////////////////////////////////////////////
-struct service_endpoints_id_t {
-	struct topology_id_t topology_id;
-	gchar device_uuid[UUID_CHAR_LENGTH];
-	gchar endpoint_uuid[UUID_CHAR_LENGTH];
-};
-
-////////////////////////////////////////////////////
-// Structure for handling generic targeted service constraints
-////////////////////////////////////////////////////
-#define MAX_CONSTRAINT_SIZE					128
-// Constraint Type: bandwidth, latency, energy, cost
-struct constraint_t {
-	gchar constraint_type[MAX_CONSTRAINT_SIZE];
-	gchar constraint_value[MAX_CONSTRAINT_SIZE];
-};
-
-////////////////////////////////////////////////////
-// Structure for individual service request
-////////////////////////////////////////////////////
-#define SERVICE_TYPE_UNKNOWN					0
-#define SERVICE_TYPE_L3NM						1
-#define SERVICE_TYPE_L2NM						2
-#define SERVICE_TYPE_TAPI						3
-
-#define MAX_NUM_SERVICE_ENPOINTS_ID				2
-
-#define MAX_NUM_SERVICE_CONSTRAINTS				10
-struct service_t {
-	// Indentifier used to determine the used Algorithm Id, e.g., KSP
-	gchar algId[MAX_ALG_ID_LENGTH];
-	// PATHS expected for the output
-	guint kPaths;
-	
-	struct serviceId_t serviceId;
-	guint service_type;	 // unknown, l2nm, l3nm, tapi
-
-	// endpoints of the network connectivity service, assumed p2p
-	// the 1st one assumed to be the source (ingress) and the 2nd one is the sink (egress)
-	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
-	guint num_service_endpoints_id;
-
-	// Service Constraints
-	struct constraint_t constraints[MAX_NUM_SERVICE_CONSTRAINTS];
-	guint num_service_constraints;
-};
-
-////////////////////////////////////////////////////
-// Structure to handle path constraints during computation
-////////////////////////////////////////////////////
-struct path_constraints_t {
-	gdouble bwConstraint;
-	gboolean bw;
-
-	gdouble costConstraint;
-	gboolean cost;
-
-	gdouble latencyConstraint;
-	gboolean latency;
-
-	gdouble energyConstraint;
-	gboolean energy;
-};
-
-////////////////////////////////////////////////////
-// Structure for the handling the service requests
-///////////////////////////////////////////////////
-//#define MAX_SERVICE_LIST						100
-//struct serviceList_t {
-//	struct service_t services[MAX_SERVICE_LIST];
-//	gint numServiceList;	
-//};
-
-////////////////////////////////////////////////////
-// Structure for the handling the active services 
-///////////////////////////////////////////////////
-struct activeServPath_t {
-	struct topology_id_t topology_id;
-	gchar deviceId[UUID_CHAR_LENGTH];
-	gchar endPointId[UUID_CHAR_LENGTH];
-};
-
-struct activeService_t {
-	struct serviceId_t serviceId;
-	guint service_type;	 // unknown, l2nm, l3nm, tapi
-	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
-	guint num_service_endpoints_id;
-	GList* activeServPath;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Structure describing the links forming a computed path
-////////////////////////////////////////////////////////////////////////////////////////////
-struct linkTopology_t {
-	gchar topologyId[UUID_CHAR_LENGTH];
-};
-
-struct pathLink_t {
-	gchar linkId[UUID_CHAR_LENGTH]; // link id UUID in char format
-
-	gchar aDeviceId[UUID_CHAR_LENGTH];
-	gchar zDeviceId[UUID_CHAR_LENGTH];
-	gchar aEndPointId[UUID_CHAR_LENGTH];
-	gchar zEndPointId[UUID_CHAR_LENGTH];
-
-	struct topology_id_t topologyId;
-	struct linkTopology_t linkTopologies[2]; // a p2p link (at most) can connect to devices (endpoints) attached to 2 different topologies
-	gint numLinkTopologies;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Structure describing a computed path
-////////////////////////////////////////////////////////////////////////////////////////////
-#define MAX_ROUTE_ELEMENTS  50
-struct routeElement_t {
-	//aNodeId/Device Id
-	struct nodes_t aNodeId;
-	//zNodeId/Device Id
-	struct nodes_t zNodeId;
-
-	// UUID of the endPointIds
-	gchar aEndPointId[UUID_CHAR_LENGTH];
-	gchar zEndPointId[UUID_CHAR_LENGTH];
-
-	// UUID of the link
-	gchar linkId[UUID_CHAR_LENGTH];
-
-	gchar aTopologyId[UUID_CHAR_LENGTH];
-	gchar zTopologyId[UUID_CHAR_LENGTH];
-
-	// contextId
-	gchar contextId[UUID_CHAR_LENGTH];
-};
-
-struct compRouteOutputItem_t {	
-	gint unit;
-	gdouble totalCap, availCap;
-
-	gdouble cost;
-	gdouble delay;
-	gdouble power;
-
-	struct routeElement_t routeElement[MAX_ROUTE_ELEMENTS];
-	gint numRouteElements;
-};
-
-#define MAX_NUM_PATHS		30
-struct path_set_t {
-	struct compRouteOutputItem_t paths[MAX_NUM_PATHS];
-	gint numPaths;
-};
-
-#define MAX_NUM_PATH_LINKS						20
-struct path_t {
-	struct capacity_t path_capacity;
-	struct latency_characteristics_t path_latency;
-	struct cost_characteristics_t path_cost;
-	struct power_characteristics_t path_power;
-
-	struct pathLink_t pathLinks[MAX_NUM_PATH_LINKS];
-	guint numPathLinks;
-};
-
-#define NO_PATH_CONS_ISSUE								1	 // No path due to a constraint issue
-#define MAX_NUM_COMPUTED_PATHS							10
-struct compRouteOutput_t {
-	// object describing the service identifier: serviceId and contextId
-	struct serviceId_t serviceId;
-	// array describing the service endpoints ids
-	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
-	guint num_service_endpoints_id;
-	struct path_t paths[MAX_NUM_COMPUTED_PATHS];
-	gint numPaths;	
-	// if the transport connectivity service cannot be computed, this value is set to 0 determining the constraints were not fulfilled
-	gint noPathIssue;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Structure to handle the response list with all the computed network connectivity services
-////////////////////////////////////////////////////////////////////////////////////////////
-#define MAX_COMP_CONN_LIST		100
-struct compRouteOutputList_t {
-	struct compRouteOutput_t compRouteConnection[MAX_COMP_CONN_LIST];
-	gint numCompRouteConnList;
-
-	///////////////// Metrics //////////////////////////////////////////
-	// Number of total succesfully computed connections, i.e., at least 1 feasible path exists
-	// for every connection in the list
-	gint compRouteOK;
-	// For the succesfully newly computed/recovered/re-allocated/re-optimized connections, this 
-	// metric determines the average allocable bandwidth over all the (re-)computed paths for the succesfully 
-	// (i.e., feasible path) connections
-	gdouble compRouteConnAvBandwidth;
-	// For the succesfully newly computed/recovered/re-allocated/re-optimized connections, this 
-	// metric determines the average path length (in terms of number of hops) over the computed path for the
-	// succesfully (i.e., feasible path) connections
-	gdouble compRouteConnAvPathLength;
-};
-
-// Prototype of external declaration of functions
-void print_path (struct compRouteOutputItem_t *);
-void print_path_t(struct path_t*);
-struct path_t* create_path();
-
-void duplicate_string(gchar *, gchar *);
-
-gchar* get_uuid_char(uuid_t);
-void copy_service_id(struct serviceId_t*, struct serviceId_t *);
-void copy_service_endpoint_id(struct service_endpoints_id_t *, struct service_endpoints_id_t *);
-
-struct graph_t* get_graph_by_contextId(GList*, gchar *);
-
-struct pred_t * create_predecessors ();
-struct edges_t* create_edge();
-void print_predecessors (struct pred_t *);
-void build_predecessors (struct pred_t *, struct service_t *, struct map_nodes_t *);
-struct nodes_t * create_node ();
-struct routeElement_t * create_routeElement ();
-
-void duplicate_node_id (struct nodes_t *, struct nodes_t *);
-gint compare_node_id (struct nodes_t *, struct nodes_t *);
-void duplicate_routeElement (struct routeElement_t *, struct routeElement_t *);
-void duplicate_edge (struct edges_t *, struct edges_t *);
-void duplicate_path (struct compRouteOutputItem_t *, struct compRouteOutputItem_t *);
-void duplicate_path_t(struct compRouteOutputItem_t *, struct path_t *);
-gint get_map_index_by_nodeId (gchar *, struct map_nodes_t *);
-void get_edge_from_map_by_node (struct edges_t *, struct nodes_t*, struct map_nodes_t *);
-void get_edge_from_predecessors (struct edges_t *, struct nodes_t*, struct pred_t *);
-void build_path (struct compRouteOutputItem_t *, struct pred_t *, struct service_t *);
-void print_graph (struct graph_t *);
-
-gint graph_vertice_lookup (gchar *, struct graph_t *);
-gint graph_targeted_vertice_lookup (gint, gchar *, struct graph_t *);
-gint graph_targeted_vertice_add (gint, gchar *, struct graph_t *);
-
-void remove_edge_from_graph (struct graph_t *, struct edges_t *);
-
-struct path_set_t * create_path_set ();
-void sort_path_set (struct path_set_t *, guint);
-void pop_front_path_set (struct path_set_t *);
-void remove_path_set(struct path_set_t*);
-
-void build_map_node(struct map_nodes_t *, struct graph_t *);
-struct compRouteOutputList_t * create_route_list();
-void duplicate_route_list(struct compRouteOutputList_t *, struct compRouteOutputList_t *);
-struct compRouteOutputItem_t * create_path_item (); 
-void add_routeElement_path_back (struct routeElement_t *, struct compRouteOutputItem_t *);
-gboolean matching_path_rootPath (struct compRouteOutputItem_t *, struct compRouteOutputItem_t *, struct nodes_t *, struct edges_t *);
-void modify_targeted_graph (struct graph_t *, struct path_set_t *, struct compRouteOutputItem_t *, struct nodes_t *);
-gint find_nodeId (gconstpointer, gconstpointer);
-gint check_link (struct nodeItem_t *, gint, gint, struct graph_t *, struct service_t *, GList **, GList **, struct map_nodes_t *, guint arg);
-gboolean check_computed_path_feasability (struct service_t *, struct compRouteOutputItem_t * );
-
-gint sort_by_distance (gconstpointer, gconstpointer);
-gint sort_by_energy(gconstpointer, gconstpointer);
-
-struct graph_t * create_graph ();
-struct map_nodes_t * create_map_node ();
-
-struct service_t * get_service_for_computed_path(gchar *);
-
-void print_service_type(guint);
-void print_link_port_direction(guint);
-void print_termination_direction(guint);
-void print_termination_state(guint);
-void print_capacity_unit(guint);
-void print_link_forwarding_direction(guint);
-
-void build_contextSet(GList **);
-void build_contextSet_active(GList **);
-void print_contextSet(GList *);
-
-gint same_src_dst_pe_nodeid (struct service_t *);
-void comp_route_connection_issue_handler (struct compRouteOutput_t *, struct service_t *);
-
-void destroy_compRouteOutputList (struct compRouteOutputList_t *);
-void duplicate_graph (struct graph_t *, struct graph_t *);
-
-void allocate_graph_resources (struct path_t *, struct service_t *, struct graph_t *);
-void allocate_graph_reverse_resources(struct path_t*, struct service_t *, struct graph_t *);
-void print_route_solution_list (GList *);
-struct timeval tv_adjust(struct timeval);
-
-void print_path_connection_list(struct compRouteOutputList_t*);
-void update_stats_path_comp(struct compRouteOutputList_t*, struct timeval, gint, gint);
-void destroy_active_service(struct activeService_t*);
-void destroy_requested_service(struct service_t*);
-void destroy_device(struct device_t*);
-void destroy_link(struct link_t*);
-void destroy_context(struct context_t*);
-void dijkstra(gint, gint, struct graph_t*, struct service_t*, struct map_nodes_t*, struct nodes_t*, struct compRouteOutputItem_t*, guint);
-void set_path_attributes(struct compRouteOutputItem_t*, struct map_t*);
-void alg_comp(struct service_t*, struct compRouteOutput_t*, struct graph_t*, guint);
+////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * 	# Copyright 2022 Centre Tecnol�gic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ * Author: CTTC/CERCA PONS RU Ricardo Mart�nez (ricardo.martinez@cttc.es)
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _PATHCOMP_TOOLS_H
+#define _PATHCOMP_TOOLS_H
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-2.0/glib/gtypes.h>
+#include <uuid/uuid.h>
+
+// External variables
+extern GList* contextSet;
+extern GList* linkList;
+extern GList* deviceList;
+extern GList* serviceList;
+extern GList* activeServList;
+
+//////////////////////////////////////////////////////////
+// Optimization computation argument 
+//////////////////////////////////////////////////////////
+#define NO_OPTIMIZATION_ARGUMENT		0x00000000
+#define ENERGY_EFFICIENT_ARGUMENT		0x00000001
+
+#define INFINITY_COST                   0xFFFFFFFF
+#define MAX_NUM_PRED					100
+
+#define MAX_KSP_VALUE					3
+
+// HTTP RETURN CODES
+#define HTTP_CODE_OK					200
+#define HTTP_CODE_CREATED 				201
+#define HTTP_CODE_BAD_REQUEST    		400
+#define HTTP_CODE_UNAUTHORIZED   		401
+#define HTTP_CODE_FORBIDDEN      		403
+#define HTTP_CODE_NOT_FOUND				404
+#define HTTP_CODE_NOT_ACCEPTABLE		406
+
+#define MAX_NODE_ID_SIZE				37 // UUID 128 Bits - In hexadecimal requires 36 char
+#define MAX_CONTEXT_ID					37
+//#define UUID_CHAR_LENGTH				37
+#define UUID_CHAR_LENGTH				100
+struct nodes_t {
+	gchar nodeId[UUID_CHAR_LENGTH];
+};
+
+struct nodeItem_t {
+    struct nodes_t node;
+    gdouble distance; // traversed distance
+	gdouble latency; // incured latency
+	gdouble power; //consumed power
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Structures for collecting the RL topology including: intra WAN topology and inter-WAN links
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#define MAX_INTER_DOMAIN_PLUG_IN_SIZE					128
+struct edges_t {	
+	//aNodeId/Device Id
+	struct nodes_t aNodeId;	
+	//zNodeId/Device Id
+	struct nodes_t zNodeId;	
+	
+	// UUID of the endPointIds
+	gchar aEndPointId[UUID_CHAR_LENGTH];
+	gchar zEndPointId[UUID_CHAR_LENGTH];
+
+	// UUID of the link
+	gchar linkId[UUID_CHAR_LENGTH];
+
+	// Potential(total) and available capacity
+	gint unit;
+	gdouble totalCap, availCap;
+	
+	gdouble cost;	
+	gdouble delay;
+	gdouble energy;
+
+	// inter-domain local and remote Ids
+	gchar interDomain_localId[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
+	gchar interDomain_remoteId[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
+
+	gchar aTopologyId[UUID_CHAR_LENGTH];
+	gchar zTopologyId[UUID_CHAR_LENGTH];
+};
+
+// Structure to handle the path computation
+struct pred_comp_t {
+	struct nodes_t v;
+	struct edges_t e;	
+};
+
+struct pred_t {
+    struct pred_comp_t predComp[MAX_NUM_PRED];
+    gint numPredComp;
+};
+
+// Structures for the managing the path computation algorithm
+struct map_t {
+	struct nodes_t verticeId;
+	struct edges_t predecessor;
+	gdouble distance;
+	gdouble avaiBandwidth;
+	gdouble latency;
+	gdouble power;
+};
+
+#define MAX_MAP_NODE_SIZE				100
+struct map_nodes_t {
+    struct map_t map[MAX_MAP_NODE_SIZE];
+    gint numMapNodes;
+};
+
+#define MAX_NUM_VERTICES				20 // 100 # LGR: reduced from 100 to 20 to divide by 5 the memory used
+#define MAX_NUM_EDGES					10 // 100 # LGR: reduced from 100 to 10 to divide by 10 the memory used
+// Structures for the graph composition
+struct targetNodes_t {
+	// remote / targeted node
+	struct nodes_t tVertice;
+	// edge conencting a pair of vertices
+	struct edges_t edges[MAX_NUM_EDGES];	
+	gint numEdges; 
+};
+
+struct vertices_t {
+	struct targetNodes_t targetedVertices[MAX_NUM_VERTICES];
+	gint numTargetedVertices;
+    struct nodes_t verticeId;
+	gdouble power_idle; // power idle of the device (due to the fans, etc.)
+};
+
+struct graph_t {
+	struct vertices_t vertices[MAX_NUM_VERTICES];
+	gint numVertices;	
+};
+
+////////////////////////////////////////////////////
+// Structure for the Set of Contexts
+///////////////////////////////////////////////////
+struct context_t {
+	gchar contextId[UUID_CHAR_LENGTH]; // UUID char format 36 chars
+	// conext Id has a graph associated
+	struct graph_t g;
+};
+
+#define MAX_ALG_ID_LENGTH		10
+////////////////////////////////////////////////////
+// External Variables
+///////////////////////////////////////////////////
+extern gchar algId[MAX_ALG_ID_LENGTH];
+
+////////////////////////////////////////////////////
+// Structure for the Requested Transport Connectivity Services
+///////////////////////////////////////////////////
+#define SERVICE_TYPE_UNKNOWN			0
+#define SERVICE_TYPE_L3NM				1
+#define SERVICE_TYPE_L2NM				2
+#define SERVICE_TYPE_TAPI				3
+
+///////////////////////////////////////////////////////////////////
+// Structure for the topology_id
+///////////////////////////////////////////////////////////////////
+struct topology_id_t {
+	gchar contextId[UUID_CHAR_LENGTH];
+	gchar topology_uuid[UUID_CHAR_LENGTH];
+};
+
+struct inter_domain_plug_in_t {
+	gchar inter_domain_plug_in_local_id[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
+	gchar inter_domain_plug_in_remote_id[MAX_INTER_DOMAIN_PLUG_IN_SIZE];
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the endPointId
+///////////////////////////////////////////////////////////////////
+struct endPointId_t {
+	struct topology_id_t topology_id;
+	gchar device_id[UUID_CHAR_LENGTH];
+	gchar endpoint_uuid[UUID_CHAR_LENGTH];
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the endPoint
+///////////////////////////////////////////////////////////////////
+#define CAPACITY_UNIT_TB									0
+#define CAPACITY_UNIT_TBPS									1
+#define CAPACITY_UNIT_GB									2
+#define CAPACITY_UNIT_GBPS									3
+#define CAPACITY_UNIT_MB									4
+#define CAPACITY_UNIT_MBPS									5
+#define CAPACITY_UNIT_KB									6
+#define CAPACITY_UNIT_KBPS									7
+#define CAPACITY_UNIT_GHZ									8
+#define CAPACITY_UNIT_MHZ									9
+struct capacity_t {
+	gdouble value;
+	gint unit;
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the endPoint
+///////////////////////////////////////////////////////////////////
+#define MAX_ENDPOINT_TYPE_SIZE								128
+// Link Port Direction
+#define LINK_PORT_DIRECTION_BIDIRECTIONAL					0
+#define LINK_PORT_DIRECTION_INPUT							1
+#define LINK_PORT_DIRECTION_OUTPUT							2
+#define LINK_PORT_DIRECTION_UNKNOWN							3
+// Termination Direction
+#define TERMINATION_DIRECTION_BIDIRECTIONAL					0
+#define TERMINATION_DIRECTION_SINK							1
+#define TERMINATION_DIRECTION_SOURCE						2
+#define TERMINATION_DIRECTION_UNKNOWN						3
+// Termination State
+#define TERMINATION_STATE_CAN_NEVER_TERMINATE				0
+#define TERMINATION_STATE_NOT_TERMINATED					1
+#define TERMINATION_STATE_TERMINATED_SERVER_TO_CLIENT_FLOW	2
+#define TERMINATION_STATE_TERMINATED_CLIENT_TO_SERVER_FLOW	3
+#define TERMINATION_STATE_TERMINATED_BIDIRECTIONAL			4
+
+struct endPoint_t {
+	struct endPointId_t endPointId;
+	gchar endpointType[MAX_ENDPOINT_TYPE_SIZE];
+	guint link_port_direction;
+	guint termination_direction;
+	guint termination_state;
+	struct capacity_t potential_capacity;
+	struct capacity_t available_capacity;
+	// inter-domain identifiers
+	struct inter_domain_plug_in_t inter_domain_plug_in;
+	gfloat energyConsumption; // in nJ/bit
+	gint operational_status; // 0 Undefined, 1 Disabled, 2 Enabled
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the device contents
+///////////////////////////////////////////////////////////////////
+#define MAX_DEV_TYPE_SIZE				128
+#define MAX_DEV_ENDPOINT_LENGTH			10
+struct device_t {
+	gdouble power_idle; // power idle (baseline) of the switch in Watts
+	gint operational_status; // 0 - Undefined, 1 - Disabled, 2 - Enabled
+	gchar deviceId[UUID_CHAR_LENGTH]; // device ID using UUID (128 bits)
+	gchar deviceType[MAX_DEV_TYPE_SIZE]; // Specifies the device type
+	// define the endpoints attached to the device
+	gint numEndPoints;
+	struct endPoint_t endPoints[MAX_DEV_ENDPOINT_LENGTH];
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the link EndPoint Id
+///////////////////////////////////////////////////////////////////
+struct link_endpointId_t {
+	struct topology_id_t topology_id;
+	gchar deviceId[UUID_CHAR_LENGTH];  // Device UUID
+	gchar endPointId[UUID_CHAR_LENGTH];	// Link EndPoint UUID
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the link cost characteristics
+///////////////////////////////////////////////////////////////////
+#define LINK_COST_NAME_SIZE								128
+struct cost_characteristics_t {
+	gchar cost_name[LINK_COST_NAME_SIZE];
+	gdouble cost_value;
+	gdouble cost_algorithm;
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the latency characteristics of the link
+///////////////////////////////////////////////////////////////////
+struct latency_characteristics_t {
+	gdouble fixed_latency;
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the latency characteristics of the link
+///////////////////////////////////////////////////////////////////
+struct power_characteristics_t {
+	gdouble power;
+};
+
+///////////////////////////////////////////////////////////////////
+// Structure for the link 
+///////////////////////////////////////////////////////////////////
+#define MAX_NUM_LINK_ENDPOINT_IDS								2
+
+#define LINK_FORWARDING_DIRECTION_BIDIRECTIONAL					0
+#define LINK_FORWARDING_DIRECTION_UNIDIRECTIONAL				1
+#define LINK_FORWARDING_DIRECTION_UNKNOWN						2
+struct link_t {
+	gchar linkId[UUID_CHAR_LENGTH]; // link Id using UUID (128 bits)
+	//gdouble energy_link; // in nJ/bit
+	//gint operational_status; // 0 Undefined, 1 Disabled, 2 Enabled
+	gint numLinkEndPointIds;
+	struct link_endpointId_t linkEndPointId[MAX_NUM_LINK_ENDPOINT_IDS];
+	guint forwarding_direction;
+	struct capacity_t potential_capacity;
+	struct capacity_t available_capacity;
+	struct cost_characteristics_t cost_characteristics;
+	struct latency_characteristics_t latency_characteristics;
+};
+
+////////////////////////////////////////////////////
+// Structure for service Identifier
+///////////////////////////////////////////////////
+struct serviceId_t {
+	gchar contextId[UUID_CHAR_LENGTH];
+	gchar service_uuid[UUID_CHAR_LENGTH];
+};
+
+////////////////////////////////////////////////////
+// Structure the service endpoint ids
+///////////////////////////////////////////////////
+struct service_endpoints_id_t {
+	struct topology_id_t topology_id;
+	gchar device_uuid[UUID_CHAR_LENGTH];
+	gchar endpoint_uuid[UUID_CHAR_LENGTH];
+};
+
+////////////////////////////////////////////////////
+// Structure for handling generic targeted service constraints
+////////////////////////////////////////////////////
+#define MAX_CONSTRAINT_SIZE					128
+// Constraint Type: bandwidth, latency, energy, cost
+struct constraint_t {
+	gchar constraint_type[MAX_CONSTRAINT_SIZE];
+	gchar constraint_value[MAX_CONSTRAINT_SIZE];
+};
+
+////////////////////////////////////////////////////
+// Structure for individual service request
+////////////////////////////////////////////////////
+#define SERVICE_TYPE_UNKNOWN					0
+#define SERVICE_TYPE_L3NM						1
+#define SERVICE_TYPE_L2NM						2
+#define SERVICE_TYPE_TAPI						3
+
+#define MAX_NUM_SERVICE_ENPOINTS_ID				2
+
+#define MAX_NUM_SERVICE_CONSTRAINTS				10
+struct service_t {
+	// Indentifier used to determine the used Algorithm Id, e.g., KSP
+	gchar algId[MAX_ALG_ID_LENGTH];
+	// PATHS expected for the output
+	guint kPaths;
+	
+	struct serviceId_t serviceId;
+	guint service_type;	 // unknown, l2nm, l3nm, tapi
+
+	// endpoints of the network connectivity service, assumed p2p
+	// the 1st one assumed to be the source (ingress) and the 2nd one is the sink (egress)
+	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
+	guint num_service_endpoints_id;
+
+	// Service Constraints
+	struct constraint_t constraints[MAX_NUM_SERVICE_CONSTRAINTS];
+	guint num_service_constraints;
+};
+
+////////////////////////////////////////////////////
+// Structure to handle path constraints during computation
+////////////////////////////////////////////////////
+struct path_constraints_t {
+	gdouble bwConstraint;
+	gboolean bw;
+
+	gdouble costConstraint;
+	gboolean cost;
+
+	gdouble latencyConstraint;
+	gboolean latency;
+
+	gdouble energyConstraint;
+	gboolean energy;
+};
+
+////////////////////////////////////////////////////
+// Structure for the handling the service requests
+///////////////////////////////////////////////////
+//#define MAX_SERVICE_LIST						100
+//struct serviceList_t {
+//	struct service_t services[MAX_SERVICE_LIST];
+//	gint numServiceList;	
+//};
+
+////////////////////////////////////////////////////
+// Structure for the handling the active services 
+///////////////////////////////////////////////////
+struct activeServPath_t {
+	struct topology_id_t topology_id;
+	gchar deviceId[UUID_CHAR_LENGTH];
+	gchar endPointId[UUID_CHAR_LENGTH];
+};
+
+struct activeService_t {
+	struct serviceId_t serviceId;
+	guint service_type;	 // unknown, l2nm, l3nm, tapi
+	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
+	guint num_service_endpoints_id;
+	GList* activeServPath;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Structure describing the links forming a computed path
+////////////////////////////////////////////////////////////////////////////////////////////
+struct linkTopology_t {
+	gchar topologyId[UUID_CHAR_LENGTH];
+};
+
+struct pathLink_t {
+	gchar linkId[UUID_CHAR_LENGTH]; // link id UUID in char format
+
+	gchar aDeviceId[UUID_CHAR_LENGTH];
+	gchar zDeviceId[UUID_CHAR_LENGTH];
+	gchar aEndPointId[UUID_CHAR_LENGTH];
+	gchar zEndPointId[UUID_CHAR_LENGTH];
+
+	struct topology_id_t topologyId;
+	struct linkTopology_t linkTopologies[2]; // a p2p link (at most) can connect to devices (endpoints) attached to 2 different topologies
+	gint numLinkTopologies;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Structure describing a computed path
+////////////////////////////////////////////////////////////////////////////////////////////
+#define MAX_ROUTE_ELEMENTS  50
+struct routeElement_t {
+	//aNodeId/Device Id
+	struct nodes_t aNodeId;
+	//zNodeId/Device Id
+	struct nodes_t zNodeId;
+
+	// UUID of the endPointIds
+	gchar aEndPointId[UUID_CHAR_LENGTH];
+	gchar zEndPointId[UUID_CHAR_LENGTH];
+
+	// UUID of the link
+	gchar linkId[UUID_CHAR_LENGTH];
+
+	gchar aTopologyId[UUID_CHAR_LENGTH];
+	gchar zTopologyId[UUID_CHAR_LENGTH];
+
+	// contextId
+	gchar contextId[UUID_CHAR_LENGTH];
+};
+
+struct compRouteOutputItem_t {	
+	gint unit;
+	gdouble totalCap, availCap;
+
+	gdouble cost;
+	gdouble delay;
+	gdouble power;
+
+	struct routeElement_t routeElement[MAX_ROUTE_ELEMENTS];
+	gint numRouteElements;
+};
+
+#define MAX_NUM_PATHS		30
+struct path_set_t {
+	struct compRouteOutputItem_t paths[MAX_NUM_PATHS];
+	gint numPaths;
+};
+
+#define MAX_NUM_PATH_LINKS						20
+struct path_t {
+	struct capacity_t path_capacity;
+	struct latency_characteristics_t path_latency;
+	struct cost_characteristics_t path_cost;
+	struct power_characteristics_t path_power;
+
+	struct pathLink_t pathLinks[MAX_NUM_PATH_LINKS];
+	guint numPathLinks;
+};
+
+#define NO_PATH_CONS_ISSUE								1	 // No path due to a constraint issue
+#define MAX_NUM_COMPUTED_PATHS							10
+struct compRouteOutput_t {
+	// object describing the service identifier: serviceId and contextId
+	struct serviceId_t serviceId;
+	// array describing the service endpoints ids
+	struct service_endpoints_id_t service_endpoints_id[MAX_NUM_SERVICE_ENPOINTS_ID];
+	guint num_service_endpoints_id;
+	struct path_t paths[MAX_NUM_COMPUTED_PATHS];
+	gint numPaths;	
+	// if the transport connectivity service cannot be computed, this value is set to 0 determining the constraints were not fulfilled
+	gint noPathIssue;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Structure to handle the response list with all the computed network connectivity services
+////////////////////////////////////////////////////////////////////////////////////////////
+#define MAX_COMP_CONN_LIST		100
+struct compRouteOutputList_t {
+	struct compRouteOutput_t compRouteConnection[MAX_COMP_CONN_LIST];
+	gint numCompRouteConnList;
+
+	///////////////// Metrics //////////////////////////////////////////
+	// Number of total succesfully computed connections, i.e., at least 1 feasible path exists
+	// for every connection in the list
+	gint compRouteOK;
+	// For the succesfully newly computed/recovered/re-allocated/re-optimized connections, this 
+	// metric determines the average allocable bandwidth over all the (re-)computed paths for the succesfully 
+	// (i.e., feasible path) connections
+	gdouble compRouteConnAvBandwidth;
+	// For the succesfully newly computed/recovered/re-allocated/re-optimized connections, this 
+	// metric determines the average path length (in terms of number of hops) over the computed path for the
+	// succesfully (i.e., feasible path) connections
+	gdouble compRouteConnAvPathLength;
+};
+
+// Prototype of external declaration of functions
+void print_path (struct compRouteOutputItem_t *);
+void print_path_t(struct path_t*);
+struct path_t* create_path();
+
+void duplicate_string(gchar *, gchar *);
+
+gchar* get_uuid_char(uuid_t);
+void copy_service_id(struct serviceId_t*, struct serviceId_t *);
+void copy_service_endpoint_id(struct service_endpoints_id_t *, struct service_endpoints_id_t *);
+
+struct graph_t* get_graph_by_contextId(GList*, gchar *);
+
+struct pred_t * create_predecessors ();
+struct edges_t* create_edge();
+void print_predecessors (struct pred_t *);
+void build_predecessors (struct pred_t *, struct service_t *, struct map_nodes_t *);
+struct nodes_t * create_node ();
+struct routeElement_t * create_routeElement ();
+
+void duplicate_node_id (struct nodes_t *, struct nodes_t *);
+gint compare_node_id (struct nodes_t *, struct nodes_t *);
+void duplicate_routeElement (struct routeElement_t *, struct routeElement_t *);
+void duplicate_edge (struct edges_t *, struct edges_t *);
+void duplicate_path (struct compRouteOutputItem_t *, struct compRouteOutputItem_t *);
+void duplicate_path_t(struct compRouteOutputItem_t *, struct path_t *);
+gint get_map_index_by_nodeId (gchar *, struct map_nodes_t *);
+void get_edge_from_map_by_node (struct edges_t *, struct nodes_t*, struct map_nodes_t *);
+void get_edge_from_predecessors (struct edges_t *, struct nodes_t*, struct pred_t *);
+void build_path (struct compRouteOutputItem_t *, struct pred_t *, struct service_t *);
+void print_graph (struct graph_t *);
+
+gint graph_vertice_lookup (gchar *, struct graph_t *);
+gint graph_targeted_vertice_lookup (gint, gchar *, struct graph_t *);
+gint graph_targeted_vertice_add (gint, gchar *, struct graph_t *);
+
+void remove_edge_from_graph (struct graph_t *, struct edges_t *);
+
+struct path_set_t * create_path_set ();
+void sort_path_set (struct path_set_t *, guint);
+void pop_front_path_set (struct path_set_t *);
+void remove_path_set(struct path_set_t*);
+
+void build_map_node(struct map_nodes_t *, struct graph_t *);
+struct compRouteOutputList_t * create_route_list();
+void duplicate_route_list(struct compRouteOutputList_t *, struct compRouteOutputList_t *);
+struct compRouteOutputItem_t * create_path_item (); 
+void add_routeElement_path_back (struct routeElement_t *, struct compRouteOutputItem_t *);
+gboolean matching_path_rootPath (struct compRouteOutputItem_t *, struct compRouteOutputItem_t *, struct nodes_t *, struct edges_t *);
+void modify_targeted_graph (struct graph_t *, struct path_set_t *, struct compRouteOutputItem_t *, struct nodes_t *);
+gint find_nodeId (gconstpointer, gconstpointer);
+gint check_link (struct nodeItem_t *, gint, gint, struct graph_t *, struct service_t *, GList **, GList **, struct map_nodes_t *, guint arg);
+gboolean check_computed_path_feasability (struct service_t *, struct compRouteOutputItem_t * );
+
+gint sort_by_distance (gconstpointer, gconstpointer);
+gint sort_by_energy(gconstpointer, gconstpointer);
+
+struct graph_t * create_graph ();
+struct map_nodes_t * create_map_node ();
+
+struct service_t * get_service_for_computed_path(gchar *);
+
+void print_service_type(guint);
+void print_link_port_direction(guint);
+void print_termination_direction(guint);
+void print_termination_state(guint);
+void print_capacity_unit(guint);
+void print_link_forwarding_direction(guint);
+
+void build_contextSet(GList **);
+void build_contextSet_active(GList **);
+void print_contextSet(GList *);
+
+gint same_src_dst_pe_nodeid (struct service_t *);
+void comp_route_connection_issue_handler (struct compRouteOutput_t *, struct service_t *);
+
+void destroy_compRouteOutputList (struct compRouteOutputList_t *);
+void duplicate_graph (struct graph_t *, struct graph_t *);
+
+void allocate_graph_resources (struct path_t *, struct service_t *, struct graph_t *);
+void allocate_graph_reverse_resources(struct path_t*, struct service_t *, struct graph_t *);
+void print_route_solution_list (GList *);
+struct timeval tv_adjust(struct timeval);
+
+void print_path_connection_list(struct compRouteOutputList_t*);
+void update_stats_path_comp(struct compRouteOutputList_t*, struct timeval, gint, gint);
+void destroy_active_service(struct activeService_t*);
+void destroy_requested_service(struct service_t*);
+void destroy_device(struct device_t*);
+void destroy_link(struct link_t*);
+void destroy_context(struct context_t*);
+void dijkstra(gint, gint, struct graph_t*, struct service_t*, struct map_nodes_t*, struct nodes_t*, struct compRouteOutputItem_t*, guint);
+void set_path_attributes(struct compRouteOutputItem_t*, struct map_t*);
+void alg_comp(struct service_t*, struct compRouteOutput_t*, struct graph_t*, guint);
 #endif
\ No newline at end of file