diff --git a/manifests/pathcompservice.yaml b/manifests/pathcompservice.yaml index 138191e2a619a3b7c67d2fbdcbebaa284e00fbc8..679552e2fbaf14ceb7e1a190f11adb6877efa386 100644 --- a/manifests/pathcompservice.yaml +++ b/manifests/pathcompservice.yaml @@ -51,27 +51,18 @@ spec: - name: backend image: registry.gitlab.com/teraflow-h2020/controller/pathcomp-backend:latest imagePullPolicy: Always - # not working; to be investigated - #readinessProbe: - # exec: - # command: - # - curl -X POST -0 - # - -H 'Expect:' - # - -H 'Content-Type:\ application/json' - # - -d '{}' - # - http://127.0.0.1:8081/pathComp/api/v1/compRoute - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - #livenessProbe: - # exec: - # command: - # - curl -X POST -0 - # - -H 'Expect:' - # - -H 'Content-Type:\ application/json' - # - -d '{}' - # - http://127.0.0.1:8081/pathComp/api/v1/compRoute - # initialDelaySeconds: 5 - # timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 5 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 5 + timeoutSeconds: 5 resources: requests: cpu: 250m diff --git a/src/pathcomp/.gitignore b/src/pathcomp/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..48a680bf0f45eb556108c349bc45be896f4219aa --- /dev/null +++ b/src/pathcomp/.gitignore @@ -0,0 +1 @@ +backend/wireshark diff --git a/src/pathcomp/.gitlab-ci.yml b/src/pathcomp/.gitlab-ci.yml index d8ab40fda138723a3e7771005125b0dccce71b1f..a45e735e4c07299c4853abdff5b6c39963a87a78 100644 --- a/src/pathcomp/.gitlab-ci.yml +++ b/src/pathcomp/.gitlab-ci.yml @@ -13,7 +13,7 @@ # limitations under the License. # Build, tag, and push the Docker image to the GitLab Docker registry -build pathcomp-backend: +build pathcomp: variables: IMAGE_NAME: 'pathcomp' # name of the microservice IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) @@ -24,8 +24,11 @@ build pathcomp-backend: # This first build tags the builder resulting image to prevent being removed by dangling image removal command - docker build -t "${IMAGE_NAME}-backend:${IMAGE_TAG}-builder" --target builder -f ./src/$IMAGE_NAME/backend/Dockerfile . - docker build -t "${IMAGE_NAME}-backend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/backend/Dockerfile . + - docker build -t "${IMAGE_NAME}-frontend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/frontend/Dockerfile . - docker tag "${IMAGE_NAME}-backend:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-backend:$IMAGE_TAG" + - docker tag "${IMAGE_NAME}-frontend:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-frontend:$IMAGE_TAG" - docker push "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-backend:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-frontend:$IMAGE_TAG" after_script: - docker images --filter="dangling=true" --quiet | xargs -r docker rmi rules: @@ -38,30 +41,6 @@ build pathcomp-backend: - src/$IMAGE_NAME/backend/**/*.{c,h,conf} - src/$IMAGE_NAME/backend/Makefile - src/$IMAGE_NAME/backend/Dockerfile - - manifests/${IMAGE_NAME}service.yaml - - .gitlab-ci.yml - -# Build, tag, and push the Docker image to the GitLab Docker registry -build pathcomp-frontend: - variables: - IMAGE_NAME: 'pathcomp' # name of the microservice - IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) - stage: build - before_script: - - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - script: - - docker build -t "${IMAGE_NAME}-frontend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/frontend/Dockerfile . - - docker tag "${IMAGE_NAME}-frontend:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-frontend:$IMAGE_TAG" - - docker push "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-frontend:$IMAGE_TAG" - after_script: - - docker images --filter="dangling=true" --quiet | xargs -r docker rmi - rules: - - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' - - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' - - changes: - - src/common/**/*.py - - proto/*.proto - - src/$IMAGE_NAME/.gitlab-ci.yml - src/$IMAGE_NAME/frontend/**/*.{py,in,yml} - src/$IMAGE_NAME/frontend/Dockerfile - src/$IMAGE_NAME/frontend/tests/*.py @@ -75,7 +54,7 @@ unit test pathcomp-backend: IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: unit_test needs: - - build pathcomp-backend + - build pathcomp before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi @@ -120,8 +99,7 @@ unit test pathcomp-frontend: IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: unit_test needs: - - build pathcomp-frontend - - build pathcomp-backend + - build pathcomp before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge --subnet=172.28.0.0/24 --gateway=172.28.0.254 teraflowbridge; fi diff --git a/src/pathcomp/backend/Dockerfile b/src/pathcomp/backend/Dockerfile index c7c8d796512ec4bb5ff59d3d48ae62d86df761af..128085f902df61acad7493ae6c085031a7aac568 100644 --- a/src/pathcomp/backend/Dockerfile +++ b/src/pathcomp/backend/Dockerfile @@ -71,4 +71,4 @@ COPY --from=builder /var/teraflow/config/pathcomp.conf ./config COPY --from=builder /var/teraflow/tests/. ./tests # release entrypoint: -ENTRYPOINT [ "./pathComp", "config/pathcomp.conf", "pathcomp.log" ] +ENTRYPOINT [ "./pathComp", "config/pathcomp.conf", "screen_only" ] diff --git a/src/pathcomp/backend/Dockerfile-gdb b/src/pathcomp/backend/Dockerfile-gdb index 13af33006504095204878b465bdee7f84f549d20..dcf2dbd2fefb22618677b746d1a6cc82a5412e13 100644 --- a/src/pathcomp/backend/Dockerfile-gdb +++ b/src/pathcomp/backend/Dockerfile-gdb @@ -34,4 +34,4 @@ RUN make EXPOSE 8081 -ENTRYPOINT [ "gdb", "--args", "./pathComp", "config/pathcomp.conf", "pathcomp.log" ] +ENTRYPOINT [ "gdb", "--args", "./pathComp", "config/pathcomp.conf", "screen_only" ] diff --git a/src/pathcomp/backend/Makefile b/src/pathcomp/backend/Makefile index 2777468b2ee54d764aa410a5c41f9e443ade2f06..f4fc1996bb32e87515bb6a1145213cd4e74a4f3b 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_RESTapi.o - gcc -o pathComp pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_RESTapi.o \ +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 \ -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_RESTapi.o - gcc -o pathComp-dbg pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_RESTapi.o \ +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 \ -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_RESTapi.o - gcc -o pathComp-cvr pathComp.o pathComp_log.o pathComp_cjson.o pathComp_tools.o pathComp_ksp.o pathComp_RESTapi.o \ +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 \ -L/usr/lib/x86_64-linux-gnu/ -lglib-2.0 -luuid $(LDFLAGS) $(LDLIBS) pathComp_log.o: pathComp_log.h pathComp_log.c @@ -56,8 +56,11 @@ pathComp_tools.o: pathComp_log.h pathComp_tools.h pathComp_tools.c pathComp_ksp.o: pathComp_log.h pathComp_tools.h pathComp_ksp.h pathComp_ksp.c $(CC) $(CFLAGS) -c pathComp_ksp.c -o pathComp_ksp.o + +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_RESTapi.o: pathComp_tools.h pathComp_log.h pathComp_cjson.h pathComp_ksp.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_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 330f0f61a6d1ea9ff0d4327ede6541b4faca1528..2a719c92481557424925b09e940dcf73ba09595c 100644 --- a/src/pathcomp/backend/pathComp.c +++ b/src/pathcomp/backend/pathComp.c @@ -132,16 +132,22 @@ int main(int argc, char *argv[]) // argv[1] specifies the folder and the configuration file gchar configFile[50]; strcpy (configFile, argv[1]); - DEBUG_PC ("Path Computation Server Config File is: %s", configFile); + DEBUG_PC ("Path Computation Server Config File is: %s", configFile); // argv[2] specifies the folder and the log file gchar log[50]; strcpy (log, argv[2]); - DEBUG_PC ("PATH COMP log File: %s", log); - - // open the log file - logfile = fopen (log, "w"); - DEBUG_PC ("log file is opened"); + gint screen = strcmp(log, "screen_only"); + if (screen == 0) { + DEBUG_PC("All logs shown through stdout, i.e.,screen"); + logfile = NULL; + } + else { + DEBUG_PC("PATH COMP log File: %s", log); + // open the log file + logfile = fopen(log, "w"); + DEBUG_PC("log file is opened"); + } // Read the pathComp.conf file FILE *pathComp_config = NULL; diff --git a/src/pathcomp/backend/pathComp_RESTapi.c b/src/pathcomp/backend/pathComp_RESTapi.c index dd352c613d26124a97c2bdd79070634572a3c976..709d3dc004027e7eb4e847f73ae1bae25653316e 100644 --- a/src/pathcomp/backend/pathComp_RESTapi.c +++ b/src/pathcomp/backend/pathComp_RESTapi.c @@ -38,6 +38,7 @@ #include "pathComp_tools.h" #include "pathComp_cjson.h" #include "pathComp_ksp.h" +#include "pathComp_sp.h" #include "pathComp_RESTapi.h" #define ISspace(x) isspace((int)(x)) @@ -457,18 +458,30 @@ void rapi_response_json_contents (char *body, gint *length, struct compRouteOutp ///////////////////////////////////////////////////////////////////////////////////////// void rapi_response_ok (GIOChannel *source, gint httpCode, struct compRouteOutputList_t *compRouteOutputList) { - g_assert(compRouteOutputList); gint ret = 0; //DEBUG_PC ("Creating the JSON Body and sending the response of the computed Route List"); - guchar buftmp[1024]; - char * buf = g_malloc0 (sizeof (char) * 2048000); + char buftmp[1024]; + char *buf = g_malloc0 (sizeof (char) * 2048000); // Create the Body of the Response - char * jsonBody = g_malloc0 (sizeof (char) * 2048000); + char * msgBody = g_malloc0 (sizeof (char) * 2048000); gint length = 0; - - rapi_response_json_contents (jsonBody, &length, compRouteOutputList); + + // If path computation was requested, the resulting computation is returned in the msg body + if (compRouteOutputList != NULL) { + rapi_response_json_contents(msgBody, &length, compRouteOutputList); + } + // no path computation was requested, then a basic msg is just added + else { + cJSON* root = cJSON_CreateObject(); + char status[3]; + sprintf(status, "OK"); + cJSON_AddItemToObject(root, "Status", cJSON_CreateString(status)); + msgBody = (char*)cJSON_Print(root); + length = strlen((const char*)msgBody); + cJSON_Delete(root); + } sprintf((char *)buf, "HTTP/1.1 200 OK\r\n"); @@ -479,10 +492,8 @@ void rapi_response_ok (GIOChannel *source, gint httpCode, struct compRouteOutput strcat ((char *)buf, (const char *)buftmp); // Add the length of the JSON enconding to the Content_Length - char buff_length[16]; - + char buff_length[16]; sprintf(buff_length, "%d", length); - //DEBUG_PC ("Buffer Length (JSON BODY): %d Added to the Content Length", length); sprintf ((char *)buftmp, "Content-Length: "); strcat ((char *)buftmp, (const char *)buff_length); @@ -494,13 +505,14 @@ void rapi_response_ok (GIOChannel *source, gint httpCode, struct compRouteOutput strcat ((char *)buf, (const char *)buftmp); sprintf((char *)buftmp, "\r\n"); strcat ((char *)buf, (const char *)buftmp); - - strcat ((char *)buf, (const char *)jsonBody); + + strcat((char*)buf, (const char*)msgBody); + //DEBUG_PC ("%s", buf); ret = rapi_send_message (source, buf); g_free (buf); memset (buftmp, '\0', sizeof ( buftmp)); - g_free (jsonBody); + g_free (msgBody); (void)ret; return; } @@ -896,7 +908,8 @@ 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]); @@ -906,7 +919,7 @@ void parsing_json_deviceList_array(cJSON* deviceArray) { cJSON* deviceUuidObj = cJSON_GetObjectItem(item, "device_Id"); if (cJSON_IsString(deviceUuidObj)) { duplicate_string(d->deviceId, deviceUuidObj->valuestring); - //DEBUG_PC("Device (%d) -- Id: %s (uuid string format)", i + 1, d->deviceId); + DEBUG_PC("Device (%d) -- Id: %s (uuid string format)", i + 1, d->deviceId); } // Get the device Type @@ -915,12 +928,11 @@ void parsing_json_deviceList_array(cJSON* deviceArray) { duplicate_string(d->deviceType, deviceTypeObj->valuestring); //DEBUG_PC(" Device Type: %s ---", d->deviceType); } - //DEBUG_PC("DeviceId: %s, Device Type: %s", d->deviceId, d->deviceType); + DEBUG_PC("DeviceId: %s, Device Type: %s", d->deviceId, d->deviceType); // get the device endPoints cJSON* deviceEndpointsArray = cJSON_GetObjectItem(item, "device_endpoints"); - if (cJSON_IsArray(deviceEndpointsArray)) - { + if (cJSON_IsArray(deviceEndpointsArray)) { parse_json_device_endpoints_array(deviceEndpointsArray, d); } } @@ -942,6 +954,7 @@ 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++; struct link_endpointId_t* endPointLink = &(l->linkEndPointId[i]); @@ -970,7 +983,7 @@ void parse_json_link_endpoints_array(cJSON *endPointsLinkObj, struct link_t* l) cJSON* deviceIdObj = cJSON_GetObjectItem(endPointIdObj, "device_id"); if (cJSON_IsString(deviceIdObj)) { duplicate_string(endPointLink->deviceId, deviceIdObj->valuestring); - //DEBUG_PC("Link Endpoint (%d) -- Device Id: %s (uuid)", i + 1, endPointLink->deviceId); + DEBUG_PC(" Link Endpoint[%d] -- DeviceId: %s", i + 1, endPointLink->deviceId); } // Get the endpoint_uuid cJSON* endPointUuidObj = cJSON_GetObjectItem(endPointIdObj, "endpoint_uuid"); @@ -980,6 +993,7 @@ void parse_json_link_endpoints_array(cJSON *endPointsLinkObj, struct link_t* l) } } } + //DEBUG_PC("link id: %s has %d endpoints", l->linkId, l->numLinkEndPointIds); return; } @@ -996,21 +1010,24 @@ 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; cJSON* item = cJSON_GetArrayItem(linkListArray, i); - // Get the link Id (uuid) cJSON* linkIdObj = cJSON_GetObjectItem(item, "link_Id"); - if (cJSON_IsString(linkIdObj)) { + if (cJSON_IsString(linkIdObj)) { duplicate_string(l->linkId, linkIdObj->valuestring); - //DEBUG_PC("Link (%d) -- Id: %s (uuid)", i + 1, l->linkId); + 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)) { + //DEBUG_PC("number linkEndPointIds: %d", l->numLinkEndPointIds); parse_json_link_endpoints_array(endPointsLinkObj, l); } // get the fowarding direction @@ -1084,8 +1101,8 @@ void parsing_json_linkList_array(cJSON* linkListArray) { */ //////////////////////////////////////////////////////////////////////////////////////// void generate_reverse_linkList() { - - DEBUG_PC("Starting the Creation of the Reverse Links [current: %d]", linkList->numLinks); + DEBUG_PC(""); + DEBUG_PC("CREATION OF REVERSE LINKS"); gint numLinks = linkList->numLinks; for (gint i = 0; i < numLinks; i++) { @@ -1100,16 +1117,17 @@ void generate_reverse_linkList() { // Assumption: p2p links. The newLink endpoints are the reversed ones form the reference Link (refLink) // i.e., refLink A->B, then newLink B->A -#if 0 + //DEBUG_PC("ref: %s has %d endpoints", refLink->linkId, refLink->numLinkEndPointIds); +#if 1 if (refLink->numLinkEndPointIds != 2) { - DEBUG_PC("To construct the new Link from ref, 2 EndPoints are a MUST"); + DEBUG_PC("To construct the new Link from ref: %s, 2 EndPoints are a MUST", refLink->linkId); exit(-1); } #endif + 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++) { - - + for (gint j = refLink->numLinkEndPointIds - 1, m = 0; j >= 0; j--, m++) { struct link_endpointId_t* refEndPId = &(refLink->linkEndPointId[j]); struct link_endpointId_t* newEndPId = &(newLink->linkEndPointId[m]); // Duplicate the topologyId information, i.e., contextId and topology_uuid @@ -1118,7 +1136,7 @@ void generate_reverse_linkList() { //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); + 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++; } @@ -1560,12 +1578,17 @@ gint triggering_routeComp (struct compRouteOutputList_t *compRouteList, gchar *a gint httpCode = HTTP_RETURN_CODE_OK; DEBUG_PC("Requested Algorithm: %s", algId); //////////////////// Algorithm Selector (RAId)////////////////////////////////////// - // Connectivity Service Abstraction (CSA) + // KSP algorithm if (strncmp ((const char*)algId, "KSP", 3) == 0) { DEBUG_PC ("Alg Id: KSP"); httpCode = pathComp_ksp_alg(compRouteList); } + // simple SP algorithm + else if (strncmp((const char*)algId, "SP", 2) == 0) { + DEBUG_PC("Alg Id: SP"); + httpCode = pathComp_sp_alg(compRouteList); + } #if 0 // Infrastructure Abstraction (InA) else if (strncmp ((const char*)raId, "InA", 3) == 0) @@ -1643,8 +1666,7 @@ 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) - { + if (RestApiMethod == 0) { DEBUG_PC ("The method is NOT supported ..."); RESTapi_unimplemented (source); RESTapi_stop(client, source, fd); @@ -1656,12 +1678,28 @@ gboolean RESTapi_activity(GIOChannel *source, GIOCondition cond, gpointer data) 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); + } + 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 (strncmp((const char*) url, "/pathComp/api/v1/compRoute", 26) != 0) - { - DEBUG_PC ("Unknown url: %s", url); - RESTapi_stop(client, source, fd); - exit (-1); + 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); + } } // get the version diff --git a/src/pathcomp/backend/pathComp_ksp.c b/src/pathcomp/backend/pathComp_ksp.c index 25e9d0b6041fdfab2373213408f62c12da31eb12..85c5e750506d56fb7c5511f6c675598adea49ee8 100644 --- a/src/pathcomp/backend/pathComp_ksp.c +++ b/src/pathcomp/backend/pathComp_ksp.c @@ -39,82 +39,9 @@ #include "pathComp_ksp.h" // Global Variables -struct map_nodes_t *mapNodes = NULL; -struct graph_t *graph = NULL; -struct contextSet_t* contextSet = NULL; -//struct linkList_t* linkList; -//struct deviceList_t* deviceList; -//struct serviceList_t* serviceList; - -gint numPathCompIntents = 0; // number of events triggering the path computation -gint numSuccesPathComp = 0; // number of events resulting in succesfully path computations fulfilling the constraints -struct timeval total_path_comp_time; -gdouble totalReqBw = 0.0; -gdouble totalServedBw = 0.0; - -/////////////////////////////////////////////////////////////////////////////////// -/** - * @file pathComp_ksp.c - * @brief update statistics of the KSP path computation - * - * @param routeConnList - * @param d - * - * @author Ricardo MartÃnez <ricardo.martinez@cttc.es> - * @date 2021 - */ - ///////////////////////////////////////////////////////////////////////////////////////// -void update_stats_ksp_path_comp(struct compRouteOutputList_t* routeConnList, struct timeval d) -{ - g_assert(routeConnList); - g_assert(serviceList); - - total_path_comp_time.tv_sec = total_path_comp_time.tv_sec + d.tv_sec; - total_path_comp_time.tv_usec = total_path_comp_time.tv_usec + d.tv_usec; - total_path_comp_time = tv_adjust(total_path_comp_time); - - gdouble path_comp_time_msec = (((total_path_comp_time.tv_sec) * 1000) + ((total_path_comp_time.tv_usec) / 1000)); - gdouble av_alg_comp_time = ((path_comp_time_msec / numSuccesPathComp)); - DEBUG_PC("\t --- STATS KSP PATH COMP ----"); - DEBUG_PC("Succesfully Comp: %d | Path Comp Requests: %d", numSuccesPathComp, numPathCompIntents); - DEBUG_PC("AV. PATH COMP ALG. TIME: %f ms", av_alg_comp_time); - - for (gint i = 0; i < serviceList->numServiceList; i++) { - struct service_t* s = &(serviceList->services[i]); - char* eptr; - for (gint j = 0; j < s->num_service_constraints; j++) { - struct constraint_t* constraints = &(s->constraints[j]); - if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) { - totalReqBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr)); - } - } - } - for (gint k = 0; k < routeConnList->numCompRouteConnList; k++) { - struct compRouteOutput_t* rO = &(routeConnList->compRouteConnection[k]); - if (rO->noPathIssue == NO_PATH_CONS_ISSUE) { - continue; - } - // Get the requested service bw bound to that computed path - struct path_t* p = &(rO->paths[0]); - struct service_t* s = get_service_for_computed_path(rO->serviceId.service_uuid); - if (s == NULL) { - DEBUG_PC("Weird the service associated to a path is not found"); - exit(-1); - } - for (gint l = 0; l < s->num_service_constraints; l++) { - struct constraint_t* constraints = &(s->constraints[l]); - char* eptr; - if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) { - totalServedBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr)); - } - } - } - gdouble avServedRatio = totalServedBw / totalReqBw; - DEBUG_PC("AV. Served Ratio: %f", avServedRatio); - gdouble avBlockedBwRatio = (gdouble)(1.0 - avServedRatio); - DEBUG_PC("AV. BBE: %f", avBlockedBwRatio); - return; -} +struct map_nodes_t *mapNodes; +struct graph_t *graph; +struct contextSet_t* contextSet; /////////////////////////////////////////////////////////////////////////////////// /** @@ -260,7 +187,7 @@ gint ksp_comp(struct pred_t* pred, struct graph_t* g, struct service_t* s, return -1; } - // Compute the shortes path route + // 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 @@ -579,6 +506,7 @@ void ksp_alg_execution_services(struct compRouteOutputList_t* outputList) { gint pathComp_ksp_alg(struct compRouteOutputList_t * routeConnList) { g_assert(routeConnList); + gint numSuccesPathComp = 0, numPathCompIntents = 0; DEBUG_PC ("================================================================"); DEBUG_PC ("=========================== KSP ========================="); @@ -608,7 +536,7 @@ gint pathComp_ksp_alg(struct compRouteOutputList_t * routeConnList) delta = tv_adjust(delta); numSuccesPathComp++; - update_stats_ksp_path_comp(routeConnList, delta); + update_stats_path_comp(routeConnList, delta, numSuccesPathComp, numPathCompIntents); print_path_connection_list(routeConnList); #endif diff --git a/src/pathcomp/backend/pathComp_ksp.h b/src/pathcomp/backend/pathComp_ksp.h index 628bd6e83b06f6bedda13ee31fe052eff01d6809..d542c493143ffe2187164c19711425aca7b7fcdf 100644 --- a/src/pathcomp/backend/pathComp_ksp.h +++ b/src/pathcomp/backend/pathComp_ksp.h @@ -25,18 +25,6 @@ #include <glib/gstdio.h> #include <glib-2.0/glib/gtypes.h> -#define MAX_KSP_VALUE 3 - -// HTTP RETURN CODES -#define HTTP_CODE_OK 200 -#define HTTP_CODE_CREATED 201 -#define HTTP_CODE_BAD_REQUEST 400 -#define HTTP_CODE_UNAUTHORIZED 401 -#define HTTP_CODE_FORBIDDEN 403 -#define HTTP_CODE_NOT_FOUND 404 -#define HTTP_CODE_NOT_ACCEPTABLE 406 - - // Prototype of external declaration of functions gint pathComp_ksp_alg (struct compRouteOutputList_t *); diff --git a/src/pathcomp/backend/pathComp_sp.c b/src/pathcomp/backend/pathComp_sp.c new file mode 100644 index 0000000000000000000000000000000000000000..735027fafcde1a6dfb9ce82faf3ba71a0bee56e5 --- /dev/null +++ b/src/pathcomp/backend/pathComp_sp.c @@ -0,0 +1,362 @@ +//////////////////////////////////////////////////////////////////////////////////////// +/** + * # Copyright 2022 Centre Tecnològic de Telecomunicacions de Catalunya (CTTC/CERCA) www.cttc.es + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + * Author: CTTC/CERCA PONS RU Ricardo Martínez (ricardo.martinez@cttc.es) + */ + //////////////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> +#include <glib.h> +#include <sys/time.h> +#include <ctype.h> +#include <strings.h> +#include <time.h> +#include <math.h> +#include <fcntl.h> + +#include "pathComp_log.h" +#include "pathComp_tools.h" +#include "pathComp_sp.h" + +// Global Variables +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 <ricardo.martinez@cttc.es> + * @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; +} + +/////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_sp.c + * @brief handling the Dijkstra algorithm + * + * @param pred + * @param g + * @param s + * + * @author Ricardo Martínez <ricardo.martinez@cttc.es> + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +gint computation(struct pred_t* pred, struct graph_t* g, struct service_t* s) { + g_assert(pred); + g_assert(g); + g_assert(s); + + // Check the both ingress src and dst endpoints are in the graph + gint srcMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[0].device_uuid, mapNodes); + if (srcMapIndex == -1) { + DEBUG_PC("ingress DeviceId: %s NOT in the graph", s->service_endpoints_id[0].device_uuid); + return -1; + } + + gint dstMapIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes); + if (dstMapIndex == -1) { + DEBUG_PC("egress DeviceId: %s NOT in the graph", s->service_endpoints_id[1].device_uuid); + return -1; + } + + // Compute the shortest path + dijkstra(srcMapIndex, dstMapIndex, g, s); + + // Check that a feasible solution in term of latency and bandwidth is found + gint map_dstIndex = get_map_index_by_nodeId(s->service_endpoints_id[1].device_uuid, mapNodes); + struct map_t* dest_map = &mapNodes->map[map_dstIndex]; + if (!(dest_map->distance < INFINITY_COST)) { + DEBUG_PC("destination: %s NOT reachable", s->service_endpoints_id[1].device_uuid); + return -1; + } + + DEBUG_PC("AvailBw @ %s is %f", dest_map->verticeId.nodeId, dest_map->avaiBandwidth); + // Check that the computed available bandwidth is larger than 0.0 + if (dest_map->avaiBandwidth <= (gfloat)0.0) { + DEBUG_PC("dst: %s NOT REACHABLE", s->service_endpoints_id[1].device_uuid); + return -1; + } + DEBUG_PC("dst: %s REACHABLE", s->service_endpoints_id[1].device_uuid); + // Handle predecessors + build_predecessors(pred, s, mapNodes); + + return 1; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_sp.c + * @brief CSPF algorithm execution + * + * @param s + * @param path + * @param g + * + * @author Ricardo Martínez <ricardo.martinez@cttc.es> + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void computation_shortest_path(struct service_t* s, struct compRouteOutput_t* path, struct graph_t* g) { + g_assert(s); + g_assert(path); + g_assert(g); + + // create map of devices / nodes to handle the path computation using the context + mapNodes = create_map_node(); + build_map_node(mapNodes, g); + + // predecessors to store the computed path + struct pred_t* predecessors = create_predecessors(); + + struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[0]); + struct service_endpoints_id_t* eEp = &(s->service_endpoints_id[1]); + + // SP computation + gint done = computation(predecessors, g, s); + 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); + + gboolean feasibleRoute = check_computed_path_feasability(s, p); + if (feasibleRoute == TRUE) { + DEBUG_PC("SP Feasible"); + print_path(p); + path->numPaths++; + + // Copy the serviceId + DEBUG_PC("contextId: %s", s->serviceId.contextId); + copy_service_id(&path->serviceId, &s->serviceId); + + // copy the service endpoints, in general, there will be 2 (point-to-point network connectivity services) + for (gint i = 0; i < s->num_service_endpoints_id; i++) { + struct service_endpoints_id_t* iEp = &(s->service_endpoints_id[i]); + struct service_endpoints_id_t* oEp = &(path->service_endpoints_id[i]); + copy_service_endpoint_id(oEp, iEp); + } + path->num_service_endpoints_id = s->num_service_endpoints_id; + + // Copy the computed path + struct path_t* targetedPath = &(path->paths[path->numPaths - 1]); + duplicate_path_t(p, targetedPath); + print_path_t(targetedPath); + g_free(predecessors); + g_free(p); + g_free(mapNodes); + return; + } + + DEBUG_PC("SP FAILED!!!"); + comp_route_connection_issue_handler(path, s); + + return; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_sp.c + * @brief Iterates over the list of network connectivity service requests + * to compute their own paths fulfilling the constraints + * + * @param outputList + * + * @author Ricardo Martínez <ricardo.martinez@cttc.es> + * @date 2022 + */ +void sp_execution_services(struct compRouteOutputList_t* oPathList) +{ + g_assert(oPathList); + g_assert(contextSet); + g_assert(serviceList); + + DEBUG_PC("----- Starting the SP Computation ------"); + + for (gint i = 0; i < serviceList->numServiceList; i++) { + struct service_t* service = &(serviceList->services[i]); + + DEBUG_PC("Starting the Computation for ServiceId: %s [ContextId: %s]", service->serviceId.service_uuid, service->serviceId.contextId); + struct compRouteOutput_t* pathService = &(oPathList->compRouteConnection[i]); + // check endpoints of the service are different (PE devices/nodes are different) + if (same_src_dst_pe_nodeid(service) == 0) { + DEBUG_PC("PEs are the same... no path computation"); + comp_route_connection_issue_handler(pathService, service); + oPathList->numCompRouteConnList++; + continue; + } + + // get the graph associated to the contextId in the contextSet, if no then error + struct graph_t* g = get_graph_by_contextId(contextSet, service->serviceId.contextId); + if (g == NULL) { + DEBUG_PC("The targeted contextId is NOT in the ContextSet ... then NO graph"); + comp_route_connection_issue_handler(pathService, service); + oPathList->numCompRouteConnList++; + continue; + } + + computation_shortest_path(service, pathService, g); + oPathList->numCompRouteConnList++; + + // for each network connectivity service, a single computed path (out of the KCSP) is retuned + // If path is found, then the selected resources must be pre-assigned into the context information + if (pathService->noPathIssue == NO_PATH_CONS_ISSUE) { + continue; + } + struct path_t* path = &(pathService->paths[pathService->numPaths - 1]); + allocate_graph_resources(path, service, g); + allocate_graph_reverse_resources(path, service, g); + print_graph(g); + } + return; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_sp.c + * @brief handles the path computation for the constrained shortest path + * + * @param compRouteOutput + * + * @author Ricardo Martínez <ricardo.martinez@cttc.es> + * @date 2022 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +gint pathComp_sp_alg(struct compRouteOutputList_t* routeConnList) +{ + g_assert(routeConnList); + + gint numSuccesPathComp = 0, numPathCompIntents = 0; + + DEBUG_PC("================================================================"); + DEBUG_PC("=========================== SP ========================="); + DEBUG_PC("================================================================"); + // increase the number of Path Comp. Intents + numPathCompIntents++; + gint http_code = HTTP_CODE_OK; + + // timestamp t0 + struct timeval t0; + gettimeofday(&t0, NULL); + + // Allocate memory for the context + contextSet = create_contextSet(); + // Build up the contextSet (>= 1) + build_contextSet(contextSet); + print_contextSet(contextSet); +#if 1 + //Triggering the path computation for each specific network connectivity service + sp_execution_services(routeConnList); + + // -- timestamp t1 + struct timeval t1, delta; + gettimeofday(&t1, NULL); + delta.tv_sec = t1.tv_sec - t0.tv_sec; + delta.tv_usec = t1.tv_usec - t0.tv_usec; + delta = tv_adjust(delta); + + numSuccesPathComp++; + update_stats_path_comp(routeConnList, delta, numSuccesPathComp, numPathCompIntents); + print_path_connection_list(routeConnList); +#endif + + g_free(contextSet); + return http_code; +} + + diff --git a/src/pathcomp/backend/pathComp_sp.h b/src/pathcomp/backend/pathComp_sp.h new file mode 100644 index 0000000000000000000000000000000000000000..fd0807fea36a69e0456e7e839265505c37ac9f86 --- /dev/null +++ b/src/pathcomp/backend/pathComp_sp.h @@ -0,0 +1,31 @@ +//////////////////////////////////////////////////////////////////////////////////////// +/** + * # 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_SP_H +#define _PATHCOMP_SP_H + + +#include <glib.h> +#include <glib/gstdio.h> +#include <glib-2.0/glib/gtypes.h> + + // Prototype of external declaration of functions +gint pathComp_sp_alg(struct compRouteOutputList_t*); + +#endif \ No newline at end of file diff --git a/src/pathcomp/backend/pathComp_tools.c b/src/pathcomp/backend/pathComp_tools.c index 1e584438461e9b99fdda9607ae3143ac5f48edf3..84cf63994405a07ff6c7fbb1da3fc667b0f0500f 100644 --- a/src/pathcomp/backend/pathComp_tools.c +++ b/src/pathcomp/backend/pathComp_tools.c @@ -41,6 +41,12 @@ #include "pathComp.h" #include "pathComp_tools.h" +gint numPathCompIntents = 0; // number of events triggering the path computation +//gint numSuccesPathComp = 0; // number of events resulting in succesfully path computations fulfilling the constraints +struct timeval total_path_comp_time; +gdouble totalReqBw = 0.0; +gdouble totalServedBw = 0.0; + //////////////////////////////////////////////////////////////////////////////////////// /** * @file pathComp_tools.c @@ -1698,6 +1704,7 @@ struct linkList_t* create_link_list() { DEBUG_PC("Memory Allocation Failure"); exit(-1); } + lList->numLinks = 0; return lList; } @@ -1910,7 +1917,7 @@ void print_link_forwarding_direction(guint linkFwDir) { DEBUG_PC("BIDIRECTIONAL LINK FORWARDING DIRECTION"); break; case LINK_FORWARDING_DIRECTION_UNIDIRECTIONAL: - //DEBUG_PC("UNIDIRECTIONAL LINK FORWARDING DIRECTION"); + DEBUG_PC("UNIDIRECTIONAL LINK FORWARDING DIRECTION"); break; case LINK_FORWARDING_DIRECTION_UNKNOWN: DEBUG_PC("UNKNOWN LINK FORWARDING DIRECTION"); @@ -2701,3 +2708,65 @@ void print_path_connection_list(struct compRouteOutputList_t* routeList) { return; } +/////////////////////////////////////////////////////////////////////////////////// +/** + * @file pathComp_tools.c + * @brief update statistics for the path computation operations + * + * @param routeConnList + * @param d + * + * @author Ricardo MartÃnez <ricardo.martinez@cttc.es> + * @date 2021 + */ + ///////////////////////////////////////////////////////////////////////////////////////// +void update_stats_path_comp(struct compRouteOutputList_t* routeConnList, struct timeval d, gint numSuccesPathComp, gint numPathCompIntents) { + g_assert(routeConnList); + + total_path_comp_time.tv_sec = total_path_comp_time.tv_sec + d.tv_sec; + total_path_comp_time.tv_usec = total_path_comp_time.tv_usec + d.tv_usec; + total_path_comp_time = tv_adjust(total_path_comp_time); + + gdouble path_comp_time_msec = (((total_path_comp_time.tv_sec) * 1000) + ((total_path_comp_time.tv_usec) / 1000)); + gdouble av_alg_comp_time = ((path_comp_time_msec / numSuccesPathComp)); + DEBUG_PC("\t --- STATS PATH COMP ----"); + DEBUG_PC("Succesfully Comp: %d | Path Comp Requests: %d", numSuccesPathComp, numPathCompIntents); + DEBUG_PC("AV. PATH COMP ALG. TIME: %f ms", av_alg_comp_time); + + for (gint i = 0; i < serviceList->numServiceList; i++) { + struct service_t* s = &(serviceList->services[i]); + char* eptr; + for (gint j = 0; j < s->num_service_constraints; j++) { + struct constraint_t* constraints = &(s->constraints[j]); + if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) { + totalReqBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr)); + } + } + } + for (gint k = 0; k < routeConnList->numCompRouteConnList; k++) { + struct compRouteOutput_t* rO = &(routeConnList->compRouteConnection[k]); + if (rO->noPathIssue == NO_PATH_CONS_ISSUE) { + continue; + } + // Get the requested service bw bound to that computed path + struct path_t* p = &(rO->paths[0]); + struct service_t* s = get_service_for_computed_path(rO->serviceId.service_uuid); + if (s == NULL) { + DEBUG_PC("Weird the service associated to a path is not found"); + exit(-1); + } + for (gint l = 0; l < s->num_service_constraints; l++) { + struct constraint_t* constraints = &(s->constraints[l]); + char* eptr; + if (strncmp((const char*)(constraints->constraint_type), "bandwidth", 9) == 0) { + totalServedBw += (gdouble)(strtod((char*)constraints->constraint_value, &eptr)); + } + } + } + gdouble avServedRatio = totalServedBw / totalReqBw; + DEBUG_PC("AV. Served Ratio: %f", avServedRatio); + gdouble avBlockedBwRatio = (gdouble)(1.0 - avServedRatio); + DEBUG_PC("AV. BBE: %f", avBlockedBwRatio); + return; + +} diff --git a/src/pathcomp/backend/pathComp_tools.h b/src/pathcomp/backend/pathComp_tools.h index b8adda535048d353c0f5c49636c5ed8e5e92ca2c..393274e161ee131c4e9d35922cc579faa088ed6e 100644 --- a/src/pathcomp/backend/pathComp_tools.h +++ b/src/pathcomp/backend/pathComp_tools.h @@ -37,11 +37,21 @@ extern struct serviceList_t* serviceList; #define INFINITY_COST 0xFFFFFFFF #define MAX_NUM_PRED 100 -#define K_MAX 5 +#define MAX_KSP_VALUE 3 + +// HTTP RETURN CODES +#define HTTP_CODE_OK 200 +#define HTTP_CODE_CREATED 201 +#define HTTP_CODE_BAD_REQUEST 400 +#define HTTP_CODE_UNAUTHORIZED 401 +#define HTTP_CODE_FORBIDDEN 403 +#define HTTP_CODE_NOT_FOUND 404 +#define HTTP_CODE_NOT_ACCEPTABLE 406 #define MAX_NODE_ID_SIZE 37 // UUID 128 Bits - In hexadecimal requires 36 char #define MAX_CONTEXT_ID 37 -#define UUID_CHAR_LENGTH 37 +//#define UUID_CHAR_LENGTH 37 +#define UUID_CHAR_LENGTH 100 struct nodes_t { gchar nodeId[UUID_CHAR_LENGTH]; }; @@ -299,7 +309,7 @@ struct latency_characteristics_t { struct link_t { gchar linkId[UUID_CHAR_LENGTH]; // link Id using UUID (128 bits) - guint numLinkEndPointIds; + gint numLinkEndPointIds; struct link_endpointId_t linkEndPointId[MAX_NUM_LINK_ENDPOINT_IDS]; guint forwarding_direction; @@ -603,4 +613,5 @@ void print_route_solution_list (GList *); struct timeval tv_adjust(struct timeval); void print_path_connection_list(struct compRouteOutputList_t*); +void update_stats_path_comp(struct compRouteOutputList_t*, struct timeval, gint, gint); #endif \ No newline at end of file diff --git a/src/pathcomp/frontend/tests/test_unitary.py b/src/pathcomp/frontend/tests/test_unitary.py index e21fe8209d6e07eff6edfcf6f85880a5de01b0a7..2368a6c0ade2bd0125a0a8df66560496fe782a1d 100644 --- a/src/pathcomp/frontend/tests/test_unitary.py +++ b/src/pathcomp/frontend/tests/test_unitary.py @@ -84,10 +84,10 @@ def test_request_service_shortestpath( pathcomp_client : PathCompClient): # pylint: disable=redefined-outer-name request_services = copy.deepcopy(SERVICES) - request_services[0]['service_constraints'] = [ - json_constraint('bandwidth[gbps]', 1000.0), - json_constraint('latency[ms]', 1200.0), - ] + #request_services[0]['service_constraints'] = [ + # json_constraint('bandwidth[gbps]', 1000.0), + # json_constraint('latency[ms]', 1200.0), + #] pathcomp_request = PathCompRequest(services=request_services) pathcomp_request.shortest_path.Clear() # hack to select the shortest path algorithm that has no attributes