From b28cd4c41848aad2241e88fbe793e9d5a7394f44 Mon Sep 17 00:00:00 2001 From: martinezric Date: Wed, 22 Mar 2023 17:17:52 +0100 Subject: [PATCH 1/2] PathComp_Backend: - Added Glist for handling the context information (deviceList and linkList) - Added the path computation algorithm to support energy aware routing - Re-factoring K-SP and SP in common .c and .h files --- src/pathcomp/backend/Makefile | 17 +- src/pathcomp/backend/pathComp.c | 2 - src/pathcomp/backend/pathComp_RESTapi.c | 721 ++++++----- src/pathcomp/backend/pathComp_RESTapi.h | 3 +- src/pathcomp/backend/pathComp_ear.c | 213 ++++ src/pathcomp/backend/pathComp_ear.h | 30 + src/pathcomp/backend/pathComp_ksp.c | 425 +------ src/pathcomp/backend/pathComp_sp.c | 118 +- src/pathcomp/backend/pathComp_tools.c | 1453 ++++++++++++++++------- src/pathcomp/backend/pathComp_tools.h | 145 +-- 10 files changed, 1843 insertions(+), 1284 deletions(-) create mode 100644 src/pathcomp/backend/pathComp_ear.c create mode 100644 src/pathcomp/backend/pathComp_ear.h diff --git a/src/pathcomp/backend/Makefile b/src/pathcomp/backend/Makefile index f4fc1996b..f60186847 100644 --- a/src/pathcomp/backend/Makefile +++ b/src/pathcomp/backend/Makefile @@ -33,16 +33,16 @@ coverage: CFLAGS += -O0 -ggdb -g -DDEBUG -fprofile-arcs -ftest-coverage -DGCOV coverage: LDFLAGS += -g -lgcov --coverage -fprofile-arcs -ftest-coverage -DGCOV coverage: pathComp-cvr -pathComp: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o - gcc -o pathComp pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o \ +pathComp: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o + gcc -o pathComp pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o \ -L/usr/lib/x86_64-linux-gnu/ -lglib-2.0 -luuid $(LDFLAGS) $(LDLIBS) -pathComp-dbg: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o - gcc -o pathComp-dbg pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o \ +pathComp-dbg: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o + gcc -o pathComp-dbg pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o \ -L/usr/lib/x86_64-linux-gnu/ -lglib-2.0 -luuid $(LDFLAGS) $(LDLIBS) -pathComp-cvr: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o - gcc -o pathComp-cvr pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_RESTapi.o \ +pathComp-cvr: pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o + gcc -o pathComp-cvr pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_sp.o pathComp_ear.o pathComp_RESTapi.o \ -L/usr/lib/x86_64-linux-gnu/ -lglib-2.0 -luuid $(LDFLAGS) $(LDLIBS) pathComp_log.o: pathComp_log.h pathComp_log.c @@ -59,8 +59,11 @@ pathComp_ksp.o: pathComp_log.h pathComp_tools.h pathComp_ksp.h pathComp_ksp.c pathComp_sp.o: pathComp_log.h pathComp_tools.h pathComp_sp.h pathComp_sp.c $(CC) $(CFLAGS) -c pathComp_sp.c -o pathComp_sp.o + +pathComp_ear.o: pathComp_log.h pathComp_tools.h pathComp_ear.h pathComp_ear.c + $(CC) $(CFLAGS) -c pathComp_ear.c -o pathComp_ear.o -pathComp_RESTapi.o: pathComp_tools.h pathComp_log.h pathComp_cjson.h pathComp_ksp.h pathComp_sp.h pathComp_RESTapi.h pathComp_RESTapi.c +pathComp_RESTapi.o: pathComp_tools.h pathComp_log.h pathComp_cjson.h pathComp_ksp.h pathComp_sp.h pathComp_ear.h pathComp_RESTapi.h pathComp_RESTapi.c $(CC) $(CFLAGS) -c pathComp_RESTapi.c -o pathComp_RESTapi.o pathComp.o: pathComp_log.h pathComp_RESTapi.h pathComp.c pathComp.h diff --git a/src/pathcomp/backend/pathComp.c b/src/pathcomp/backend/pathComp.c index 2a719c924..12c57a80b 100644 --- a/src/pathcomp/backend/pathComp.c +++ b/src/pathcomp/backend/pathComp.c @@ -52,10 +52,8 @@ void my_gcov_handler(int signum) // External Variables FILE *logfile = NULL; - // PATH COMP IP address API Client struct in_addr pathComp_IpAddr; - // REST API ENABLED int RESTAPI_ENABLED = 0; diff --git a/src/pathcomp/backend/pathComp_RESTapi.c b/src/pathcomp/backend/pathComp_RESTapi.c index 709d3dc00..fd98187dc 100644 --- a/src/pathcomp/backend/pathComp_RESTapi.c +++ b/src/pathcomp/backend/pathComp_RESTapi.c @@ -39,6 +39,7 @@ #include "pathComp_cjson.h" #include "pathComp_ksp.h" #include "pathComp_sp.h" +#include "pathComp_ear.h" #include "pathComp_RESTapi.h" #define ISspace(x) isspace((int)(x)) @@ -53,9 +54,10 @@ guint CLIENT_ID = 0; guint32 paId_req = 0; // Global variables -struct linkList_t* linkList; -struct deviceList_t* deviceList; -struct serviceList_t* serviceList; +GList* linkList; +GList* deviceList; +GList* serviceList; +GList* activeServList; gchar algId[MAX_ALG_ID_LENGTH]; gboolean syncPath = FALSE; @@ -81,8 +83,9 @@ gint find_rl_client_by_fd (gconstpointer data, gconstpointer userdata) struct pathComp_client *client = (struct pathComp_client*)data; gint fd = *(gint *)userdata; - if (client->fd == fd) - return 0; + if (client->fd == fd) { + return 0; + } return -1; } @@ -457,7 +460,6 @@ void rapi_response_json_contents (char *body, gint *length, struct compRouteOutp */ ///////////////////////////////////////////////////////////////////////////////////////// void rapi_response_ok (GIOChannel *source, gint httpCode, struct compRouteOutputList_t *compRouteOutputList) { - gint ret = 0; //DEBUG_PC ("Creating the JSON Body and sending the response of the computed Route List"); @@ -529,8 +531,7 @@ void rapi_response_ok (GIOChannel *source, gint httpCode, struct compRouteOutput * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void rapi_response (GIOChannel *source, gint error) -{ +void rapi_response (GIOChannel *source, gint error) { int ret = 0; guchar buftmp[1024]; char * buf = g_malloc0 (sizeof (char) * 2048000); @@ -569,11 +570,94 @@ void rapi_response (GIOChannel *source, gint error) return; } +/////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief parsing topology Identifier Object (contains Context Id and Toplogy UUID) JSON object + * + * @param obj + * @param topology_id + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void parse_topology_Id(cJSON* obj, struct topology_id_t* topology_id) { + g_assert(topology_id); + // Get the context Id (UUID) from the topologyIdObj + cJSON* contextIdObj = cJSON_GetObjectItem(obj, "contextId"); + if (cJSON_IsString(contextIdObj)) { + duplicate_string(topology_id->contextId, contextIdObj->valuestring); + } + // Get the topologyId (UUID) from the topologyIdObj + cJSON* topologyUuidObj = cJSON_GetObjectItem(obj, "topology_uuid"); + if (cJSON_IsString(topologyUuidObj)) { + duplicate_string(topology_id->topology_uuid, topologyUuidObj->valuestring); + } + return; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief parsing EndpointIds JSON object + * + * @param item + * @param serviceEndPointId + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void parse_endPointsIds(cJSON* item, struct service_endpoints_id_t* serviceEndPointId) { + // Get the topology Id Object + cJSON* topologyIdObj = cJSON_GetObjectItem(item, "topology_id"); + if (cJSON_IsObject(topologyIdObj)) { + parse_topology_Id(topologyIdObj, &serviceEndPointId->topology_id); + } + // Get the deviceId (UUID) + cJSON* deviceIdObj = cJSON_GetObjectItem(item, "device_id"); + if (cJSON_IsString(deviceIdObj)) { + duplicate_string(serviceEndPointId->device_uuid, deviceIdObj->valuestring); + DEBUG_PC("DeviceId: %s", serviceEndPointId->device_uuid); + } + // Get the endpointId (UUID) + cJSON* endPointIdObj = cJSON_GetObjectItem(item, "endpoint_uuid"); + if (cJSON_IsString(endPointIdObj)) { + duplicate_string(serviceEndPointId->endpoint_uuid, endPointIdObj->valuestring); + DEBUG_PC("EndPointId: %s", serviceEndPointId->endpoint_uuid); + } + return; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief Function used to parse the array of Endpoint Ids of the active services + * + * @param endPointArray + * @param actServ + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void parse_act_service_endPointsIds_array(cJSON* endPointIdArray, struct activeService_t* actServ) { + g_assert(actServ); + + for (gint i = 0; i < cJSON_GetArraySize(endPointIdArray); i++) { + actServ->num_service_endpoints_id++; + struct service_endpoints_id_t* serviceEndPointId = &(actServ->service_endpoints_id[i]); + cJSON* item = cJSON_GetArrayItem(endPointIdArray, i); + parse_endPointsIds(item, serviceEndPointId); + } + return; +} /////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_RESTapi.c - * @brief Function used to parse the array of Endpoint Ids + * @brief Function used to parse the array of Endpoint Ids of the requested services * * @param endPointArray * @param s @@ -589,35 +673,7 @@ void parse_service_endPointsIds_array(cJSON* endPointIdArray, struct service_t* struct service_endpoints_id_t* serviceEndPointId = &(s->service_endpoints_id[i]); cJSON* item = cJSON_GetArrayItem(endPointIdArray, i); - - // Get the topology Id Object - cJSON* topologyIdObj = cJSON_GetObjectItem(item, "topology_id"); - if (cJSON_IsObject(topologyIdObj)) { - // Get the context Id (UUID) from the topologyIdObj - cJSON* contextIdObj = cJSON_GetObjectItem(topologyIdObj, "contextId"); - if (cJSON_IsString(contextIdObj)) { - duplicate_string(serviceEndPointId->topology_id.contextId, contextIdObj->valuestring); - //DEBUG_PC("Service EndPoint [%d]-- ContextId: %s (uuid string format)", i + 1, serviceEndPointId->topology_id.contextId); - } - // Get the topologyId (UUID) from the topologyIdObj - cJSON* topologyUuidObj = cJSON_GetObjectItem(topologyIdObj, "topology_uuid"); - if (cJSON_IsString(topologyUuidObj)) { - duplicate_string(serviceEndPointId->topology_id.topology_uuid, topologyUuidObj->valuestring); - //DEBUG_PC("Service Endpoint (%d) -- TopologyId: %s (uuid string format)", i + 1, serviceEndPointId->topology_id.topology_uuid); - } - } - // Get the deviceId (UUID) - cJSON* deviceIdObj = cJSON_GetObjectItem(item, "device_id"); - if (cJSON_IsString(deviceIdObj)) { - duplicate_string(serviceEndPointId->device_uuid, deviceIdObj->valuestring); - DEBUG_PC("[%d] - DeviceId: %s", i + 1, serviceEndPointId->device_uuid); - } - // Get the endpointId (UUID) - cJSON* endPointIdObj = cJSON_GetObjectItem(item, "endpoint_uuid"); - if (cJSON_IsString(endPointIdObj)) { - duplicate_string(serviceEndPointId->endpoint_uuid, endPointIdObj->valuestring); - DEBUG_PC("[%d] EndPointId: %s", i + 1, serviceEndPointId->endpoint_uuid); - } + parse_endPointsIds(item, serviceEndPointId); } return; } @@ -635,11 +691,8 @@ void parse_service_endPointsIds_array(cJSON* endPointIdArray, struct service_t* */ ///////////////////////////////////////////////////////////////////////////////////////// void parse_service_constraints(cJSON* constraintArray, struct service_t* s) { - for (gint i = 0; i < cJSON_GetArraySize(constraintArray); i++) { - s->num_service_constraints++; - struct constraint_t* constraint = &(s->constraints[i]); cJSON* item = cJSON_GetArrayItem(constraintArray, i); @@ -659,6 +712,38 @@ void parse_service_constraints(cJSON* constraintArray, struct service_t* s) { return; } +/////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief Function used to parse the serviceId information from a JSON obj + * + * @param obj + * @param serviceId + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void parse_json_serviceId(cJSON* obj, struct serviceId_t* serviceId) { + g_assert(obj); + g_assert(serviceId); + + // Get context Id uuid + cJSON* contextIdObj = cJSON_GetObjectItem(obj, "contextId"); + if (cJSON_IsString(contextIdObj)) { + // convert the string in contextId->valuestring in uuid binary format + duplicate_string(serviceId->contextId, contextIdObj->valuestring); + DEBUG_PC("ContextId: %s (uuid string format)", serviceId->contextId); + } + // Get service Id uuid + cJSON* serviceUuidObj = cJSON_GetObjectItem(obj, "service_uuid"); + if (cJSON_IsString(serviceUuidObj)) { + duplicate_string(serviceId->service_uuid, serviceUuidObj->valuestring); + DEBUG_PC("Service UUID: %s (uuid string format)", serviceId->service_uuid); + } + return; +} + /////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_RESTapi.c @@ -675,15 +760,15 @@ void parsing_json_serviceList_array(cJSON* serviceArray) { for (gint i = 0; i < cJSON_GetArraySize(serviceArray); i++) { - serviceList->numServiceList++; - struct service_t* service = &(serviceList->services[i]); - + struct service_t* service = g_malloc0(sizeof(struct service_t)); + if (service == NULL) { + DEBUG_PC("Memory allocation error ..."); + exit(-1); + } cJSON* item = cJSON_GetArrayItem(serviceArray, i); - // Get the algorithm Id cJSON* algIdItem = cJSON_GetObjectItem(item, "algId"); - if (cJSON_IsString(algIdItem)) - { + if (cJSON_IsString(algIdItem)) { duplicate_string(service->algId, algIdItem->valuestring); DEBUG_PC ("algId: %s", service->algId); // assumed that all the services request the same algId @@ -692,16 +777,13 @@ void parsing_json_serviceList_array(cJSON* serviceArray) { // Get the syncPaths cJSON* synchPathObj = cJSON_GetObjectItemCaseSensitive(item, "syncPaths"); - if (cJSON_IsBool(synchPathObj)) - { + if (cJSON_IsBool(synchPathObj)) { // Check Synchronization of multiple Paths to attain e.g. global concurrent optimization - if (cJSON_IsTrue(synchPathObj)) - { + if (cJSON_IsTrue(synchPathObj)) { syncPath = TRUE; DEBUG_PC("Path Synchronization is required"); } - if (cJSON_IsFalse(synchPathObj)) - { + if (cJSON_IsFalse(synchPathObj)) { syncPath = FALSE; DEBUG_PC("No Path Synchronization"); } @@ -710,19 +792,7 @@ void parsing_json_serviceList_array(cJSON* serviceArray) { // Get service Id in terms of contextId and service uuids cJSON* serviceIdObj = cJSON_GetObjectItem(item, "serviceId"); if (cJSON_IsObject(serviceIdObj)) { - // Get context Id uuid - cJSON* contextIdObj = cJSON_GetObjectItem(serviceIdObj, "contextId"); - if (cJSON_IsString(contextIdObj)) { - // convert the string in contextId->valuestring in uuid binary format - duplicate_string(service->serviceId.contextId, contextIdObj->valuestring); - DEBUG_PC("ContextId: %s (uuid string format)", service->serviceId.contextId); - } - // Get service Id uuid - cJSON* serviceUuidObj = cJSON_GetObjectItem(serviceIdObj, "service_uuid"); - if (cJSON_IsString(serviceUuidObj)) { - duplicate_string(service->serviceId.service_uuid, serviceUuidObj->valuestring); - DEBUG_PC("Service UUID: %s (uuid string format)", service->serviceId.service_uuid); - } + parse_json_serviceId(serviceIdObj, &service->serviceId); } // Get de service type @@ -750,6 +820,9 @@ void parsing_json_serviceList_array(cJSON* serviceArray) { if (cJSON_IsNumber(kPathsObj)){ service->kPaths = (guint)(kPathsObj->valuedouble); } + + // Append the requested service to the serviceList + serviceList = g_list_append(serviceList, service); } return; } @@ -767,7 +840,6 @@ void parsing_json_serviceList_array(cJSON* serviceArray) { */ ///////////////////////////////////////////////////////////////////////////////////////// void parse_capacity_object(cJSON* capacity, struct capacity_t* c) { - cJSON* totalSizeObj = cJSON_GetObjectItem(capacity, "total-size"); if (cJSON_IsObject(totalSizeObj)) { //Get the capacity value @@ -797,7 +869,6 @@ void parse_capacity_object(cJSON* capacity, struct capacity_t* c) { */ ///////////////////////////////////////////////////////////////////////////////////////// void parse_json_device_endpoints_array(cJSON* endPointsArray, struct device_t* d) { - for (gint i = 0; i < cJSON_GetArraySize(endPointsArray); i++) { d->numEndPoints++; struct endPoint_t* endpoint = &(d->endPoints[i]); @@ -810,30 +881,17 @@ void parse_json_device_endpoints_array(cJSON* endPointsArray, struct device_t* d // Get the topology Id Object cJSON* topologyIdObj = cJSON_GetObjectItem(endPointIdObj, "topology_id"); if (cJSON_IsObject(topologyIdObj)) { - // Get the context Id (UUID) from the topologyIdObj - cJSON* contextIdObj = cJSON_GetObjectItem(topologyIdObj, "contextId"); - if (cJSON_IsString(contextIdObj)) { - duplicate_string(endpoint->endPointId.topology_id.contextId, contextIdObj->valuestring); - //DEBUG_PC("Device EndPoint (%d)-- ContextId: %s (uuid string format)", i + 1, endpoint->endPointId.topology_id.contextId); - } - // Get the topologyId (UUID) from the topologyIdObj - cJSON* topologyUuidObj = cJSON_GetObjectItem(topologyIdObj, "topology_uuid"); - if (cJSON_IsString(topologyUuidObj)) { - duplicate_string(endpoint->endPointId.topology_id.topology_uuid, topologyUuidObj->valuestring); - //DEBUG_PC("Device Endpoint (%d) -- TopologyId: %s (uuid string format)", i + 1, endpoint->endPointId.topology_id.topology_uuid); - } + parse_topology_Id(topologyIdObj, &endpoint->endPointId.topology_id); } // Get the deviceId cJSON* deviceIdObj = cJSON_GetObjectItem(endPointIdObj, "device_id"); if (cJSON_IsString(deviceIdObj)) { duplicate_string(endpoint->endPointId.device_id, deviceIdObj->valuestring); - //DEBUG_PC("Device Endpoint (%d) -- Device Id: %s (uuid)", i + 1, endpoint->endPointId.device_id); } // Get the endpoint_uuid cJSON* endPointUuidObj = cJSON_GetObjectItem(endPointIdObj, "endpoint_uuid"); if (cJSON_IsString(endPointUuidObj)) { duplicate_string(endpoint->endPointId.endpoint_uuid, endPointUuidObj->valuestring); - //DEBUG_PC("Device Endpoint (%d) -- EndPoint Uuid: %s (uuid)", i + 1, endpoint->endPointId.endpoint_uuid); } } // Get the EndPoint Type @@ -892,6 +950,20 @@ void parse_json_device_endpoints_array(cJSON* endPointsArray, struct device_t* d //DEBUG_PC("Inter-Domain Remote Id: %s", endpoint->inter_domain_plug_in.inter_domain_plug_in_remote_id); } } + + // Energy consumption per endPoint port + cJSON* energyPortObj = cJSON_GetObjectItem(item, "energy_consumption"); + if (cJSON_IsNumber(energyPortObj)) { + memcpy(&endpoint->energyConsumption, &energyPortObj->valuedouble, sizeof(gdouble)); + DEBUG_PC("Endpoint Energy Consumption: %f", endpoint->energyConsumption); + } + + // Endpoint Operational Status + cJSON* operationalStatusObj = cJSON_GetObjectItem(item, "operational_status"); + if (cJSON_IsNumber(operationalStatusObj)) { + endpoint->operational_status = (gint)(operationalStatusObj->valuedouble); + DEBUG_PC("Endpoint Operational Status: %d", endpoint->operational_status); + } } return; } @@ -910,11 +982,28 @@ void parse_json_device_endpoints_array(cJSON* endPointsArray, struct device_t* d void parsing_json_deviceList_array(cJSON* deviceArray) { DEBUG_PC(""); DEBUG_PC("========= PARSING DEVICE LIST ============"); - for (gint i = 0; i < cJSON_GetArraySize(deviceArray); i++) { - deviceList->numDevices++; - struct device_t* d = &(deviceList->devices[i]); + for (gint i = 0; i < cJSON_GetArraySize(deviceArray); i++) { + struct device_t* d = g_malloc0(sizeof(struct device_t)); + if (d == NULL) { + DEBUG_PC("Memory Allocation Failure"); + exit(-1); + } cJSON* item = cJSON_GetArrayItem(deviceArray, i); + // Get the power idle of the switch + cJSON* powerIdleObj = cJSON_GetObjectItem(item, "power_idle"); + if (cJSON_IsNumber(powerIdleObj)) { + memcpy(&d->power_idle, &powerIdleObj->valuedouble, sizeof(gdouble)); + DEBUG_PC("Power Idle: %f", d->power_idle); + } + + // Get the operational state + cJSON* opeStatusObj = cJSON_GetObjectItem(item, "operational_status"); + if (cJSON_IsNumber(opeStatusObj)) { + d->operational_status = (gint)(opeStatusObj->valuedouble); + DEBUG_PC("Operational Status: %d (0 Undefined, 1 Disabled, 2 Enabled", d->operational_status); + } + // Get the device UUID cJSON* deviceUuidObj = cJSON_GetObjectItem(item, "device_Id"); if (cJSON_IsString(deviceUuidObj)) { @@ -935,6 +1024,8 @@ void parsing_json_deviceList_array(cJSON* deviceArray) { if (cJSON_IsArray(deviceEndpointsArray)) { parse_json_device_endpoints_array(deviceEndpointsArray, d); } + // append the device into the deviceList + deviceList = g_list_append(deviceList, d); } return; } @@ -952,7 +1043,6 @@ void parsing_json_deviceList_array(cJSON* deviceArray) { */ ///////////////////////////////////////////////////////////////////////////////////////// void parse_json_link_endpoints_array(cJSON *endPointsLinkObj, struct link_t* l) { - for (gint i = 0; i < cJSON_GetArraySize(endPointsLinkObj); i++) { //DEBUG_PC("link: %s has %d endPointIds", l->linkId, l->numLinkEndPointIds); l->numLinkEndPointIds++; @@ -966,18 +1056,7 @@ void parse_json_link_endpoints_array(cJSON *endPointsLinkObj, struct link_t* l) // Get the topology Id Object cJSON* topologyIdObj = cJSON_GetObjectItem(endPointIdObj, "topology_id"); if (cJSON_IsObject(topologyIdObj)) { - // Get the context Id (UUID) from the topologyIdObj - cJSON* contextIdObj = cJSON_GetObjectItem(topologyIdObj, "contextId"); - if (cJSON_IsString(contextIdObj)) { - duplicate_string(endPointLink->topology_id.contextId, contextIdObj->valuestring); - //DEBUG_PC("Link EndPoint (%d)-- ContextId: %s (uuid string format)", i + 1, endPointLink->topology_id.contextId); - } - // Get the topologyId (UUID) from the topologyIdObj - cJSON* topologyUuidObj = cJSON_GetObjectItem(topologyIdObj, "topology_uuid"); - if (cJSON_IsString(topologyUuidObj)) { - duplicate_string(endPointLink->topology_id.topology_uuid, topologyUuidObj->valuestring); - //DEBUG_PC("Link Endpoint (%d) -- TopologyId: %s (uuid string format)", i + 1, endPointLink->topology_id.topology_uuid); - } + parse_topology_Id(topologyIdObj, &endPointLink->topology_id); } // Get the deviceId cJSON* deviceIdObj = cJSON_GetObjectItem(endPointIdObj, "device_id"); @@ -1009,21 +1088,23 @@ void parse_json_link_endpoints_array(cJSON *endPointsLinkObj, struct link_t* l) */ ///////////////////////////////////////////////////////////////////////////////////////// void parsing_json_linkList_array(cJSON* linkListArray) { - DEBUG_PC(""); DEBUG_PC("======= PARSING OF THE LINK LIST ARRAY =========="); - for (gint i = 0; i < cJSON_GetArraySize(linkListArray); i++) { - linkList->numLinks++; - struct link_t* l = &(linkList->links[i]); - //l->numLinkEndPointIds = 0; - + for (gint i = 0; i < cJSON_GetArraySize(linkListArray); i++) { + struct link_t* l = g_malloc0(sizeof(struct link_t)); + if (l == NULL) { + DEBUG_PC("Memory Allocation Failure"); + exit(-1); + } cJSON* item = cJSON_GetArrayItem(linkListArray, i); + // Get the link Id (uuid) cJSON* linkIdObj = cJSON_GetObjectItem(item, "link_Id"); if (cJSON_IsString(linkIdObj)) { duplicate_string(l->linkId, linkIdObj->valuestring); DEBUG_PC(" * Link (%d) -- Id: %s (uuid)", i + 1, l->linkId); } + // Get the link endpoints (assumed to be p2p) cJSON* endPointsLinkObj = cJSON_GetObjectItem(item, "link_endpoint_ids"); if (cJSON_IsArray(endPointsLinkObj)) { @@ -1086,6 +1167,7 @@ void parsing_json_linkList_array(cJSON* linkListArray) { //DEBUG_PC("Link (%d) -- Latency: %f", i + 1, l->latency_characteristics.fixed_latency); } } + linkList = g_list_append(linkList, l); } return; } @@ -1103,15 +1185,22 @@ void parsing_json_linkList_array(cJSON* linkListArray) { void generate_reverse_linkList() { DEBUG_PC(""); DEBUG_PC("CREATION OF REVERSE LINKS"); - gint numLinks = linkList->numLinks; - - for (gint i = 0; i < numLinks; i++) { - struct link_t* refLink = &(linkList->links[i]); - struct link_t* newLink = &(linkList->links[numLinks + i]); - linkList->numLinks++; + gint numLinks = g_list_length (linkList); + DEBUG_PC("Initial Number of links in the main List: %d", numLinks); + gint i = 0; + for (GList* ln = g_list_first(linkList); + (ln) && (i < numLinks); + ln = g_list_next(ln), i++) + { + struct link_t* refLink = (struct link_t*)(ln->data); + struct link_t* newLink = g_malloc0(sizeof(struct link_t)); + if (newLink == NULL) { + DEBUG_PC("Memory Allocation Failure"); + exit(-1); + } // Copy the linkId + appending "_rev" duplicate_string(newLink->linkId, refLink->linkId); - strcat(newLink->linkId, "_rev"); + strcat(newLink->linkId, "_rev"); //DEBUG_PC("refLink: %s // newLink: %s", refLink->linkId, newLink->linkId); @@ -1124,7 +1213,7 @@ void generate_reverse_linkList() { exit(-1); } #endif - DEBUG_PC(" * Link[%d] -- Id: %s", numLinks + i, newLink->linkId); + //DEBUG_PC(" * Link[%d] -- Id: %s", numLinks + i, newLink->linkId); //DEBUG_PC("Number of Endpoints in Link: %d", refLink->numLinkEndPointIds); for (gint j = refLink->numLinkEndPointIds - 1, m = 0; j >= 0; j--, m++) { @@ -1134,9 +1223,9 @@ void generate_reverse_linkList() { duplicate_string(newEndPId->topology_id.contextId, refEndPId->topology_id.contextId); duplicate_string(newEndPId->topology_id.topology_uuid, refEndPId->topology_id.topology_uuid); //duplicate the deviceId and endPoint_uuid - duplicate_string(newEndPId->deviceId, refEndPId->deviceId); - duplicate_string(newEndPId->endPointId, refEndPId->endPointId); - DEBUG_PC("refLink Endpoint[%d]: %s(%s)", j, refEndPId->deviceId, refEndPId->endPointId); + duplicate_string(newEndPId->deviceId, refEndPId->endPointId); + duplicate_string(newEndPId->endPointId, refEndPId->deviceId); + //DEBUG_PC("refLink Endpoint[%d]: %s(%s)", j, refEndPId->deviceId, refEndPId->endPointId); //DEBUG_PC("newLink Endpoint[%d]: %s(%s)", m, newEndPId->deviceId, newEndPId->endPointId); newLink->numLinkEndPointIds++; } @@ -1158,11 +1247,87 @@ void generate_reverse_linkList() { // duplicate latency characteristics memcpy(&newLink->latency_characteristics.fixed_latency, &refLink->latency_characteristics.fixed_latency, sizeof(gdouble)); + // Append in the linkList the new creted Link + linkList = g_list_append(linkList, newLink); } - DEBUG_PC("Terminating Reverse Links [total: %d]", linkList->numLinks); + DEBUG_PC("Terminating Reverse Links [total links: %d]", g_list_length(linkList)); return; } +/////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief Function used to parse the JSON object/s for active services + * + * @param actServiceArray + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void parsing_json_activeService_array(cJSON* actServiceArray) { + DEBUG_PC(""); + DEBUG_PC("====== PARSING THE JSON CONTENTS OF THE ACTIVE SERVICES ======="); + + for (gint i = 0; i < cJSON_GetArraySize(actServiceArray); i++) { + struct activeService_t* actServ = g_malloc0(sizeof(struct activeService_t)); + if (actServ == NULL) { + DEBUG_PC("Memory Allocation Failure"); + exit(-1); + } + cJSON* item = cJSON_GetArrayItem(actServiceArray, i); + // ServiceId + cJSON* serviceIdObj = cJSON_GetObjectItem(item, "serviceId"); + if (cJSON_IsObject(serviceIdObj)) { + parse_json_serviceId(serviceIdObj, &actServ->serviceId); + } + // Service Type + cJSON* serviceTypeObj = cJSON_GetObjectItem(item, "serviceType"); + if (cJSON_IsNumber(serviceTypeObj)) + { + actServ->service_type = (guint)(serviceTypeObj->valuedouble); + print_service_type(actServ->service_type); + } + // Service Endpoints + cJSON* endPointIdsArray = cJSON_GetObjectItem(item, "service_endpoints_ids"); + if (cJSON_IsArray(endPointIdsArray)) { + parse_act_service_endPointsIds_array(endPointIdsArray, actServ); + } + // Parsing the active service path + actServ->activeServPath = NULL; + cJSON* actServPathArray = cJSON_GetObjectItem(item, "devices"); + if (cJSON_IsArray(endPointIdsArray)) { + for (gint j = 0; j < cJSON_GetArraySize(actServPathArray); j++) { + struct activeServPath_t* actServPath = g_malloc0(sizeof(struct activeServPath_t)); + if (actServPath == NULL) { + DEBUG_PC("Memory Allocation Failure"); + exit(-1); + } + cJSON* item2 = cJSON_GetArrayItem(item, j); + // Topology Id + cJSON* topologyIdObj = cJSON_GetObjectItem(item2, "topology_id"); + if (cJSON_IsObject(topologyIdObj)) { + parse_topology_Id(topologyIdObj, &actServPath->topology_id); + } + // Device Id + cJSON* deviceIdObj = cJSON_GetObjectItem(item2, "device_id"); + if (cJSON_IsString(deviceIdObj)) { + duplicate_string(actServPath->deviceId, deviceIdObj->valuestring); + } + // EndPointId + cJSON* endPointUUIDObj = cJSON_GetObjectItem(item2, "endpoint_uuid"); + if (cJSON_IsString(endPointUUIDObj)) { + duplicate_string(actServPath->endPointId, endPointUUIDObj->valuestring); + } + // Append element from the Active Service Path (i.e.,topologyId, deviceId and endpointId) + actServ->activeServPath = g_list_append(actServ->activeServPath, actServPath); + } + } + // append into the Actice Service List + activeServList = g_list_append(activeServList, actServ); + } + return; +} /////////////////////////////////////////////////////////////////////////////////////// /** @@ -1179,22 +1344,6 @@ void generate_reverse_linkList() { ///////////////////////////////////////////////////////////////////////////////////////// void parsing_json_obj_pathComp_request(cJSON * root, GIOChannel * source) { - //DEBUG_PC("**"); - if (deviceList == NULL){ - DEBUG_PC ("Device List does not exist ... STOP"); - exit(-1); - } - - if (linkList == NULL) { - DEBUG_PC("Link List does not exist ... STOP") - } - - if (serviceList == NULL) - { - DEBUG_PC ("Service List does not exist ... STOP"); - exit(-1); - } - // Set of services to seek their path and resource selection cJSON* serviceListArray = cJSON_GetObjectItem(root, "serviceList"); if (cJSON_IsArray(serviceListArray)) { @@ -1214,7 +1363,13 @@ void parsing_json_obj_pathComp_request(cJSON * root, GIOChannel * source) // In the context information, if solely the list of links are passed for a single direction, // the reverse direction MUST be created sythetically - generate_reverse_linkList(); + //generate_reverse_linkList(); + } + + // Get the list of active services + cJSON* actServiceArray = cJSON_GetObjectItem(root, "activeServList"); + if (cJSON_IsArray(actServiceArray)) { + parsing_json_activeService_array(actServiceArray); } return; } @@ -1296,19 +1451,16 @@ struct pathComp_client * RESTapi_client_create (GIOChannel * channel_client, gin * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void RESTapi_client_close (struct pathComp_client* client) -{ +void RESTapi_client_close (struct pathComp_client* client) { //DEBUG_PC("Closing the client (Id: %d) %p", client->type, client); //DEBUG_PC("Client ibuf: %p || obuf: %p", client->ibuf, client->obuf); - if (client->ibuf != NULL) - { + if (client->ibuf != NULL) { //DEBUG_PC("Client ibuf: %p", client->ibuf); stream_free(client->ibuf); client->ibuf = NULL; } - if (client->obuf != NULL) - { + if (client->obuf != NULL) { //DEBUG_PC("Client obuf: %p", client->obuf); stream_free(client->obuf); client->obuf = NULL; @@ -1334,16 +1486,14 @@ void RESTapi_client_close (struct pathComp_client* client) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void RESTapi_close_operations (GIOChannel * source) -{ +void RESTapi_close_operations (GIOChannel * source) { gint fd = g_io_channel_unix_get_fd (source); //DEBUG_PC ("Stop all the operations over the fd: %d", fd); g_io_channel_flush(source, NULL); GError *error = NULL; g_io_channel_shutdown (source, TRUE, &error); - if(error) - { + if(error) { DEBUG_PC ("An error occurred ..."); } g_io_channel_unref (source); @@ -1363,8 +1513,7 @@ void RESTapi_close_operations (GIOChannel * source) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void RESTapi_stop (struct pathComp_client* client, GIOChannel * source, gint fd) -{ +void RESTapi_stop (struct pathComp_client* client, GIOChannel * source, gint fd) { DEBUG_PC("Client Socket: %d is Stopped", fd); // remove client @@ -1388,38 +1537,31 @@ void RESTapi_stop (struct pathComp_client* client, GIOChannel * source, gint fd) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint RESTapi_get_line (GIOChannel *channel, gchar *buf, gint size) -{ +gint RESTapi_get_line (GIOChannel *channel, gchar *buf, gint size) { gint i = 0; //DEBUG_PC ("\n"); //DEBUG_PC ("----- Read REST API Line(\r\n) ------"); gint n = 0; guchar c = '\0'; // END OF FILE gboolean cr = FALSE; - while (i < size - 1) - { + while (i < size - 1) { n = read_channel (channel, &c, 1); - if (n == -1) - { + if (n == -1) { //DEBUG_PC ("Close the channel and eliminate the client"); return -1; } - if (n > 0) - { + if (n > 0) { //DEBUG_PC ("%c", c); buf[i] = c; i++; - if (c == '\r') - { + if (c == '\r') { cr = TRUE; } - if ((c == '\n') && (cr == TRUE)) - { + if ((c == '\n') && (cr == TRUE)) { break; } } - else - { + else { c = '\n'; buf[i] = c; i++; @@ -1448,8 +1590,7 @@ guint RESTapi_get_method (gchar *buf, gint *j) guint RestApiMethod = 0; gchar method[255]; gint i = 0; - while (!ISspace(buf[*j]) && (i < sizeof(method) - 1)) - { + while (!ISspace(buf[*j]) && (i < sizeof(method) - 1)) { method[i] = buf[*j]; i++; *j = *j + 1; @@ -1459,32 +1600,60 @@ guint RESTapi_get_method (gchar *buf, gint *j) // Check that the methods are GET, POST or PUT if (strcasecmp((const char *)method, "GET") && strcasecmp((const char *)method, "POST") && - strcasecmp ((const char *)method, "HTTP/1.1") && strcasecmp ((const char *)method, "PUT")) - { - DEBUG_PC ("The method: %s is not currently supported ...", method); + strcasecmp ((const char *)method, "HTTP/1.1") && strcasecmp ((const char *)method, "PUT")) { + DEBUG_PC ("%s is not a method ...", method); return RestApiMethod; } // Method selector - if (strncmp ((const char*)method, "GET", 3) == 0) - { + if (strncmp ((const char*)method, "GET", 3) == 0) { RestApiMethod = REST_API_METHOD_GET; } - else if (strncmp ((const char*)method, "POST", 4) == 0) - { + else if (strncmp ((const char*)method, "POST", 4) == 0) { RestApiMethod = REST_API_METHOD_POST; } - else if (strncmp ((const char *)method, "HTTP/1.1", 8) == 0) - { + else if (strncmp ((const char *)method, "HTTP/1.1", 8) == 0) { RestApiMethod = REST_API_METHOD_HTTP; } - else if (strncmp ((const char *)method, "PUT", 3) == 0) - { + else if (strncmp ((const char *)method, "PUT", 3) == 0) { RestApiMethod = REST_API_METHOD_PUT; - } - + } return RestApiMethod; } +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_RESTapi.c + * @brief Function used to check whether it is a supported method, and return the associated numerical id + * + * @param method + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +guint is_rest_api_method(char *method) { + guint RestApiMethod = 0; + if (strcasecmp((const char*)method, "GET") && strcasecmp((const char*)method, "POST") && + strcasecmp((const char*)method, "HTTP/1.1") && strcasecmp((const char*)method, "PUT")) { + DEBUG_PC("The method: %s is not currently supported ...", method); + return RestApiMethod; + } + // Method selector + if (strncmp((const char*)method, "GET", 3) == 0) { + RestApiMethod = REST_API_METHOD_GET; + } + else if (strncmp((const char*)method, "POST", 4) == 0) { + RestApiMethod = REST_API_METHOD_POST; + } + else if (strncmp((const char*)method, "HTTP/1.1", 8) == 0) { + RestApiMethod = REST_API_METHOD_HTTP; + } + else if (strncmp((const char*)method, "PUT", 3) == 0) { + RestApiMethod = REST_API_METHOD_PUT; + } + return RestApiMethod; +} + //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_RESTapi.c @@ -1538,8 +1707,7 @@ gint get_url (gchar *buf, gint *j, gchar *url) ///////////////////////////////////////////////////////////////////////////////////////// gint get_version (gchar *buf, gint *j, gchar *version) { // Skip space char - while (ISspace(buf[*j]) && (*j < strlen(buf))) - { + while (ISspace(buf[*j]) && (*j < strlen(buf))) { *j = *j + 1; } //DEBUG_PC ("buf[%d]: %c", *j, buf[*j]); @@ -1579,8 +1747,7 @@ gint triggering_routeComp (struct compRouteOutputList_t *compRouteList, gchar *a DEBUG_PC("Requested Algorithm: %s", algId); //////////////////// Algorithm Selector (RAId)////////////////////////////////////// // KSP algorithm - if (strncmp ((const char*)algId, "KSP", 3) == 0) - { + if (strncmp ((const char*)algId, "KSP", 3) == 0) { DEBUG_PC ("Alg Id: KSP"); httpCode = pathComp_ksp_alg(compRouteList); } @@ -1589,20 +1756,11 @@ gint triggering_routeComp (struct compRouteOutputList_t *compRouteList, gchar *a DEBUG_PC("Alg Id: SP"); httpCode = pathComp_sp_alg(compRouteList); } -#if 0 - // Infrastructure Abstraction (InA) - else if (strncmp ((const char*)raId, "InA", 3) == 0) - { - //DEBUG_PC ("RA: InA"); - httpCode = ra_InA_alg (compRouteList); - } - // Global Concurrent Optimization (GCO): Resoration / Re-Allocation / Re-Optimization - else if (strncmp ((const char*)raId, "GCO", 3) == 0) - { - //DEBUG_PC ("RA: GCO"); - httpCode = ra_GCO_alg (compRouteList); + // energy-aware routing + else if (strncmp((const char*)algId, "EAR", 3) == 0) { + DEBUG_PC("Alg Id: Energy Aware Routing, EAR"); + httpCode = pathComp_ear_alg(compRouteList); } -#endif return httpCode; } @@ -1619,8 +1777,7 @@ gint triggering_routeComp (struct compRouteOutputList_t *compRouteList, gchar *a * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) -{ +gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) { /** some checks */ g_assert(source != NULL); g_assert(data != NULL); @@ -1638,24 +1795,21 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) gint fd = g_io_channel_unix_get_fd (source); DEBUG_PC ("fd: %d, cond: %d", fd, cond); - if (cond != G_IO_IN) - { + if (cond != G_IO_IN) { DEBUG_PC ("Something happening with the channel and fd ... (cond: %d)", cond); RESTapi_stop(client, source, fd); return FALSE; } - /** Clear input buffer. */ + // Clear input buffer stream_reset (client->ibuf); // get line gint nbytes = RESTapi_get_line (source, buf, sizeof (buf)); - if (nbytes == -1) - { + if (nbytes == -1) { DEBUG_PC ("nbytes -1 ... CLOSE CLIENT FD and eliminate CLIENT"); RESTapi_stop(client, source, fd); return FALSE; - } - + } if ((buf[0] == '\n') && (nbytes == 1)) { //DEBUG_PC (" -- buf[0] = newline --"); @@ -1664,95 +1818,90 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) } gint i = 0, j = 0; - // Get the REST Method - guint RestApiMethod = RESTapi_get_method (buf, &j); - if (RestApiMethod == 0) { - DEBUG_PC ("The method is NOT supported ..."); - RESTapi_unimplemented (source); - RESTapi_stop(client, source, fd); - return FALSE; - } - - // get the REST url - gchar url[255]; - i = get_url (buf, &j, url); - url[i] = '\0'; - // GET - used for checking status of pathComp ... used url /pathComp/api/v1/health - if (RestApiMethod == REST_API_METHOD_GET) { - if (strncmp((const char*)url, "/health", 7) != 0) { - DEBUG_PC("unknown url [%s] for GET method -- Heatlh function", url); - RESTapi_stop(client, source, fd); - exit(-1); + while (1) { + DEBUG_PC("%s", buf); + char word[255]; + while (!ISspace(buf[j]) && (i < sizeof(word) - 1)) { + word[i] = buf[j]; i++; j++; } - else { - DEBUG_PC("Sending API Response OK to health requests"); - rapi_response_ok(source, HTTP_RETURN_CODE_OK, NULL); - return TRUE; + word[i] = '\0'; + // Check if word is bound to a Method, i.e., POST, GET, HTTP/1.1. + guint method = is_rest_api_method(word); + if (method == 0) { + // ignore other REST fields i.e., Host:, User-Agent:, Accept: .... + break; } - } - - // for method POST, PUT check that the url is "/pathComp" - if (RestApiMethod == REST_API_METHOD_POST) { - if (strncmp((const char*)url, "/pathComp/api/v1/compRoute", 26) != 0) - { - DEBUG_PC("Unknown url: %s", url); - RESTapi_stop(client, source, fd); - exit(-1); + // word is bound to a known / supported REST Method + else { + gchar url[255]; + i = get_url(buf, &j, url); + url[i] = '\0'; + // GET - used for checking status of pathComp ... used url /pathComp/api/v1/health + if (method == REST_API_METHOD_GET) { + if (strncmp((const char*)url, "/health", 7) != 0) { + DEBUG_PC("unknown url [%s] for GET method -- Heatlh function", url); + RESTapi_stop(client, source, fd); + exit(-1); + } + else { + DEBUG_PC("Sending API Response OK to health requests"); + rapi_response_ok(source, HTTP_RETURN_CODE_OK, NULL); + return TRUE; + } + } + // for method POST, PUT check that the url is "/pathComp" + if (method == REST_API_METHOD_POST) { + if (strncmp((const char*)url, "/pathComp/api/v1/compRoute", 26) != 0) { + DEBUG_PC("Unknown url: %s", url); + RESTapi_stop(client, source, fd); + exit(-1); + } + } + // get the version + i = get_version(buf, &j, version); + version[i] = '\0'; + break; } } - - // get the version - i = get_version (buf, &j, version); - version[i] = '\0'; - // Assume HTTP/1.1, then there is Host Header memset(buf, '\0', sizeof(buf)); nbytes = RESTapi_get_line(source, buf, sizeof (buf)); - if (nbytes == -1) - { + if (nbytes == -1) { DEBUG_PC ("nbytes -1 ... then close the fd and eliminate associated client"); RESTapi_stop(client, source, fd); return FALSE; - } - - //DEBUG_PC ("Header: %s", buf); + } // Headers --- The Header Fields ends up with a void line (i.e., \r\n) - while ((nbytes > 0) && (strcmp ("\r\n", (const char *)buf) != 0)) - { + while ((nbytes > 0) && (strcmp ("\r\n", (const char *)buf) != 0)) { /* read & discard headers */ memset(buf, '\0', sizeof(buf)); nbytes = RESTapi_get_line (source, buf, sizeof (buf)); - if (nbytes == -1) - { + if (nbytes == -1) { DEBUG_PC ("nbytes -1 ... then close the fd and eliminate associated client"); RESTapi_stop(client, source, fd); return FALSE; } //DEBUG_PC ("Header: %s", buf); - if (strncmp ((const char *)buf, "Content-Length:", 15) == 0) - { + if (strncmp ((const char *)buf, "Content-Length:", 15) == 0) { //DEBUG_PC ("Header Content-Length Found"); gchar str[20]; gint i = 15, k = 0; // "Content-Length:" We skip the first 16 characters to directly retrieve the length in bytes of the Body of Request gchar contentLength[255]; memset (contentLength, '\0', sizeof (contentLength)); - while (buf[i] != '\r') - { + while (buf[i] != '\r') { //DEBUG_PC ("%c", buf[i]); str[k] = buf[i]; k++, i++; } str[k] = '\0'; j = 0, i = 0; - while (ISspace(str[j]) && (j < strlen(str))) - { + while (ISspace(str[j]) && (j < strlen(str))) { j++; } - while (j < strlen(str)) - { + while (j < strlen(str)) { contentLength[i] = str[j]; i++; j++; } @@ -1762,8 +1911,7 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) } } //DEBUG_PC("Read Entire HTTP Header"); - if (body_length == 0) - { + if (body_length == 0) { DEBUG_PC ("--- NO REST API Body length (length = %d) ---", body_length); return TRUE; } @@ -1772,23 +1920,23 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// //DEBUG_PC ("REST API Request - Body -"); nbytes = read_channel (source, (guchar *)(client->ibuf->data + client->ibuf->putp), body_length); - if ((nbytes < 0) && (body_length > 0)) - { + if ((nbytes < 0) && (body_length > 0)) { DEBUG_PC ("nbytes: %d; body_length: %d", nbytes, body_length); exit (-1); - } - + } client->ibuf->putp += nbytes; client->ibuf->endp += nbytes; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Parsing the contents of the Request /////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // build the device list - deviceList = create_device_list(); + // build the device list + deviceList = NULL; // build the link list - linkList = create_link_list(); + linkList = NULL; // Create the network connectivity service list - serviceList = create_service_list(); + serviceList = NULL; + // Create the active service List + activeServList = NULL; // Process the json contents and store relevant information at Device, Link, // and network connectivity service @@ -1807,22 +1955,21 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) gint httpCode = triggering_routeComp (compRouteOutputList, algId); // Send the response to the REST API Client - if (httpCode != HTTP_RETURN_CODE_OK) - { + if (httpCode != HTTP_RETURN_CODE_OK) { DEBUG_PC ("HTTP CODE: %d -- NO OK", httpCode); rapi_response (source, httpCode); } - else - { + else { DEBUG_PC ("HTTP CODE: %d -- OK", httpCode); rapi_response_ok (source, httpCode, compRouteOutputList); } // Release the variables - g_free (compRouteOutputList); - g_free(linkList); - g_free(deviceList); - g_free(serviceList); + g_free (compRouteOutputList); + g_list_free_full(g_steal_pointer(&linkList), (GDestroyNotify)destroy_link); + g_list_free_full(g_steal_pointer(&deviceList), (GDestroyNotify)destroy_device); + g_list_free_full(g_steal_pointer(&serviceList), (GDestroyNotify)destroy_requested_service); + g_list_free_full(g_steal_pointer(&activeServList), (GDestroyNotify)destroy_active_service); return TRUE; } @@ -1839,23 +1986,20 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gboolean RESTapi_tcp_new_connection(GIOChannel *source, GIOCondition cond, gpointer data) -{ +gboolean RESTapi_tcp_new_connection(GIOChannel *source, GIOCondition cond, gpointer data) { DEBUG_PC (" ****** New TCP Connection (REST API) ******"); /** get size of client_addre structure */ struct sockaddr_in client_addr; socklen_t client = sizeof(client_addr); - if ((cond == G_IO_HUP) || (cond == G_IO_ERR) || (G_IO_NVAL)) - { + if ((cond == G_IO_HUP) || (cond == G_IO_ERR) || (G_IO_NVAL)) { //DEBUG_PC ("Something happening with the channel and fd ... cond: %d", cond); // Find the associated client (by the fd) and remove from PATH COMP client list. // Stop all the operations over that PATH COMP client bound channel struct pathComp_client *pathComp_client = NULL; gint fd = g_io_channel_unix_get_fd (source); GList *found = g_list_find_custom (RESTapi_tcp_client_list, &fd, find_rl_client_by_fd); - if (found != NULL) - { + if (found != NULL) { pathComp_client = (struct pathComp_client*)(found->data); // remove client RESTapi_client_close(pathComp_client); @@ -1865,28 +2009,22 @@ gboolean RESTapi_tcp_new_connection(GIOChannel *source, GIOCondition cond, gpoin return FALSE; } } - if (cond == G_IO_IN) - { + if (cond == G_IO_IN) { gint new = accept(g_io_channel_unix_get_fd(source), (struct sockaddr*)&client_addr, &client); - if (new < 0) - { + if (new < 0) { //DEBUG_PC ("Unable to accept new connection"); return FALSE; } - /** new channel */ + // new channel GIOChannel * new_channel = g_io_channel_unix_new (new); //DEBUG_PC ("TCP Connection (REST API) is UP; (socket: %d)", new); - - /** create pathComp client */ + // create pathComp client struct pathComp_client *new_client = RESTapi_client_create (new_channel, new); - /** - * force binary encoding with NULL - */ + // force binary encoding with NULL GError *error = NULL; - if ( g_io_channel_set_encoding (new_channel, NULL, &error) != G_IO_STATUS_NORMAL) - { + if ( g_io_channel_set_encoding (new_channel, NULL, &error) != G_IO_STATUS_NORMAL) { DEBUG_PC ("Error: %s", error->message); exit (-1); } @@ -1894,8 +2032,7 @@ gboolean RESTapi_tcp_new_connection(GIOChannel *source, GIOCondition cond, gpoin // On unbuffered channels, it is safe to mix read // & write calls from the new and old APIs. g_io_channel_set_buffered (new_channel, FALSE); - if (g_io_channel_set_flags (new_channel, G_IO_FLAG_NONBLOCK, &error) != G_IO_STATUS_NORMAL ) - { + if (g_io_channel_set_flags (new_channel, G_IO_FLAG_NONBLOCK, &error) != G_IO_STATUS_NORMAL ) { DEBUG_PC ("Error: %s", error->message); exit (-1); } diff --git a/src/pathcomp/backend/pathComp_RESTapi.h b/src/pathcomp/backend/pathComp_RESTapi.h index 80e63da7c..fb021b3dd 100644 --- a/src/pathcomp/backend/pathComp_RESTapi.h +++ b/src/pathcomp/backend/pathComp_RESTapi.h @@ -51,8 +51,7 @@ // List of tcp clients connected to PATH COMP #define PATH_COMP_CLIENT_TYPE 1000 -struct pathComp_client -{ +struct pathComp_client { /** IO Channel from client. */ GIOChannel *channel; diff --git a/src/pathcomp/backend/pathComp_ear.c b/src/pathcomp/backend/pathComp_ear.c new file mode 100644 index 000000000..c13993b64 --- /dev/null +++ b/src/pathcomp/backend/pathComp_ear.c @@ -0,0 +1,213 @@ +//////////////////////////////////////////////////////////////////////////////////////// +/** + * # 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathComp_log.h" +#include "pathComp_tools.h" +#include "pathComp_ear.h" + +// Global Variables +GList* contextSet; + +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_ear.c + * @brief Iterates over the list of network connectivity service requests + * to compute their own paths fulfilling the constraints and minimizing the + * total consume energy (power) + * + * @param outputList + * + * @author Ricardo Martínez + * @date 2022 + */ +void ear_comp_services(struct compRouteOutputList_t* oPathList, gint activeFlag) { + g_assert(oPathList); + // Check at least there is a service to be processed + if (g_list_length(serviceList) == 0) { + DEBUG_PC("serviceList is Empty..."); + return; + } + gint i = 0; + DEBUG_PC("[EAR]----- Starting the Energy Aware Routing Computation ------"); + DEBUG_PC("[EAR]----- Over Context %s Devices and Links", activeFlag ? "Active" : "All"); + for (GList* listnode = g_list_first(serviceList); + listnode; + listnode = g_list_next(listnode), i++) { + struct service_t* service = (struct service_t*)(listnode->data); + + DEBUG_PC("[EAR] Triggering Computation ServiceId: %s [ContextId: %s]", service->serviceId.service_uuid, service->serviceId.contextId); + struct compRouteOutput_t* pathService = &(oPathList->compRouteConnection[i]); + DEBUG_PC("Number of pathService[%d]->paths: %d", i, pathService->numPaths); + // check endpoints of the service are different (PE devices/nodes are different) + if (same_src_dst_pe_nodeid(service) == 0) { + DEBUG_PC("[EAR] PEs are the same... no path computation"); + comp_route_connection_issue_handler(pathService, service); + oPathList->numCompRouteConnList++; + continue; + } + struct graph_t* g = get_graph_by_contextId(contextSet, service->serviceId.contextId); + if (g == NULL) { + DEBUG_PC("[EAR] contextId: %s NOT in the ContextSet ... then NO graph", service->serviceId.contextId); + comp_route_connection_issue_handler(pathService, service); + oPathList->numCompRouteConnList++; + continue; + } + alg_comp(service, pathService, g, ENERGY_EFFICIENT_ARGUMENT); + 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_ear.c + * @brief Tries to route all the services over the active devices and links. If not all + * these services can be routed, then it is tried to route them through the whole context + * including both active and slept/power off devices and links + * + * @param oList + * + * @author Ricardo Martínez + * @date 2022 + */ + //////////////////////////////////////////////////////////////////////////////////////// +void ear_comp(struct compRouteOutputList_t* oList) { + g_assert(oList); + + DEBUG_PC("Number of services to be processed: %d", g_list_length(serviceList)); + // Make a copy of oList to be derived from the active devices and links + struct compRouteOutputList_t* oListTmp = create_route_list(); + duplicate_route_list(oListTmp, oList); + print_path_connection_list(oListTmp); + + // 1st - try to accommodate all the requested service over the active device and links + gint activeContext = 1; + // Create the context for the active devicesand links + DEBUG_PC("=========================== Building the Active ContextSet ================================="); + contextSet = NULL; + build_contextSet_active(&contextSet); + //print_contextSet(contextSet); + ear_comp_services(oListTmp, activeContext); + + gint numSuccessPaths = 0; + // Check the number of succesfully computed paths, i.e., without path issues + for (gint i = 0; i < oListTmp->numCompRouteConnList; i++) { + struct compRouteOutput_t* ro = &(oListTmp->compRouteConnection[i]); + DEBUG_PC("Number of paths: %d for oListTmp[%d]", ro->numPaths, i); + if (ro->noPathIssue == 0) { + numSuccessPaths++; + } + } + if (numSuccessPaths == oListTmp->numCompRouteConnList) { + duplicate_route_list(oList, oListTmp); + g_free(oListTmp); + return; + } + // 2nd - If not all the services have been accommodated, use the whole device and links + // Create the context for all the devices and links + + // Remove the previous Context subject to active devices and links + g_list_free_full(g_steal_pointer(&contextSet), (GDestroyNotify)destroy_context); + contextSet = NULL; + DEBUG_PC("====================== Building the whole ContextSet ====================================="); + build_contextSet(&contextSet); + //print_contextSet(contextSet); + + activeContext = 0; // Active flag is not SET + ear_comp_services(oList, activeContext); + return; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_ear.c + * @brief handles the path computation for energy aware routing + * + * @param compRouteOutput + * + * @author Ricardo Martínez + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +gint pathComp_ear_alg(struct compRouteOutputList_t* routeConnList) { + g_assert(routeConnList); + print_path_connection_list(routeConnList); + + gint numSuccesPathComp = 0, numPathCompIntents = 0; + + DEBUG_PC("================================================================"); + DEBUG_PC("=========================== EAR ========================="); + DEBUG_PC("================================================================"); + // increase the number of Path Comp. Intents + numPathCompIntents++; + gint http_code = HTTP_CODE_OK; + + // timestamp t0 + struct timeval t0; + gettimeofday(&t0, NULL); + + // Initialize and create the contextSet + //contextSet = NULL; + //build_contextSet(contextSet); + //print_contextSet(contextSet); +#if 1 + //Triggering the path computation for each specific network connectivity service + ear_comp(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; +} \ No newline at end of file diff --git a/src/pathcomp/backend/pathComp_ear.h b/src/pathcomp/backend/pathComp_ear.h new file mode 100644 index 000000000..70210d869 --- /dev/null +++ b/src/pathcomp/backend/pathComp_ear.h @@ -0,0 +1,30 @@ +//////////////////////////////////////////////////////////////////////////////////////// +/** + * # 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_EAR_H +#define _PATHCOMP_EAR_H + +#include +#include +#include + + // Prototype of external declaration of functions +gint pathComp_ear_alg(struct compRouteOutputList_t*); + +#endif \ No newline at end of file diff --git a/src/pathcomp/backend/pathComp_ksp.c b/src/pathcomp/backend/pathComp_ksp.c index 85c5e7505..5d394369a 100644 --- a/src/pathcomp/backend/pathComp_ksp.c +++ b/src/pathcomp/backend/pathComp_ksp.c @@ -39,401 +39,7 @@ #include "pathComp_ksp.h" // Global Variables -struct map_nodes_t *mapNodes; -struct graph_t *graph; -struct contextSet_t* contextSet; - -/////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_ksp.c - * @brief Dijkstra algorithm - * - * @param srcMapIndex - * @param dstMapIndex - * @param g - * @param s - * @param SN - * @param RP - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -void sp_comp(gint srcMapIndex, gint dstMapIndex, struct graph_t* g, struct service_t* s, - struct nodes_t* SN, struct compRouteOutputItem_t* RP) { - 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; - - // 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; - duplicate_node_id(&mapNodes->map[srcMapIndex].verticeId, &nodeItem->node); - 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); - (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(S, g_free); - g_list_free_full(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); - (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(S, g_free); - g_list_free_full(Q, g_free); - return; -} - -/////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_ksp.c - * @brief KSP computation using Dijkstra algorithm - * - * @param pred - * @param g - * @param s - * @param SN - * @param RP - * - * @author Ricardo Martínez - * @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) { - 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 route - sp_comp(srcMapIndex, dstMapIndex, g, s, SN, RP); - - // 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_ksp.c - * @brief K-CSPF algorithm execution (YEN algorithm) - * - * @param s - * @param path - * @param g - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -void alg_comp(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 - 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); - 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]; - // Get the delay and cost - memcpy(&p->cost, &dst_map->distance, sizeof(gdouble)); - memcpy(&p->availCap, &dst_map->avaiBandwidth, sizeof(dst_map->avaiBandwidth)); - memcpy(&p->delay, &dst_map->latency, sizeof(mapNodes->map[indexDest].latency)); - DEBUG_PC ("Computed Path Avail Bw: %f, Path Cost: %f, latency: %f", p->availCap, p->cost, p->delay); - print_path(p); - - // If 1st SP satisfies the requirements from the req, STOP - gboolean feasibleRoute = check_computed_path_feasability(s, p); - if (feasibleRoute == TRUE) { - DEBUG_PC("1st K-CSPF FEASIBLE, STOP!"); - 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("1st CSPF COMPUTATION IS NOT FEASIBLE --> TRIGGER K COMPUTATIONS"); - // Create A and B sets of paths to handle the YEN algorithm - struct path_set_t* A = create_path_set(); - struct path_set_t* B = create_path_set(); - - // Add the previously 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(); - struct nodes_t* 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("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(); - // Baseline graph - //build_graph (gAux); - 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) == -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]; - - memcpy(&newKpath->cost, &dst_map->distance, sizeof(gdouble)); - memcpy(&newKpath->availCap, &dst_map->avaiBandwidth, sizeof(dst_map->avaiBandwidth)); - memcpy(&newKpath->delay, &dst_map->latency, sizeof(mapNodes->map[indexDest].latency)); - DEBUG_PC("New PATH (@ kth: %d) ADDED to B[%d] - {Path Cost: %f, e2e latency: %f, bw: %f ", k, B->numPaths, newKpath->cost, newKpath->delay, newKpath->availCap); - // 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 paths contained in B by cost and latency and available bandwidth - sort_path_set(B); - - // Add the lowest path into A[k] - DEBUG_PC("-------------------------------------------------------------"); - DEBUG_PC("To Add SP from B[0] to A[%d] --- Path Cost: %f, e2e Latency: %f", A->numPaths, B->paths[0].cost, B->paths[0].delay); - duplicate_path(&B->paths[0], &A->paths[A->numPaths]); - A->numPaths++; - DEBUG_PC("A Set size: %d", A->numPaths); - DEBUG_PC("-------------------------------------------------------------"); - - // Remove/pòp 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 = &(path->service_endpoints_id[m]); - copy_service_endpoint_id(oEp, iEp); - } - - for (gint ksp = 1; 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[k-th%d] available: %f, pathCost: %f; latency: %f", ksp, A->paths[ksp].availCap, A->paths[ksp].cost, A->paths[ksp].delay); - 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; -} +GList* contextSet; //////////////////////////////////////////////////////////////////////////////////////// /** @@ -449,14 +55,20 @@ void alg_comp(struct service_t* s, struct compRouteOutput_t* path, struct graph_ ///////////////////////////////////////////////////////////////////////////////////////// void ksp_alg_execution_services(struct compRouteOutputList_t* outputList) { g_assert(outputList); - g_assert(contextSet); - g_assert(serviceList); - + // Check at least there is a service to be processed + if (g_list_length(serviceList) == 0) { + DEBUG_PC("serviceList is Empty..."); + return; + } DEBUG_PC("----- Starting the KSP Computation ------"); // Iterate over the list of requested network connectivity services - for (gint i = 0; i < serviceList->numServiceList; i++) { - struct service_t* service = &(serviceList->services[i]); + 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 = &(outputList->compRouteConnection[i]); @@ -475,13 +87,12 @@ void ksp_alg_execution_services(struct compRouteOutputList_t* outputList) { outputList->numCompRouteConnList++; continue; } - alg_comp(service, pathService, g); + alg_comp(service, pathService, g, NO_OPTIMIZATION_ARGUMENT); // last parameter 0 is related to an optimization computation argument outputList->numCompRouteConnList++; - // for each network connectivity service, a single computed path (out of the KCSP) is retuned + // for each network connectivity service, a single computed path (out of the KSP) 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) - { + if (pathService->noPathIssue == NO_PATH_CONS_ISSUE) { continue; } struct path_t* path = &(pathService->paths[pathService->numPaths - 1]); @@ -520,9 +131,9 @@ gint pathComp_ksp_alg(struct compRouteOutputList_t * routeConnList) gettimeofday(&t0, NULL); // Allocate memory for the context - contextSet = create_contextSet(); + contextSet = NULL; // Build up the contextSet (>= 1) - build_contextSet(contextSet); + build_contextSet(&contextSet); print_contextSet(contextSet); #if 1 //Triggering the path computation for each specific network connectivity service @@ -540,6 +151,6 @@ gint pathComp_ksp_alg(struct compRouteOutputList_t * routeConnList) print_path_connection_list(routeConnList); #endif - g_free(contextSet); + g_list_free_full(g_steal_pointer(&contextSet), (GDestroyNotify)destroy_context); return http_code; } \ No newline at end of file diff --git a/src/pathcomp/backend/pathComp_sp.c b/src/pathcomp/backend/pathComp_sp.c index 735027faf..6510a0d7d 100644 --- a/src/pathcomp/backend/pathComp_sp.c +++ b/src/pathcomp/backend/pathComp_sp.c @@ -39,74 +39,7 @@ #include "pathComp_sp.h" // Global Variables -struct map_nodes_t* mapNodes; -struct graph_t* graph; -struct contextSet_t* contextSet; - -/////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_sp.c - * @brief Excecution Dijkstra algorithm - * - * @param srcMapIndex - * @param dstMapIndex - * @param g - * @param s - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -void dijkstra(gint srcMapIndex, gint dstMapIndex, struct graph_t* g, struct service_t* s) { - 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; - - // 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; - duplicate_node_id(&mapNodes->map[srcMapIndex].verticeId, &nodeItem->node); - Q = g_list_insert_sorted(Q, nodeItem, sort_by_distance); - - 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); - (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(S, g_free); - g_list_free_full(Q, g_free); - return; -} +GList* contextSet; /////////////////////////////////////////////////////////////////////////////////// /** @@ -116,12 +49,13 @@ void dijkstra(gint srcMapIndex, gint dstMapIndex, struct graph_t* g, struct serv * @param pred * @param g * @param s + * @param mapNodes * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint computation(struct pred_t* pred, struct graph_t* g, struct service_t* s) { +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); @@ -140,7 +74,7 @@ gint computation(struct pred_t* pred, struct graph_t* g, struct service_t* s) { } // Compute the shortest path - dijkstra(srcMapIndex, dstMapIndex, g, s); + 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); @@ -182,7 +116,7 @@ void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* pa g_assert(g); // create map of devices / nodes to handle the path computation using the context - mapNodes = create_map_node(); + struct map_nodes_t *mapNodes = create_map_node(); build_map_node(mapNodes, g); // predecessors to store the computed path @@ -192,7 +126,7 @@ void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* pa struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]); // SP computation - gint done = computation(predecessors, g, s); + 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); @@ -207,11 +141,8 @@ void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* pa //DEBUG_PC ("Path is constructed"); gint indexDest = get_map_index_by_nodeId(eEp->device_uuid, mapNodes); - struct map_t* dst_map = &mapNodes->map[indexDest]; - // Get the delay and cost - memcpy(&p->cost, &dst_map->distance, sizeof(gdouble)); - memcpy(&p->availCap, &dst_map->avaiBandwidth, sizeof(dst_map->avaiBandwidth)); - memcpy(&p->delay, &dst_map->latency, sizeof(mapNodes->map[indexDest].latency)); + 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); @@ -242,10 +173,8 @@ void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* pa g_free(mapNodes); return; } - DEBUG_PC("SP FAILED!!!"); comp_route_connection_issue_handler(path, s); - return; } @@ -260,16 +189,21 @@ void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* pa * @author Ricardo Martínez * @date 2022 */ -void sp_execution_services(struct compRouteOutputList_t* oPathList) -{ - g_assert(oPathList); - g_assert(contextSet); - g_assert(serviceList); +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 ------"); - - for (gint i = 0; i < serviceList->numServiceList; i++) { - struct service_t* service = &(serviceList->services[i]); + 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]); @@ -317,10 +251,8 @@ void sp_execution_services(struct compRouteOutputList_t* oPathList) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) -{ +gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) { g_assert(routeConnList); - gint numSuccesPathComp = 0, numPathCompIntents = 0; DEBUG_PC("================================================================"); @@ -335,9 +267,9 @@ gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) gettimeofday(&t0, NULL); // Allocate memory for the context - contextSet = create_contextSet(); + contextSet = NULL; // Build up the contextSet (>= 1) - build_contextSet(contextSet); + build_contextSet(&contextSet); print_contextSet(contextSet); #if 1 //Triggering the path computation for each specific network connectivity service @@ -355,7 +287,7 @@ gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) print_path_connection_list(routeConnList); #endif - g_free(contextSet); + 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 84cf63994..139d97325 100644 --- a/src/pathcomp/backend/pathComp_tools.c +++ b/src/pathcomp/backend/pathComp_tools.c @@ -63,7 +63,6 @@ struct timeval tv_adjust (struct timeval a) { a.tv_usec -= 1000000; a.tv_sec++; } - while (a.tv_usec < 0) { a.tv_usec += 1000000; a.tv_sec--; @@ -84,8 +83,7 @@ struct timeval tv_adjust (struct timeval a) { */ //////////////////////////////////////////////////////////////////////////////////////// void duplicate_string(gchar* dst, gchar* src) { - g_assert(dst); - g_assert(src); + g_assert(dst); g_assert(src); strcpy(dst, src); dst[strlen(dst)] = '\0'; return; @@ -103,16 +101,15 @@ void duplicate_string(gchar* dst, gchar* src) { */ ///////////////////////////////////////////////////////////////////////////////////////// void print_path (struct compRouteOutputItem_t *p) { - g_assert(p); - + g_assert(p); DEBUG_PC ("=========== COMPUTED PATH ======================="); - DEBUG_PC ("Path Avail. Bw: %f, E2E Path Latency: %f, Path Cost: %f", p->availCap, p->delay, p->cost); + 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 ("aNodeId: %s (%s) --> zNodeId: %s (%s)", p->routeElement[k].aNodeId.nodeId, p->routeElement[k].aEndPointId, + 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("linkId: %s", p->routeElement[k].linkId); - DEBUG_PC("aTopologyId: %s", p->routeElement[k].aTopologyId); - DEBUG_PC("zTopologyId: %s", p->routeElement[k].zTopologyId); + 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; @@ -132,8 +129,8 @@ void print_path (struct compRouteOutputItem_t *p) { void print_path_t(struct path_t* p) { g_assert(p); DEBUG_PC(" ============ COMPUTED OUTPUT PATH ================="); - DEBUG_PC("Path Avail Capacity: %f, Cost: %f, Latency: %f", p->path_capacity.value, - p->path_cost.cost_value, p->path_latency.fixed_latency); + 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); @@ -148,6 +145,25 @@ void print_path_t(struct path_t* p) { return; } +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_tools.c + * @brief Function used allocate memory for struct path_t + * + * + * @author Ricardo Martínez + * @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 @@ -182,12 +198,9 @@ gchar* get_uuid_char(uuid_t uuid) { */ ///////////////////////////////////////////////////////////////////////////////////////// void copy_service_id(struct serviceId_t* o, struct serviceId_t* i) { - g_assert(o); - g_assert(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; } @@ -204,8 +217,7 @@ void copy_service_id(struct serviceId_t* o, struct serviceId_t* i) { */ ///////////////////////////////////////////////////////////////////////////////////////// void copy_service_endpoint_id(struct service_endpoints_id_t* oEp, struct service_endpoints_id_t* iEp) { - g_assert(oEp); - g_assert(iEp); + g_assert(oEp); g_assert(iEp); // copy topology information memcpy(oEp->topology_id.contextId, iEp->topology_id.contextId, sizeof(iEp->topology_id.contextId)); @@ -220,8 +232,8 @@ void copy_service_endpoint_id(struct service_endpoints_id_t* oEp, struct service //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_tools.c - * @brief From the set of contexts, it is returned the graph associated to that contexct matching - * with the passed contextId + * @brief From the set of contexts, it is returned the graph associated to that context matching + * with the passed contextId. * * @param Set * @param contextId @@ -230,15 +242,16 @@ void copy_service_endpoint_id(struct service_endpoints_id_t* oEp, struct service * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct graph_t* get_graph_by_contextId(struct contextSet_t* Set, gchar* contextId) { - g_assert(Set); +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 (gint i = 0; i < Set->num_context_set; i++) { - struct context_t* context = &(Set->contextList[i]); + 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; @@ -301,16 +314,13 @@ struct path_constraints_t * get_path_constraints(struct service_t* s) { * @file pathComp_tools.c * @brief Creates the predecessors to keep the computed path * - * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct pred_t * create_predecessors () -{ +struct pred_t * create_predecessors () { struct pred_t *predecessors = g_malloc0 (sizeof (struct pred_t)); - if (predecessors == NULL) - { + if (predecessors == NULL) { DEBUG_PC ("memory allocation failed\n"); exit (-1); } @@ -327,11 +337,9 @@ struct pred_t * create_predecessors () * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct edges_t* create_edge() -{ +struct edges_t* create_edge() { struct edges_t* e = g_malloc0(sizeof(struct edges_t)); - if (e == NULL) - { + if (e == NULL) { DEBUG_PC("Memory allocation failed\n"); exit(-1); } @@ -380,16 +388,13 @@ void print_predecessors (struct pred_t *p) * @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); +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 (); + struct edges_t *e = create_edge(); get_edge_from_map_by_node (e, v, map); // Get u (being source of edge e) @@ -420,9 +425,7 @@ void build_predecessors (struct pred_t *p, struct service_t *s, struct map_nodes p->numPredComp++; } print_predecessors (p); - g_free (e); - g_free(v); - g_free(srcNode); + g_free (e); g_free(v); g_free(srcNode); return; } @@ -456,11 +459,9 @@ struct nodes_t * create_node () * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct routeElement_t * create_routeElement () -{ +struct routeElement_t * create_routeElement () { struct routeElement_t *rE = g_malloc0 (sizeof (struct routeElement_t)); - if (rE == NULL) - { + if (rE == NULL) { DEBUG_PC ("memory allocation problem"); exit (-1); } @@ -479,11 +480,9 @@ struct routeElement_t * create_routeElement () * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void duplicate_node_id (struct nodes_t *src, struct nodes_t *dst) -{ +void duplicate_node_id (struct nodes_t *src, struct nodes_t *dst) { g_assert (src); - g_assert (dst); - + g_assert (dst); //DEBUG_PC ("Duplicate nodeId for %s", src->nodeId); strcpy (dst->nodeId, src->nodeId); return; @@ -501,8 +500,7 @@ void duplicate_node_id (struct nodes_t *src, struct nodes_t *dst) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint compare_node_id (struct nodes_t *a, struct nodes_t *b) -{ +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))); @@ -545,8 +543,7 @@ void duplicate_routeElement (struct routeElement_t *src, struct routeElement_t * */ ///////////////////////////////////////////////////////////////////////////////////////// void duplicate_edge (struct edges_t *e1, struct edges_t *e2) { - g_assert (e1); - g_assert (e2); + g_assert (e1); g_assert (e2); duplicate_node_id (&e2->aNodeId, &e1->aNodeId); duplicate_node_id (&e2->zNodeId, &e1->zNodeId); @@ -564,7 +561,8 @@ void duplicate_edge (struct edges_t *e1, struct edges_t *e2) { memcpy(&e1->availCap, &e2->availCap, sizeof(gdouble)); memcpy (&e1->cost, &e2->cost, sizeof (gdouble)); - memcpy (&e1->delay, &e2->delay, sizeof (gdouble)); + memcpy (&e1->delay, &e2->delay, sizeof (gdouble)); + memcpy(&e1->energy, &e2->energy, sizeof(gdouble)); return; } @@ -581,19 +579,18 @@ void duplicate_edge (struct edges_t *e1, struct edges_t *e2) { */ ///////////////////////////////////////////////////////////////////////////////////////// void duplicate_path (struct compRouteOutputItem_t *a, struct compRouteOutputItem_t *b) { - g_assert (a); - g_assert (b); - memcpy (&b->availCap, &a->availCap, sizeof (gdouble)); - b->numRouteElements = a->numRouteElements; + 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->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); - + duplicate_node_id (n1, n2); //zNodeId duplication n1 = &(a->routeElement[k].zNodeId); n2 = &(b->routeElement[k].zNodeId); @@ -619,14 +616,14 @@ void duplicate_path (struct compRouteOutputItem_t *a, struct compRouteOutputItem * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void duplicate_path_t(struct compRouteOutputItem_t* a, struct path_t* b) -{ - g_assert(a); - g_assert(b); +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; @@ -665,23 +662,17 @@ void duplicate_path_t(struct compRouteOutputItem_t* a, struct path_t* b) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint get_map_index_by_nodeId (gchar *nodeId, struct map_nodes_t * mapN) -{ - gint index = -1; - gint i = 0; - - for (i = 0; i < mapN->numMapNodes; i++) - { +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) - { - index = i; - //DEBUG_PC ("Index: %d", index); - return index; + if (memcmp (mapN->map[i].verticeId.nodeId, nodeId, strlen (nodeId)) == 0) { + //DEBUG_PC ("Index: %d", i); + return i; } } //DEBUG_PC ("Index: %d", index); - return index; + return -1; } //////////////////////////////////////////////////////////////////////////////////////// @@ -697,14 +688,11 @@ gint get_map_index_by_nodeId (gchar *nodeId, struct map_nodes_t * mapN) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void get_edge_from_map_by_node (struct edges_t *e, struct nodes_t* v, struct map_nodes_t *mapN) { - +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); - + 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; @@ -725,7 +713,6 @@ void get_edge_from_map_by_node (struct edges_t *e, struct nodes_t* v, struct map ///////////////////////////////////////////////////////////////////////////////////////// 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++) { @@ -755,14 +742,13 @@ void get_edge_from_predecessors (struct edges_t *e, struct nodes_t* n, struct pr */ ///////////////////////////////////////////////////////////////////////////////////////// void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, struct service_t *s) { - //DEBUG_PC ("\n"); // 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); - - struct edges_t* e = create_edge(); - + // 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; @@ -782,14 +768,12 @@ void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, s duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId); p->numRouteElements++; - // Get the destination device Id of the network connectivity service + // 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) - { + while (compare_node_id (&u, dst) != 0) { k++; - p->numRouteElements++; - // v = u + p->numRouteElements++; duplicate_node_id (&u, v); get_edge_from_predecessors (e, v, predecessors); // Get the target u @@ -802,10 +786,7 @@ void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, s 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); - - // copy the contextId - //duplicate_string(p->routeElement[k].contextId, s->service_endpoints_id[0].topology_id.contextId); + duplicate_string(p->routeElement[k].contextId, s->serviceId.contextId); } g_free(e); g_free(v); g_free(pathCons); //DEBUG_PC ("Path is constructed"); @@ -823,22 +804,19 @@ void build_path (struct compRouteOutputItem_t *p, struct pred_t *predecessors, s * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void print_graph (struct graph_t *g) -{ +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); + DEBUG_PC("Graph Num Vertices: %d", g->numVertices); - gint i = 0, j = 0, k = 0; - for (i = 0; i < g->numVertices; i++) - { + for (gint i = 0; i < g->numVertices; i++) { DEBUG_PC ("Head Vertice [%s]", g->vertices[i].verticeId.nodeId); - for (j = 0; j < g->vertices[i].numTargetedVertices; j++) + for (gint j = 0; j < g->vertices[i].numTargetedVertices; j++) { DEBUG_PC (" Tail Vertice: %s", g->vertices[i].targetedVertices[j].tVertice.nodeId); - for (k = 0; k < g->vertices[i].targetedVertices[j].numEdges; k++) + 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, @@ -996,8 +974,7 @@ gint graph_targeted_vertice_add (gint vIndex, gchar *nodeId, struct graph_t *g) * @author Ricardo Martínez * @date 2022 */ -void remove_edge_from_graph (struct graph_t *g, struct edges_t *e) -{ +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; @@ -1013,14 +990,13 @@ void remove_edge_from_graph (struct graph_t *g, struct edges_t *e) 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) { + if (edgeIndex == -1) { DEBUG_PC ("%s --> %s NOT in the Graph!!", e->aNodeId.nodeId, e->zNodeId.nodeId); return; } @@ -1050,11 +1026,9 @@ void remove_edge_from_graph (struct graph_t *g, struct edges_t *e) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct path_set_t * create_path_set () -{ +struct path_set_t * create_path_set () { struct path_set_t * p = g_malloc0 (sizeof (struct path_set_t)); - if (p == NULL) - { + if (p == NULL) { DEBUG_PC ("Memory allocation problem"); exit (-1); } @@ -1072,10 +1046,8 @@ struct path_set_t * create_path_set () * @date 2021 */ ///////////////////////////////////////////////////////////////////////////////////////// -void remove_path_set(struct path_set_t* p) -{ - g_assert(p); - g_free(p); +void remove_path_set(struct path_set_t* p) { + g_assert(p); g_free(p); return; } @@ -1091,15 +1063,14 @@ void remove_path_set(struct path_set_t* p) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void build_map_node (struct map_nodes_t *mapN, struct graph_t *g) -{ +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++) - { + 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); @@ -1111,22 +1082,137 @@ void build_map_node (struct map_nodes_t *mapN, struct graph_t *g) * @file pathComp_tools.c * @brief Allocate memory for path of struct compRouteOutputList_t * * - * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct compRouteOutputList_t * create_route_list () -{ +struct compRouteOutputList_t * create_route_list () { struct compRouteOutputList_t *p = g_malloc0 (sizeof (struct compRouteOutputList_t)); - if (p == NULL) - { + 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 + * @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 + * @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 + * @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 @@ -1137,8 +1223,7 @@ struct compRouteOutputList_t * create_route_list () * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct compRouteOutputItem_t *create_path_item () -{ +struct compRouteOutputItem_t *create_path_item () { struct compRouteOutputItem_t *p = g_malloc0 (sizeof (struct compRouteOutputItem_t)); if (p == NULL) { DEBUG_PC ("Memory Allocation Problem"); @@ -1150,71 +1235,86 @@ struct compRouteOutputItem_t *create_path_item () //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_tools.c - * @brief Sort the set of paths according to the metric (1st criteria) and latency (2nd criteria) + * @brief Sort the set of paths the AvailBw, Cost and Delay * * @params setP + * @params args * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void sort_path_set(struct path_set_t* setP) { +void sort_path_set(struct path_set_t* setP, guint args) { g_assert(setP); - // Sort the paths contained in setP by shotest metric and latency - float epsilon = 0.0000001; + // 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* path2 = &setP->paths[j + 1]; struct compRouteOutputItem_t* pathTmp = create_path_item(); - // 1st Criteria (avail Bw) - if ((path2->availCap - path1->availCap > 0.0) && (fabs(path1->availCap - path2->availCap) > epsilon)) { + //////////////////////// 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; } - else if ((path1->availCap - path2->availCap > 0.0) && (fabs(path1->availCap - path2->availCap) > epsilon)) { - g_free(pathTmp); - continue; - } - // likely the same available bw between path1 and path2 - else if (fabs(path1->availCap - path2->availCap) < epsilon) { - // 2nd criteria: sort path cost - if (path1->cost > path2->cost) { - duplicate_path(path1, pathTmp); - duplicate_path(path2, path1); - duplicate_path(pathTmp, path2); - g_free(pathTmp); - continue; - } - else if (path1->cost < path2->cost) { - g_free(pathTmp); - continue; - } - // 3rd criteria: same path cost, prioritize the one with lowest e2e latency - else if (path1->cost == path2->cost) { - if ((path2->delay - path1->delay > 0.0) && (fabs(path1->delay - path2->delay) > epsilon)) { + 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 if ((path1->delay - path2->delay > 0.0) && (fabs(path1->delay - path2->delay) > epsilon)) { + } + 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; } - // Same bw, same cost and same latency, path1 and path2 are practically the same - else if (fabs(path1->delay - path2->delay) < epsilon) { + 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; @@ -1253,8 +1353,7 @@ void pop_front_path_set (struct path_set_t *setP) { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void add_routeElement_path_back (struct routeElement_t *rE, struct compRouteOutputItem_t *p) -{ +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; @@ -1272,7 +1371,6 @@ void add_routeElement_path_back (struct routeElement_t *rE, struct compRouteOutp 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; } @@ -1336,21 +1434,19 @@ gboolean matching_path_rootPath (struct compRouteOutputItem_t *ap, struct compRo ///////////////////////////////////////////////////////////////////////////////////////// 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++) - { + for (gint j = 0; j < A->numPaths; j++) { struct compRouteOutputItem_t *ap = &A->paths[j]; - struct edges_t *e = create_edge (); + struct edges_t *e = create_edge(); gboolean ret = FALSE; ret = matching_path_rootPath (ap, rootPath, spurNode, e); if (ret == TRUE) { - //DEBUG_PC ("Removal %s [%u]--> %s [%u] from the graph", e->aNodeId.nodeId, e->aLinkId, e->zNodeId.nodeId, e->zLinkId); + 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); + print_graph (g); g_free (e); } - if (ret == FALSE) - { + if (ret == FALSE) { g_free (e); continue; } @@ -1403,54 +1499,45 @@ gint find_nodeId (gconstpointer data, gconstpointer userdata) */ ///////////////////////////////////////////////////////////////////////////////////////// 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) { - g_assert(g); - g_assert(s); - g_assert(mapNodes); + 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 (u ===> v):"); - DEBUG_PC("u: %s ====>", u->node.nodeId); - DEBUG_PC("====> v: %s", v->tVertice.nodeId); + 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 to explore it!", v->tVertice.nodeId); + 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; - gdouble latency_through_u = INFINITY_COST; - gint i = 0; - - // Check bandwidth requirement is fulfillied on edge u --> v - gint foundAvailBw = 0; - gdouble edgeAvailBw = 0.0; + 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)); - DEBUG_PC("edge:u ===> v"); - DEBUG_PC ("%s[%s] ===>", u->node.nodeId, e->aEndPointId); - DEBUG_PC("====> %s[%s]", v->tVertice.nodeId, e->zEndPointId); - DEBUG_PC("edge available bw: %f", edgeAvailBw); - - // if network service constraint specifies "bandwidth" needs (assuming coherent units) - if (path_constraints->bw == TRUE) { - if (edgeAvailBw < path_constraints->bwConstraint) { - continue; - } - else { - foundAvailBw = 1; - break; - } + 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; } } - // if bw path constraint is specified but not sastified ... discard the edge - if ((path_constraints->bw == TRUE) && (foundAvailBw == 0)) - { + // 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; @@ -1461,7 +1548,12 @@ gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struc 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; + 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 @@ -1480,7 +1572,7 @@ gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struc memcpy (&availBw_through_u, &edgeAvailBw, sizeof (gdouble)); } } - // Relax the link according to the pathCost and latency + // 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 @@ -1488,17 +1580,35 @@ gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struc //DEBUG_PC ("dist(src, u) + dist(u, v): %f > dist (src, v): %f --> Discard Link", distance_through_u, v_map->distance); return 0; } - // 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; - } + // 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", availBw_through_u, distance_through_u, latency_through_u); + 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)); @@ -1509,26 +1619,31 @@ gint check_link (struct nodeItem_t *u, gint indexGraphU, gint indexGraphV, struc 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 - *Q = g_list_insert_sorted (*Q, nodeItem, sort_by_distance); - //DEBUG_PC ("%s ADDED to Q (length: %d)", nodeItem->node.nodeId, g_list_length(*Q)); + 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 + // 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); + 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 aTopology: %s", e2->aTopologyId); DEBUG_PC("v-pred zTopology: %s", e2->zTopologyId); // Check whether v is dstPEId - //DEBUG_PC ("Targeted dstPEId: %s", req->dstPEId.nodeId); + //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); @@ -1551,7 +1666,6 @@ gboolean check_computed_path_feasability (struct service_t *s, struct compRouteO 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); @@ -1562,8 +1676,7 @@ gboolean check_computed_path_feasability (struct service_t *s, struct compRouteO return FALSE; } } - // Other constraints... - + // Other constraints... g_free(pathCons); return ret; } @@ -1573,12 +1686,13 @@ gboolean check_computed_path_feasability (struct service_t *s, struct compRouteO * @file pathComp_tools.c * @brief Sorting the GList Q items by distance * + * @param a + * @param b * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -gint sort_by_distance (gconstpointer a, gconstpointer b) -{ +gint sort_by_distance (gconstpointer a, gconstpointer b) { //DEBUG_PC ("sort by distance a and b"); g_assert(a != NULL); g_assert(b != NULL); @@ -1596,13 +1710,55 @@ gint sort_by_distance (gconstpointer a, gconstpointer b) return 1; else if (node1->distance < node2->distance) return 0; - if (node1->distance == node2->distance) - { + 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 + * @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; } //////////////////////////////////////////////////////////////////////////////////////// @@ -1617,8 +1773,7 @@ gint sort_by_distance (gconstpointer a, gconstpointer b) ///////////////////////////////////////////////////////////////////////////////////////// struct graph_t * create_graph () { struct graph_t * g = g_malloc0 (sizeof (struct graph_t)); - if (g == NULL) - { + if (g == NULL) { DEBUG_PC ("Memory Allocation Problem"); exit (-1); } @@ -1637,8 +1792,7 @@ struct graph_t * create_graph () { ///////////////////////////////////////////////////////////////////////////////////////// struct map_nodes_t * create_map_node () { struct map_nodes_t * mN = g_malloc0 (sizeof (struct map_nodes_t)); - if (mN == NULL) - { + if (mN == NULL) { DEBUG_PC ("Memory allocation failed"); exit (-1); } @@ -1656,78 +1810,18 @@ struct map_nodes_t * create_map_node () { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// - struct service_t* get_service_for_computed_path(gchar* serviceUUID) { - for (gint i = 0; i < serviceList->numServiceList; i++) { - struct service_t* s = &(serviceList->services[i]); - if (strcmp(s->serviceId.service_uuid, serviceUUID) == 0) - return s; + 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 Allocate memory for struct deviceList_t - * - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -struct deviceList_t* create_device_list() -{ - struct deviceList_t* dList = g_malloc0(sizeof(struct deviceList_t)); - if (dList == NULL) - { - DEBUG_PC("Memory Allocation Failure"); - exit(-1); - } - return dList; -} - -//////////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_tools.c - * @brief Allocate memory for struct linkList_t - * - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -struct linkList_t* create_link_list() { - struct linkList_t* lList = g_malloc0(sizeof(struct linkList_t)); - if (lList == NULL) - { - DEBUG_PC("Memory Allocation Failure"); - exit(-1); - } - lList->numLinks = 0; - return lList; -} - -//////////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_tools.c - * @brief Allocate memory for struct serviceList_t - * - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -struct serviceList_t* create_service_list() { - struct serviceList_t* sList = g_malloc0(sizeof(struct serviceList_t)); - if (sList == NULL) - { - DEBUG_PC("Memory Allocation Failure"); - exit(-1); - } - return sList; -} - //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_tools.c @@ -1770,8 +1864,7 @@ void print_service_type(guint type) { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void print_link_port_direction(guint direction) -{ +void print_link_port_direction(guint direction) { switch (direction) { case LINK_PORT_DIRECTION_BIDIRECTIONAL: //DEBUG_PC("Bidirectional Port Direction"); @@ -1800,8 +1893,7 @@ void print_link_port_direction(guint direction) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void print_termination_direction(guint direction) -{ +void print_termination_direction(guint direction) { switch (direction) { case TERMINATION_DIRECTION_BIDIRECTIONAL: //DEBUG_PC("Bidirectional Termination Direction"); @@ -1926,26 +2018,6 @@ void print_link_forwarding_direction(guint linkFwDir) { return; } -//////////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_tools.c - * @brief Allocate memory for the contextSet - * - * @param - * - * @author Ricardo Martínez - * @date 2022 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -struct contextSet_t* create_contextSet() { - struct contextSet_t* c = g_malloc0(sizeof(struct contextSet_t)); - if (c == NULL) { - DEBUG_PC("Memory Allocation Failure"); - exit(-1); - } - return c; -} - //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_tools.c @@ -1958,18 +2030,19 @@ struct contextSet_t* create_contextSet() { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct context_t* find_contextId_in_set(gchar* contextUuid, struct contextSet_t* set) { - - g_assert(set); - //DEBUG_PC("Checking if contextId: %s in in the ContextList??", contextUuid); - - for (gint i = 0; i < set->num_context_set; i++) { - struct context_t* c = &(set->contextList[i]); +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; @@ -1987,11 +2060,19 @@ struct context_t* find_contextId_in_set(gchar* contextUuid, struct contextSet_t* * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct context_t* add_contextId_in_set(gchar *contextUuid, struct contextSet_t *set) { +struct context_t* add_contextId_in_set(gchar *contextUuid, GList** set) { - set->num_context_set++; - struct context_t* c = &(set->contextList[set->num_context_set - 1]); + 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; } @@ -2008,9 +2089,7 @@ struct context_t* add_contextId_in_set(gchar *contextUuid, struct contextSet_t * */ ///////////////////////////////////////////////////////////////////////////////////////// struct vertices_t* find_vertex_in_graph_context(struct graph_t *g, gchar* deviceId) { - - for (gint i = 0; i < g->numVertices; i++) - { + for (gint i = 0; i < g->numVertices; i++) { struct vertices_t* v = &(g->vertices[i]); if (strcmp(v->verticeId.nodeId, deviceId) == 0) { return v; @@ -2031,10 +2110,11 @@ struct vertices_t* find_vertex_in_graph_context(struct graph_t *g, gchar* device * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct vertices_t* add_vertex_in_graph(struct graph_t* g, gchar* deviceId) { +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, deviceId); + duplicate_string(v->verticeId.nodeId, d->deviceId); + memcpy(&v->power_idle, &d->power_idle, sizeof(gdouble)); return v; } @@ -2044,17 +2124,24 @@ struct vertices_t* add_vertex_in_graph(struct graph_t* g, gchar* deviceId) { * @brief Construct the graphs (vertices and edges) bound to every individual context * * @param cSet + * @param activeFlag * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void build_contextSet_deviceList(struct contextSet_t* cSet) { - // Check every device their endpoints - for (gint i = 0; i < deviceList->numDevices; i++) { - struct device_t* d = &(deviceList->devices[i]); +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]); @@ -2062,18 +2149,17 @@ void build_contextSet_deviceList(struct contextSet_t* cSet) { 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); + 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->deviceId); + v = add_vertex_in_graph(&c->g, d); } } } @@ -2136,8 +2222,10 @@ struct targetNodes_t* add_targeted_vertex_in_graph_context(struct vertices_t* v, ///////////////////////////////////////////////////////////////////////////////////////// struct endPoint_t* find_device_tied_endpoint(gchar* devId, gchar* endPointUuid) { //DEBUG_PC("devId: %s ePId: %s", devId, endPointUuid); - for (gint i = 0; i < deviceList->numDevices; i++) { - struct device_t* d = &(deviceList->devices[i]); + 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; } @@ -2160,51 +2248,65 @@ struct endPoint_t* find_device_tied_endpoint(gchar* devId, gchar* endPointUuid) * * @param w * @param l + * @param activeFlag * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void add_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l) { +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); - - // copy the deviceId and endpointsIds (A --> Z) - struct link_endpointId_t* aEndpointId = &(l->linkEndPointId[0]); duplicate_string(e->aNodeId.nodeId, aEndpointId->deviceId); duplicate_string(e->aEndPointId, aEndpointId->endPointId); - duplicate_string(e->aTopologyId, aEndpointId->topology_id.topology_uuid); - - struct link_endpointId_t* zEndpointId = &(l->linkEndPointId[1]); + 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); - - // The potential and available capacity is indeed retrieved using aEndpointId in the deviceList - 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); - } + //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 + // 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; } @@ -2220,8 +2322,7 @@ void add_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l) * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -struct edges_t* find_edge_in_targetedVertice_set(struct targetNodes_t* w, struct link_t* l) { - +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) { @@ -2238,32 +2339,37 @@ struct edges_t* find_edge_in_targetedVertice_set(struct targetNodes_t* w, struct * contents/info of the link list * * @param set + * @param activeFlag * * @author Ricardo Martínez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void build_contextSet_linklList(struct contextSet_t* set) { - g_assert(set); - +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++; - for (gint j = 0; j < linkList->numLinks; j++) { - struct link_t* l = &(linkList->links[j]); - // link assumed to be P2P A --> B; I.e. 2 endPoints; 1st specifies A and 2nd specifie B + // 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 Context: %s", l->linkId, contextUuid); + 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); @@ -2277,28 +2383,29 @@ void build_contextSet_linklList(struct contextSet_t* set) { 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("aDeviceId: %s IS NOT IN Vertices of contextId: %s", aDeviceId, contextUuid); + 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("B device [%s] is PEER of A device [%s]", bDeviceId, v->verticeId.nodeId); + 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); + 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); + add_edge_in_targetedVertice_set(w, l, activeFlag); } else { DEBUG_PC("The link already exists ..."); @@ -2320,21 +2427,47 @@ void build_contextSet_linklList(struct contextSet_t* set) { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void build_contextSet(struct contextSet_t* cSet) { - g_assert(cSet); - g_assert(deviceList); - g_assert(linkList); +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); + 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); + 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 + * @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 @@ -2346,11 +2479,14 @@ void build_contextSet(struct contextSet_t* cSet) { * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// -void print_contextSet(struct contextSet_t* set) { - g_assert(set); +void print_contextSet(GList* set) { + + DEBUG_PC("Printing the ContextSet w/ number of Elements: %d", g_list_length(set)); - for (gint i = 0; i < set->num_context_set; i++) { - struct context_t* c = &(set->contextList[i]); + 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("-------------------------------------------------------------"); @@ -2426,8 +2562,7 @@ gint same_src_dst_pe_nodeid(struct service_t* s) ///////////////////////////////////////////////////////////////////////////////////////// void comp_route_connection_issue_handler (struct compRouteOutput_t *path, struct service_t *s) { - g_assert(path); - g_assert(s); + g_assert(path); g_assert(s); // Increase the number of computed routes/paths despite there was an issue to be reported path->numPaths++; @@ -2476,8 +2611,7 @@ void destroy_compRouteOutputList (struct compRouteOutputList_t *ro) */ ///////////////////////////////////////////////////////////////////////////////////////// void duplicate_graph (struct graph_t *originalGraph, struct graph_t *destGraph) { - g_assert (originalGraph); - g_assert (destGraph); + g_assert (originalGraph); g_assert (destGraph); destGraph->numVertices = originalGraph->numVertices; for (gint i = 0; i < originalGraph->numVertices; i++) { @@ -2485,6 +2619,7 @@ void duplicate_graph (struct graph_t *originalGraph, struct graph_t *destGraph) 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]); @@ -2600,9 +2735,7 @@ struct edges_t* get_reverse_edge_from_the_graph(struct edges_t* e, struct graph_ ///////////////////////////////////////////////////////////////////////////////////////// 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); + 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); @@ -2621,8 +2754,7 @@ void allocate_graph_resources (struct path_t *p, struct service_t *s, struct gra memcpy(&e->availCap, &resBw, sizeof(gdouble)); DEBUG_PC("Final e/link avail Bw: %f", e->availCap); } - g_free(pathCons); - + g_free(pathCons); return; } @@ -2637,14 +2769,12 @@ void allocate_graph_resources (struct path_t *p, struct service_t *s, struct gra * @parma g * * @author Ricardo Martínez - * @date 2021 + * @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); + 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++) { @@ -2678,20 +2808,20 @@ void allocate_graph_reverse_resources(struct path_t* p, struct service_t * s, st * @param routeList * * @author Ricardo Martínez - * @date 2021 + * @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 Item: %d ===================", 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, + 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, + 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) { @@ -2717,7 +2847,7 @@ void print_path_connection_list(struct compRouteOutputList_t* routeList) { * @param d * * @author Ricardo Martínez - * @date 2021 + * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct timeval d, gint numSuccesPathComp, gint numPathCompIntents) { @@ -2733,8 +2863,11 @@ void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct DEBUG_PC("Succesfully Comp: %d | Path Comp Requests: %d", numSuccesPathComp, numPathCompIntents); DEBUG_PC("AV. PATH COMP ALG. TIME: %f ms", av_alg_comp_time); - for (gint i = 0; i < serviceList->numServiceList; i++) { - struct service_t* s = &(serviceList->services[i]); + 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]); @@ -2743,6 +2876,7 @@ void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct } } } + for (gint k = 0; k < routeConnList->numCompRouteConnList; k++) { struct compRouteOutput_t* rO = &(routeConnList->compRouteConnection[k]); if (rO->noPathIssue == NO_PATH_CONS_ISSUE) { @@ -2768,5 +2902,500 @@ void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct 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 + * @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 + * @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 + * @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 + * @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 + * @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 + * @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 + * @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 + * @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 + * @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 + * @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 8fe704c39..041d42019 100644 --- a/src/pathcomp/backend/pathComp_tools.h +++ b/src/pathcomp/backend/pathComp_tools.h @@ -27,12 +27,17 @@ #include // External variables -extern struct map_nodes_t* mapNodes; -extern struct graph_t* graph; -extern struct contextSet_t* contextSet; -extern struct linkList_t* linkList; -extern struct deviceList_t* deviceList; -extern struct serviceList_t* serviceList; +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 @@ -58,8 +63,9 @@ struct nodes_t { struct nodeItem_t { struct nodes_t node; - gdouble distance; - gdouble latency; + gdouble distance; // traversed distance + gdouble latency; // incured latency + gdouble power; //consumed power }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -84,7 +90,8 @@ struct edges_t { gdouble totalCap, availCap; gdouble cost; - gdouble delay; + gdouble delay; + gdouble energy; // inter-domain local and remote Ids gchar interDomain_localId[MAX_INTER_DOMAIN_PLUG_IN_SIZE]; @@ -111,7 +118,8 @@ struct map_t { struct edges_t predecessor; gdouble distance; gdouble avaiBandwidth; - gdouble latency; + gdouble latency; + gdouble power; }; #define MAX_MAP_NODE_SIZE 100 @@ -135,6 +143,7 @@ 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 { @@ -151,15 +160,6 @@ struct context_t { struct graph_t g; }; -//////////////////////////////////////////////////// -// Structure for the Set of Contexts -/////////////////////////////////////////////////// -#define MAX_NUMBER_CONTEXT 5 // 100 # LGR: reduced from 100 to 5 to divide by 20 the memory used -struct contextSet_t { - struct context_t contextList[MAX_NUMBER_CONTEXT]; - gint num_context_set; -}; - #define MAX_ALG_ID_LENGTH 10 //////////////////////////////////////////////////// // External Variables @@ -245,6 +245,8 @@ struct endPoint_t { 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 }; /////////////////////////////////////////////////////////////////// @@ -253,25 +255,15 @@ struct endPoint_t { #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 device List -/////////////////////////////////////////////////////////////////// -#define MAX_NUM_DEVICE 200 -struct deviceList_t { - // device information - gint numDevices; - struct device_t devices[MAX_NUM_DEVICE]; -}; - /////////////////////////////////////////////////////////////////// // Structure for the link EndPoint Id /////////////////////////////////////////////////////////////////// @@ -298,6 +290,13 @@ 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 /////////////////////////////////////////////////////////////////// @@ -308,10 +307,10 @@ struct latency_characteristics_t { #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; @@ -319,15 +318,6 @@ struct link_t { struct latency_characteristics_t latency_characteristics; }; -/////////////////////////////////////////////////////////////////// -// Structure for the link List -/////////////////////////////////////////////////////////////////// -#define MAX_NUM_LIST 2000 -struct linkList_t { - gint numLinks; - struct link_t links[MAX_NUM_LIST]; -}; - //////////////////////////////////////////////////// // Structure for service Identifier /////////////////////////////////////////////////// @@ -369,12 +359,10 @@ struct constraint_t { 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 @@ -407,10 +395,27 @@ struct path_constraints_t { //////////////////////////////////////////////////// // Structure for the handling the service requests /////////////////////////////////////////////////// -#define MAX_SERVICE_LIST 100 -struct serviceList_t { - struct service_t services[MAX_SERVICE_LIST]; - gint numServiceList; +//#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; }; //////////////////////////////////////////////////////////////////////////////////////////// @@ -429,7 +434,6 @@ struct pathLink_t { 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; }; @@ -458,13 +462,13 @@ struct routeElement_t { gchar contextId[UUID_CHAR_LENGTH]; }; -struct compRouteOutputItem_t { - // Potential(total) and available capacity +struct compRouteOutputItem_t { gint unit; gdouble totalCap, availCap; gdouble cost; gdouble delay; + gdouble power; struct routeElement_t routeElement[MAX_ROUTE_ELEMENTS]; gint numRouteElements; @@ -481,6 +485,7 @@ 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; @@ -488,18 +493,14 @@ struct path_t { #define NO_PATH_CONS_ISSUE 1 // No path due to a constraint issue #define MAX_NUM_COMPUTED_PATHS 10 -struct compRouteOutput_t -{ +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; - + gint numPaths; // if the transport connectivity service cannot be computed, this value is set to 0 determining the constraints were not fulfilled gint noPathIssue; }; @@ -508,8 +509,7 @@ struct compRouteOutput_t // Structure to handle the response list with all the computed network connectivity services //////////////////////////////////////////////////////////////////////////////////////////// #define MAX_COMP_CONN_LIST 100 -struct compRouteOutputList_t -{ +struct compRouteOutputList_t { struct compRouteOutput_t compRouteConnection[MAX_COMP_CONN_LIST]; gint numCompRouteConnList; @@ -530,6 +530,7 @@ struct compRouteOutputList_t // 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 *); @@ -537,7 +538,7 @@ 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(struct contextSet_t *, gchar *); +struct graph_t* get_graph_by_contextId(GList*, gchar *); struct pred_t * create_predecessors (); struct edges_t* create_edge(); @@ -565,31 +566,29 @@ 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 *); +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 *); +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 *); -struct deviceList_t* create_device_list(); -struct linkList_t* create_link_list(); -struct serviceList_t* create_service_list(); - void print_service_type(guint); void print_link_port_direction(guint); void print_termination_direction(guint); @@ -597,9 +596,9 @@ void print_termination_state(guint); void print_capacity_unit(guint); void print_link_forwarding_direction(guint); -struct contextSet_t* create_contextSet(); -void build_contextSet(struct contextSet_t *); -void print_contextSet(struct contextSet_t *); +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 *); @@ -614,4 +613,12 @@ 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 -- GitLab From 29038f103a28d4633ac3243da4ecb4b5e5a33bc0 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Sat, 25 Mar 2023 10:31:56 +0000 Subject: [PATCH 2/2] PathComp component - Backend: - Updated file headers in EAR algorithm --- src/pathcomp/backend/pathComp_ear.c | 15 ++++++--------- src/pathcomp/backend/pathComp_ear.h | 7 ++----- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/pathcomp/backend/pathComp_ear.c b/src/pathcomp/backend/pathComp_ear.c index c13993b64..aee3d09f7 100644 --- a/src/pathcomp/backend/pathComp_ear.c +++ b/src/pathcomp/backend/pathComp_ear.c @@ -1,6 +1,5 @@ -//////////////////////////////////////////////////////////////////////////////////////// -/** - * # Copyright 2022 Centre Tecnològic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es +/* + * 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. @@ -13,10 +12,8 @@ * 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 #include #include @@ -50,7 +47,7 @@ GList* contextSet; * * @param outputList * - * @author Ricardo Martínez + * @author Ricardo Mart�nez * @date 2022 */ void ear_comp_services(struct compRouteOutputList_t* oPathList, gint activeFlag) { @@ -110,7 +107,7 @@ void ear_comp_services(struct compRouteOutputList_t* oPathList, gint activeFlag) * * @param oList * - * @author Ricardo Martínez + * @author Ricardo Mart�nez * @date 2022 */ //////////////////////////////////////////////////////////////////////////////////////// @@ -168,7 +165,7 @@ void ear_comp(struct compRouteOutputList_t* oList) { * * @param compRouteOutput * - * @author Ricardo Martínez + * @author Ricardo Mart�nez * @date 2022 */ ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/pathcomp/backend/pathComp_ear.h b/src/pathcomp/backend/pathComp_ear.h index 70210d869..dff620256 100644 --- a/src/pathcomp/backend/pathComp_ear.h +++ b/src/pathcomp/backend/pathComp_ear.h @@ -1,6 +1,5 @@ -//////////////////////////////////////////////////////////////////////////////////////// -/** - * # Copyright 2022 Centre Tecnològic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es +/* + * 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. @@ -13,8 +12,6 @@ * 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_EAR_H -- GitLab