From f67adad42f2c857ff76b52df39f0beb5c2cabee4 Mon Sep 17 00:00:00 2001 From: Niranjana Date: Thu, 3 Feb 2022 04:50:38 +0000 Subject: [DCAEGEN2] Calculate slice utilization data Issue-ID: DCAEGEN2-2942 Signed-off-by: Niranjana Change-Id: Id16d2a36cf964b15495531a54094cad96471bdcb --- .../slice/analysis/ms/service/ConsumerThread.java | 150 ++++---- .../analysis/ms/service/MLMessageProcessor.java | 87 ++--- .../analysis/ms/service/SliceUtilization.java | 216 ++++++++++++ .../ms/service/SnssaiSamplesProcessor.java | 385 +++++++++++---------- 4 files changed, 528 insertions(+), 310 deletions(-) create mode 100644 components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java (limited to 'components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service') diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java index 6098142e..5dcd9189 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,95 +24,93 @@ package org.onap.slice.analysis.ms.service; import java.util.List; import java.util.Objects; -import org.onap.slice.analysis.ms.configdb.CpsInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.SubCounter; import org.onap.slice.analysis.ms.utils.BeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** +/** * This Thread class consumes message from pm data queue and sends onset message to policy */ public class ConsumerThread extends Thread { - private static Logger log = LoggerFactory.getLogger(ConsumerThread.class); - private PmDataQueue pmDataQueue; - private IConfigDbService configDbService; - private SnssaiSamplesProcessor snssaiSamplesProcessor; - private CpsInterface cpsInterface; - private long initialDelaySec; - private int samples; + private static Logger log = LoggerFactory.getLogger(ConsumerThread.class); + private PmDataQueue pmDataQueue; + private IConfigDbService configDbService; + private SnssaiSamplesProcessor snssaiSamplesProcessor; + private CpsInterface cpsInterface; + private long initialDelaySec; + private int samples; - /** - * Default constructor. - */ - public ConsumerThread() { - super(); - this.pmDataQueue = BeanUtil.getBean(PmDataQueue.class); - this.configDbService = BeanUtil.getBean(IConfigDbService.class); - this.initialDelaySec = Configuration.getInstance().getInitialDelaySeconds(); - this.samples = Configuration.getInstance().getSamples(); - this.cpsInterface = BeanUtil.getBean(CpsInterface.class); - } + /** + * Default constructor. + */ + public ConsumerThread() { + super(); + this.pmDataQueue = BeanUtil.getBean(PmDataQueue.class); + this.configDbService = BeanUtil.getBean(IConfigDbService.class); + this.initialDelaySec = Configuration.getInstance().getInitialDelaySeconds(); + this.samples = Configuration.getInstance().getSamples(); + this.cpsInterface = BeanUtil.getBean(CpsInterface.class); + } - /** - * Consumes data from PM data queue, process the data and sends onset message to policy if needed - */ - @Override - public void run() { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - boolean done = false; - boolean result = false; - String snssai = ""; - List nfs = null; - while (!done) { - try { - Thread.sleep(initialDelaySec); - log.info("Starting Consumer Thread"); - snssai = pmDataQueue.getSnnsaiFromQueue(); - if (!snssai.equals("")) { - log.info("Consumer thread processing data for s-nssai {}",snssai); - try { - if (isConfigDbEnabled) { - nfs = configDbService.fetchNetworkFunctionsOfSnssai(snssai); - } - else { - nfs = cpsInterface.fetchNetworkFunctionsOfSnssai(snssai); - } - } - catch(Exception e) { - pmDataQueue.putSnssaiToQueue(snssai); - log.error("Exception caught while fetching nfs of snssai {}, {}", snssai, e.getMessage()); - } - if(nfs != null && checkForEnoughSamples(nfs, snssai)) { - this.snssaiSamplesProcessor = BeanUtil.getBean(SnssaiSamplesProcessor.class); - result = snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs); - if(!result) { - log.info("Not enough samples to process for {}",snssai); - pmDataQueue.putSnssaiToQueue(snssai); - } - } - } - } catch (Exception e) { - log.error("Exception in Consumer Thread, {}", e.getMessage()); - done = true; - } - } - } + /** + * Consumes data from PM data queue, process the data and sends onset message to policy if needed + */ + @Override + public void run() { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + boolean done = false; + boolean result = false; + String snssai = ""; + List nfs = null; + while (!done) { + try { + Thread.sleep(initialDelaySec); + log.info("Starting Consumer Thread"); + snssai = pmDataQueue.getSnnsaiFromQueue(); + if (!snssai.equals("")) { + log.info("Consumer thread processing data for s-nssai {}", snssai); + try { + if (isConfigDbEnabled) { + nfs = configDbService.fetchNetworkFunctionsOfSnssai(snssai); + } else { + nfs = cpsInterface.fetchNetworkFunctionsOfSnssai(snssai); + } + } catch (Exception e) { + pmDataQueue.putSnssaiToQueue(snssai); + log.error("Exception caught while fetching nfs of snssai {}, {}", snssai, e.getMessage()); + } + if (nfs != null && checkForEnoughSamples(nfs, snssai)) { + this.snssaiSamplesProcessor = BeanUtil.getBean(SnssaiSamplesProcessor.class); + result = snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs); + if (!result) { + log.info("Not enough samples to process for {}", snssai); + pmDataQueue.putSnssaiToQueue(snssai); + } + } + } + } catch (Exception e) { + log.error("Exception in Consumer Thread, {}", e.getMessage()); + done = true; + } + } + } /** * Checks whether enough samples are available for the network functions */ - public boolean checkForEnoughSamples(List nfs, String snssai) { - for(String nf : nfs) { - if(! pmDataQueue.checkSamplesInQueue(new SubCounter(nf, snssai), samples)) { - log.info("Not enough samples to process for network function {} of snssai {}", nf, snssai); - pmDataQueue.putSnssaiToQueue(snssai); - return false; - } - } - return true; - } + public boolean checkForEnoughSamples(List nfs, String snssai) { + for (String nf : nfs) { + if (!pmDataQueue.checkSamplesInQueue(new SubCounter(nf, snssai), samples)) { + log.info("Not enough samples to process for network function {} of snssai {}", nf, snssai); + pmDataQueue.putSnssaiToQueue(snssai); + return false; + } + } + return true; + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java index 8bc7b0d5..f692efcc 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import org.onap.slice.analysis.ms.configdb.AaiInterface; -import org.onap.slice.analysis.ms.configdb.CpsInterface; +import org.onap.slice.analysis.ms.aai.AaiInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.CUModel; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.MLOutputModel; @@ -44,51 +44,54 @@ import org.springframework.stereotype.Component; @Component @Scope("prototype") public class MLMessageProcessor { - private static Logger log = LoggerFactory.getLogger(MLMessageProcessor.class); + private static Logger log = LoggerFactory.getLogger(MLMessageProcessor.class); - @Autowired - private IConfigDbService configDbService; + @Autowired + private IConfigDbService configDbService; - @Autowired - private PolicyService policyService; + @Autowired + private PolicyService policyService; - @Autowired - private AaiInterface aaiInterface; + @Autowired + private AaiInterface aaiInterface; - @Autowired - private CpsInterface cpsInterface; + @Autowired + private CpsInterface cpsInterface; - public void processMLMsg(MLOutputModel mlOutputMsg) { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - Map> ricToCellMapping = null; - Map serviceDetails = null; - String snssai = mlOutputMsg.getSnssai(); - List cuData = mlOutputMsg.getData(); - if (isConfigDbEnabled) { - ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); - } else { - ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); - } - log.debug("RIC to cell mapping of S-NSSAI {} is {}", snssai, ricToCellMapping); - for (CUModel cuModel : cuData) { - String cellId = String.valueOf(cuModel.getCellCUList().get(0).getCellLocalId()); - ricToCellMapping.forEach((ricId, cells) -> { - if (cells.contains(cellId)) { - cuModel.setNearRTRICId(ricId); - } - }); - } - AdditionalProperties addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(mlOutputMsg); + /** + * Process the message sent by ML service and sends notification to policy + */ + public void processMLMsg(MLOutputModel mlOutputMsg) { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + Map> ricToCellMapping = null; + Map serviceDetails = null; + String snssai = mlOutputMsg.getSnssai(); + List cuData = mlOutputMsg.getData(); + if (isConfigDbEnabled) { + ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); + } else { + ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); + } + log.debug("RIC to cell mapping of S-NSSAI {} is {}", snssai, ricToCellMapping); + for (CUModel cuModel : cuData) { + String cellId = String.valueOf(cuModel.getCellCUList().get(0).getCellLocalId()); + ricToCellMapping.forEach((ricId, cells) -> { + if (cells.contains(cellId)) { + cuModel.setNearRTRICId(ricId); + } + }); + } + AdditionalProperties addProps = new AdditionalProperties<>(); + addProps.setResourceConfig(mlOutputMsg); - if (isConfigDbEnabled) { - serviceDetails = configDbService.fetchServiceDetails(snssai); - } else { - serviceDetails = aaiInterface.fetchServiceDetails(snssai); + if (isConfigDbEnabled) { + serviceDetails = configDbService.fetchServiceDetails(snssai); + } else { + serviceDetails = aaiInterface.fetchServiceDetails(snssai); - } - policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); - } + } + policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java new file mode 100644 index 00000000..94696343 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * 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. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.onap.slice.analysis.ms.exception.DesClientException; +import org.onap.slice.analysis.ms.models.AggregatedConfig; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.models.SliceConfigDetails; +import org.onap.slice.analysis.ms.models.SliceConfigRequest; +import org.onap.slice.analysis.ms.models.SliceConfigResponse; +import org.onap.slice.analysis.ms.restclients.DesRestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * This Service calculates the slice utilization details + */ +@Service +public class SliceUtilization { + + private static Logger log = LoggerFactory.getLogger(SliceUtilization.class); + + @Autowired + private AaiService aaiService; + + @Autowired + DesRestClient desRestClient; + + /** + * Default values set for uplink and downlink throughput calculation (in + * accordance with 3GPP specifications) + * + */ + private static final Integer numOfAggregatedComponentCarries = 8; + private static final Integer maxNumOfLayers = 4; + private static final Integer maxModulationOrder = 2; + private static final Integer scalingFactor = 1; + private static final Double maxBitRate = 948.0 / 1024; + private static final Integer nrNumerology = 2; + private static final Double averageSymbolDuration = Math.pow(10, -3) / (14 * 2 * nrNumerology); + private static final Double overHeadForDl = 0.18; + private static final Double overHeadForUl = 0.10; + private static final Integer TOTAL_PRB = 132; + + /** + * Calculates the slice utilization details for requested slices. + * + * @param sliceConfigRequest contains sliceInstanceId + * @return SliceConfigResponse contains slice utilization details + */ + public SliceConfigResponse getSliceUtilizationData(SliceConfigRequest sliceConfigRequest) { + + log.info("getSliceUtilizationData"); + SliceConfigResponse sliceConfigResponse = new SliceConfigResponse(); + ArrayList sliceConfigDetailsList = new ArrayList<>(); + + try { + sliceConfigRequest.getSliceIdentifiers().forEach(sliceInstanceId -> { + List snssaiList = null; + snssaiList = aaiService.getSnssaiList(sliceInstanceId); + List pmDataList = new ArrayList<>(); + snssaiList.forEach(snssai -> { + JSONObject pmData = getPMData(snssai); + pmDataList.add(pmData); + }); + AggregatedConfig aggregatedConfig = calculateSliceUtilization(pmDataList); + SliceConfigDetails sliceConfigDetails = new SliceConfigDetails(); + sliceConfigDetails.setSliceIdentifiers(sliceInstanceId); + sliceConfigDetails.setAggregatedConfig(aggregatedConfig); + sliceConfigDetailsList.add(sliceConfigDetails); + + }); + } catch (Exception e) { + log.error("Exception caught while fetching data"); + } + sliceConfigResponse.setSliceConfigDetails(sliceConfigDetailsList); + log.info("SliceConfigResponse: " + sliceConfigResponse.toString()); + return sliceConfigResponse; + + } + + /** + * Fetches the PM data for requested SNSSAI from DES. + * + * @param snssai snssai ID + * @return PM Data for requested SNSSAI + */ + protected JSONObject getPMData(String snssai) { + String desUrl = Configuration.getInstance().getDesUrl(); + Map inputParameter = new HashMap<>(); + int duration = Configuration.getInstance().getPmDataDurationInWeeks(); + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + calendar.add(Calendar.WEEK_OF_MONTH, -duration); + inputParameter.put("snssai", "SM.PrbUsedDl." + snssai); + inputParameter.put("time", String.valueOf(calendar.getTimeInMillis())); + ResponseEntity response = null; + JSONObject pmData = null; + try { + + String jsonRequestBody = new ObjectMapper().writeValueAsString(inputParameter); + log.info("fetching PM Data for : {}", snssai); + response = + desRestClient.sendPostRequest(desUrl, jsonRequestBody, new ParameterizedTypeReference() {}); + pmData = new JSONObject(response.getBody()); + if (response.getStatusCode().value() != 200) { + throw new DesClientException(String.format("Response code from DES other than 200: %d\", statusCode", + response.getStatusCode().value())); + } + + } catch (Exception e) { + log.error("Error while fetching PM data from DES {} ", e); + } + + return pmData; + } + + /** + * Calculates average DL and UL PRB used from the PM data and returns the + * remaining resources(utilization details) in terms of throughput + * + * @param pmDataList PM data for all SNSSAIs + * @return aggregatedConfig containing slice utilization details + */ + protected AggregatedConfig calculateSliceUtilization(List pmDataList) { + + Integer numOfPRBData = 0; + Integer dlPRBUsed = 0; + Integer ulPRBUsed = 0; + Integer dlThptIndex = 0; + Integer ulThptIndex = 1; + try { + for (JSONObject pmData : pmDataList) { + JSONArray result = pmData.getJSONArray("result"); + for (int i = 0; i < result.length(); i++) { + JSONObject measValuesObject = result.getJSONObject(i); + String measValuesListStr = measValuesObject.getString("measValuesList"); + String sMeasTypesListtStr = measValuesObject.getString("sMeasTypesList"); + JSONArray measValuesArray = new JSONArray(measValuesListStr); + JSONArray sMeasTypesArray = new JSONArray(sMeasTypesListtStr); + if (sMeasTypesArray.getString(0).contains("PrbUsedUl")) { + ulThptIndex = 0; + dlThptIndex = 1; + } + numOfPRBData += measValuesArray.length(); + for (int j = 0; j < measValuesArray.length(); j++) { + dlPRBUsed += + measValuesArray.getJSONArray(j).getJSONArray(2).getJSONArray(dlThptIndex).getInt(1); + ulPRBUsed += + measValuesArray.getJSONArray(j).getJSONArray(2).getJSONArray(ulThptIndex).getInt(1); + } + } + } + } catch (Exception e) { + log.error("Exception caught while calculating slice utilization: {}", e); + } + + Integer averageDLPrb = dlPRBUsed / numOfPRBData; + Integer averageULPrb = ulPRBUsed / numOfPRBData; + Double tempdl = 0.0; + Double tempul = 0.0; + int j = 1; + + while (j <= numOfAggregatedComponentCarries) { + tempdl += ((Math.pow(maxNumOfLayers, j) * Math.pow(maxModulationOrder, j) * Math.pow(scalingFactor, j) + * maxBitRate * (TOTAL_PRB - averageDLPrb) * 12 * (1 - Math.pow(overHeadForDl, j))) + / averageSymbolDuration) * Math.pow(10, -6); + tempul += ((Math.pow(maxNumOfLayers, j) * Math.pow(maxModulationOrder, j) * Math.pow(scalingFactor, j) + * maxBitRate * (TOTAL_PRB - averageULPrb) * 12 * (1 - Math.pow(overHeadForUl, j))) + / averageSymbolDuration) * Math.pow(10, -6); + j++; + + } + + Integer dLThptPerSliceInMbps = (int) Math.round(tempdl); + Integer uLThptPerSliceInMbps = (int) Math.round(tempul); + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + aggregatedConfig.setDLThptPerSlice(dLThptPerSliceInMbps); + aggregatedConfig.setULThptPerSlice(uLThptPerSliceInMbps); + return aggregatedConfig; + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java index d802f81d..b4e06896 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= * *******************************************************************************/ + package org.onap.slice.analysis.ms.service; import java.util.ArrayList; @@ -29,9 +30,9 @@ import java.util.Objects; import javax.annotation.PostConstruct; -import org.onap.slice.analysis.ms.configdb.AaiInterface; -import org.onap.slice.analysis.ms.configdb.CpsInterface; +import org.onap.slice.analysis.ms.aai.AaiInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.MeasurementObject; import org.onap.slice.analysis.ms.models.SubCounter; @@ -48,201 +49,201 @@ import org.springframework.stereotype.Component; @Component @Scope("prototype") public class SnssaiSamplesProcessor { - private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class); - - @Autowired - private PolicyService policyService; - - @Autowired - private IConfigDbService configDbService; - - @Autowired - private PmDataQueue pmDataQueue; - - @Autowired - private AverageCalculator averageCalculator; - - @Autowired - private AaiInterface aaiInterface; - - @Autowired - private CpsInterface cpsInterface; - - private List snssaiMeasurementList = new ArrayList<>(); - private Map> ricToCellMapping = new HashMap<>(); - private Map> ricToPrbsMapping = new HashMap<>(); - private Map> ricToThroughputMapping = new HashMap<>(); - private int noOfSamples; - private List pmsToCompute; - private Map prbThroughputMapping = new HashMap<>(); - private int minPercentageChange; - - @PostConstruct - public void init() { - Configuration configuration = Configuration.getInstance(); - noOfSamples = configuration.getSamples(); - pmsToCompute = new ArrayList<>(); - pmsToCompute.add("PrbUsedDl"); - pmsToCompute.add("PrbUsedUl"); - prbThroughputMapping = new HashMap<>(); - prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); - prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); - minPercentageChange = configuration.getMinPercentageChange(); + private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class); + + @Autowired + private PolicyService policyService; + + @Autowired + private IConfigDbService configDbService; + + @Autowired + private PmDataQueue pmDataQueue; + + @Autowired + private AverageCalculator averageCalculator; + + @Autowired + private AaiInterface aaiInterface; + + @Autowired + private CpsInterface cpsInterface; + + private List snssaiMeasurementList = new ArrayList<>(); + private Map> ricToCellMapping = new HashMap<>(); + private Map> ricToPrbsMapping = new HashMap<>(); + private Map> ricToThroughputMapping = new HashMap<>(); + private int noOfSamples; + private List pmsToCompute; + private Map prbThroughputMapping = new HashMap<>(); + private int minPercentageChange; + + @PostConstruct + public void init() { + Configuration configuration = Configuration.getInstance(); + noOfSamples = configuration.getSamples(); + pmsToCompute = new ArrayList<>(); + pmsToCompute.add("PrbUsedDl"); + pmsToCompute.add("PrbUsedUl"); + prbThroughputMapping = new HashMap<>(); + prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); + prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); + minPercentageChange = configuration.getMinPercentageChange(); + } + + /** + * process the measurement data of an S-NSSAI + */ + public boolean processSamplesOfSnnsai(String snssai, List networkFunctions) { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + List sample = null; + List> samples = null; + Map serviceDetails = null; + log.info("Network Functions {} of snssai {}", networkFunctions, snssai); + for (String nf : networkFunctions) { + log.debug("Average of samples for {}:", snssai); + samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples); + if (samples != null) { + sample = averageCalculator.findAverageOfSamples(samples); + addToMeasurementList(sample); + } else { + log.info("Not enough samples present for nf {}", nf); + return false; + } } - - /** - * process the measurement data of an S-NSSAI - */ - public boolean processSamplesOfSnnsai(String snssai, List networkFunctions) { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - List sample = null; - List> samples = null; - Map serviceDetails =null; - log.info("Network Functions {} of snssai {}", networkFunctions, snssai); - for (String nf : networkFunctions) { - log.debug("Average of samples for {}:", snssai); - samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples); - if (samples != null) { - sample = averageCalculator.findAverageOfSamples(samples); - addToMeasurementList(sample); - } else { - log.info("Not enough samples present for nf {}", nf); - return false; - } - } - log.info("snssai measurement list {}", snssaiMeasurementList); - Map> ricConfiguration; - Map sliceConfiguration; - if (isConfigDbEnabled) { - ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); - ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai); - sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai); - serviceDetails = configDbService.fetchServiceDetails(snssai); - } else { - ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); - ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai); - serviceDetails = aaiInterface.fetchServiceDetails(snssai); - sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai); - } - log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping); - log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration); - pmsToCompute.forEach(pm -> { - log.debug("processing for pm {}", pm); - sumOfPrbsAcrossCells(pm); - int sum = computeSum(pm); - computeThroughput(sliceConfiguration, sum, pm); - calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm)); - }); - updateConfiguration(); - if (ricToThroughputMapping.size() > 0) { - AdditionalProperties>>> addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping)); - policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); - } - return true; + log.info("snssai measurement list {}", snssaiMeasurementList); + Map> ricConfiguration; + Map sliceConfiguration; + if (isConfigDbEnabled) { + ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); + ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai); + sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai); + serviceDetails = configDbService.fetchServiceDetails(snssai); + } else { + ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); + ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai); + serviceDetails = aaiInterface.fetchServiceDetails(snssai); + sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai); } - - /** - * change the RICConfig data format to be compatible with SDN-R - */ - protected Map>> getChangedRIConfigFormat( - Map> ricToThroughputMapping) { - Iterator>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry> entry = null; - List> ricConfigList = new ArrayList<>(); - Map>> ricConfigData = new HashMap<>(); - while (it.hasNext()) { - Map newConfigMap = new HashMap<>(); - entry = it.next(); - newConfigMap = entry.getValue(); - newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey())); - ricConfigList.add(newConfigMap); - } - ricConfigData.put("data", ricConfigList); - return ricConfigData; + log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping); + log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration); + pmsToCompute.forEach(pm -> { + log.debug("processing for pm {}", pm); + sumOfPrbsAcrossCells(pm); + int sum = computeSum(pm); + computeThroughput(sliceConfiguration, sum, pm); + calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm)); + }); + updateConfiguration(); + if (ricToThroughputMapping.size() > 0) { + AdditionalProperties>>> addProps = new AdditionalProperties<>(); + addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping)); + policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); } - - /** - * process the measurement data of an S-NSSAI - */ - protected void updateConfiguration() { - Iterator>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry> entry = null; - while (it.hasNext()) { - entry = it.next(); - if (entry.getValue().size() == 0) { - it.remove(); - } - } + return true; + } + + /** + * change the RICConfig data format to be compatible with SDN-R + */ + protected Map>> getChangedRIConfigFormat( + Map> ricToThroughputMapping) { + Iterator>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry> entry = null; + List> ricConfigList = new ArrayList<>(); + Map>> ricConfigData = new HashMap<>(); + while (it.hasNext()) { + Map newConfigMap = new HashMap<>(); + entry = it.next(); + newConfigMap = entry.getValue(); + newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey())); + ricConfigList.add(newConfigMap); } - - private void addToMeasurementList(List sample) { - snssaiMeasurementList.addAll(sample); + ricConfigData.put("data", ricConfigList); + return ricConfigData; + } + + /** + * process the measurement data of an S-NSSAI + */ + protected void updateConfiguration() { + Iterator>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry> entry = null; + while (it.hasNext()) { + entry = it.next(); + if (entry.getValue().size() == 0) { + it.remove(); + } } - - /** - * Calculate the change in the configuration value and keep the configuration - * only if it is greater than a specific limit - */ - protected void calculatePercentageChange(Map> ricConfiguration, String pm) { - Iterator>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry> entry = null; - float existing = 0; - float change = 0; - while (it.hasNext()) { - entry = it.next(); - existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm)); - change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100; - if (change <= minPercentageChange) { - ricToThroughputMapping.get(entry.getKey()).remove(pm); - log.info("Removing pm data {} for RIC {}", pm, entry.getKey()); - } - } + } + + private void addToMeasurementList(List sample) { + snssaiMeasurementList.addAll(sample); + } + + /** + * Calculate the change in the configuration value and keep the configuration + * only if it is greater than a specific limit + */ + protected void calculatePercentageChange(Map> ricConfiguration, String pm) { + Iterator>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry> entry = null; + float existing = 0; + float change = 0; + while (it.hasNext()) { + entry = it.next(); + existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm)); + change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100; + if (change <= minPercentageChange) { + ricToThroughputMapping.get(entry.getKey()).remove(pm); + log.info("Removing pm data {} for RIC {}", pm, entry.getKey()); + } } - - protected void sumOfPrbsAcrossCells(String pmName) { - ricToCellMapping.forEach((ric, cells) -> { - int sumOfPrbs = 0; - for (String cell : cells) { - int index = MeasurementObject.findIndex(cell, snssaiMeasurementList); - sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName); - } - if (ricToPrbsMapping.containsKey(ric)) { - ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs); - } else { - Map pmToPrbMapping = new HashMap<>(); - pmToPrbMapping.put(pmName, sumOfPrbs); - ricToPrbsMapping.put(ric, pmToPrbMapping); - } - }); - log.info("PRBs sum computed for RIC {}", ricToPrbsMapping); - } - - protected Integer computeSum(String pm) { - return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum); - } - - protected void computeThroughput(Map sliceConfiguration, int sum, String pm) { - Iterator>> it = ricToPrbsMapping.entrySet().iterator(); - Map.Entry> entry = null; - Map throughtputMap = null; - String ric = ""; - int value = 0; - while (it.hasNext()) { - entry = it.next(); - ric = entry.getKey(); - value = Math.round(((float) entry.getValue().get(pm) / sum) - * (float) sliceConfiguration.get(prbThroughputMapping.get(pm))); - if (ricToThroughputMapping.containsKey(ric)) { - ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value); - } else { - throughtputMap = new HashMap<>(); - throughtputMap.put(prbThroughputMapping.get(pm), value); - ricToThroughputMapping.put(ric, throughtputMap); - } - } - log.info("Throughput computed for RIC {}", ricToThroughputMapping); + } + + protected void sumOfPrbsAcrossCells(String pmName) { + ricToCellMapping.forEach((ric, cells) -> { + int sumOfPrbs = 0; + for (String cell : cells) { + int index = MeasurementObject.findIndex(cell, snssaiMeasurementList); + sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName); + } + if (ricToPrbsMapping.containsKey(ric)) { + ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs); + } else { + Map pmToPrbMapping = new HashMap<>(); + pmToPrbMapping.put(pmName, sumOfPrbs); + ricToPrbsMapping.put(ric, pmToPrbMapping); + } + }); + log.info("PRBs sum computed for RIC {}", ricToPrbsMapping); + } + + protected Integer computeSum(String pm) { + return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum); + } + + protected void computeThroughput(Map sliceConfiguration, int sum, String pm) { + Iterator>> it = ricToPrbsMapping.entrySet().iterator(); + Map.Entry> entry = null; + Map throughtputMap = null; + String ric = ""; + int value = 0; + while (it.hasNext()) { + entry = it.next(); + ric = entry.getKey(); + value = Math.round(((float) entry.getValue().get(pm) / sum) + * (float) sliceConfiguration.get(prbThroughputMapping.get(pm))); + if (ricToThroughputMapping.containsKey(ric)) { + ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value); + } else { + throughtputMap = new HashMap<>(); + throughtputMap.put(prbThroughputMapping.get(pm), value); + ricToThroughputMapping.put(ric, throughtputMap); + } } + log.info("Throughput computed for RIC {}", ricToThroughputMapping); + } } -- cgit 1.2.3-korg