1 /*******************************************************************************
2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 Wipro Limited.
6 * ==============================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 *******************************************************************************/
21 package org.onap.slice.analysis.ms.service;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
28 import java.util.Objects;
30 import javax.annotation.PostConstruct;
32 import org.onap.slice.analysis.ms.configdb.AaiInterface;
33 import org.onap.slice.analysis.ms.configdb.CpsInterface;
34 import org.onap.slice.analysis.ms.configdb.IConfigDbService;
35 import org.onap.slice.analysis.ms.models.Configuration;
36 import org.onap.slice.analysis.ms.models.MeasurementObject;
37 import org.onap.slice.analysis.ms.models.SubCounter;
38 import org.onap.slice.analysis.ms.models.policy.AdditionalProperties;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.context.annotation.Scope;
43 import org.springframework.stereotype.Component;
46 * This class process the measurement data of an S-NSSAI
50 public class SnssaiSamplesProcessor {
51 private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class);
54 private PolicyService policyService;
57 private IConfigDbService configDbService;
60 private PmDataQueue pmDataQueue;
63 private AverageCalculator averageCalculator;
66 private AaiInterface aaiInterface;
69 private CpsInterface cpsInterface;
71 private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>();
72 private Map<String, List<String>> ricToCellMapping = new HashMap<>();
73 private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>();
74 private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>();
75 private int noOfSamples;
76 private List<String> pmsToCompute;
77 private Map<String, String> prbThroughputMapping = new HashMap<>();
78 private int minPercentageChange;
82 Configuration configuration = Configuration.getInstance();
83 noOfSamples = configuration.getSamples();
84 pmsToCompute = new ArrayList<>();
85 pmsToCompute.add("PrbUsedDl");
86 pmsToCompute.add("PrbUsedUl");
87 prbThroughputMapping = new HashMap<>();
88 prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice");
89 prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice");
90 minPercentageChange = configuration.getMinPercentageChange();
94 * process the measurement data of an S-NSSAI
96 public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) {
97 Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true
98 : Configuration.getInstance().getConfigDbEnabled();
99 List<MeasurementObject> sample = null;
100 List<List<MeasurementObject>> samples = null;
101 Map<String, String> serviceDetails =null;
102 log.info("Network Functions {} of snssai {}", networkFunctions, snssai);
103 for (String nf : networkFunctions) {
104 log.debug("Average of samples for {}:", snssai);
105 samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples);
106 if (samples != null) {
107 sample = averageCalculator.findAverageOfSamples(samples);
108 addToMeasurementList(sample);
110 log.info("Not enough samples present for nf {}", nf);
114 log.info("snssai measurement list {}", snssaiMeasurementList);
115 Map<String, Map<String, Object>> ricConfiguration;
116 Map<String, Integer> sliceConfiguration;
117 if (isConfigDbEnabled) {
118 ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai);
119 ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai);
120 sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai);
121 serviceDetails = configDbService.fetchServiceDetails(snssai);
123 ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai);
124 ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai);
125 serviceDetails = aaiInterface.fetchServiceDetails(snssai);
126 sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai);
128 log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping);
129 log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration);
130 pmsToCompute.forEach(pm -> {
131 log.debug("processing for pm {}", pm);
132 sumOfPrbsAcrossCells(pm);
133 int sum = computeSum(pm);
134 computeThroughput(sliceConfiguration, sum, pm);
135 calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm));
137 updateConfiguration();
138 if (ricToThroughputMapping.size() > 0) {
139 AdditionalProperties<Map<String, List<Map<String, Integer>>>> addProps = new AdditionalProperties<>();
140 addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping));
141 policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails);
147 * change the RICConfig data format to be compatible with SDN-R
149 protected Map<String, List<Map<String, Integer>>> getChangedRIConfigFormat(
150 Map<String, Map<String, Integer>> ricToThroughputMapping) {
151 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
152 Map.Entry<String, Map<String, Integer>> entry = null;
153 List<Map<String, Integer>> ricConfigList = new ArrayList<>();
154 Map<String, List<Map<String, Integer>>> ricConfigData = new HashMap<>();
155 while (it.hasNext()) {
156 Map<String, Integer> newConfigMap = new HashMap<>();
158 newConfigMap = entry.getValue();
159 newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey()));
160 ricConfigList.add(newConfigMap);
162 ricConfigData.put("data", ricConfigList);
163 return ricConfigData;
167 * process the measurement data of an S-NSSAI
169 protected void updateConfiguration() {
170 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
171 Map.Entry<String, Map<String, Integer>> entry = null;
172 while (it.hasNext()) {
174 if (entry.getValue().size() == 0) {
180 private void addToMeasurementList(List<MeasurementObject> sample) {
181 snssaiMeasurementList.addAll(sample);
185 * Calculate the change in the configuration value and keep the configuration
186 * only if it is greater than a specific limit
188 protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) {
189 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
190 Map.Entry<String, Map<String, Integer>> entry = null;
193 while (it.hasNext()) {
195 existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm));
196 change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100;
197 if (change <= minPercentageChange) {
198 ricToThroughputMapping.get(entry.getKey()).remove(pm);
199 log.info("Removing pm data {} for RIC {}", pm, entry.getKey());
204 protected void sumOfPrbsAcrossCells(String pmName) {
205 ricToCellMapping.forEach((ric, cells) -> {
207 for (String cell : cells) {
208 int index = MeasurementObject.findIndex(cell, snssaiMeasurementList);
209 sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName);
211 if (ricToPrbsMapping.containsKey(ric)) {
212 ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs);
214 Map<String, Integer> pmToPrbMapping = new HashMap<>();
215 pmToPrbMapping.put(pmName, sumOfPrbs);
216 ricToPrbsMapping.put(ric, pmToPrbMapping);
219 log.info("PRBs sum computed for RIC {}", ricToPrbsMapping);
222 protected Integer computeSum(String pm) {
223 return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum);
226 protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) {
227 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator();
228 Map.Entry<String, Map<String, Integer>> entry = null;
229 Map<String, Integer> throughtputMap = null;
232 while (it.hasNext()) {
234 ric = entry.getKey();
235 value = Math.round(((float) entry.getValue().get(pm) / sum)
236 * (float) sliceConfiguration.get(prbThroughputMapping.get(pm)));
237 if (ricToThroughputMapping.containsKey(ric)) {
238 ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value);
240 throughtputMap = new HashMap<>();
241 throughtputMap.put(prbThroughputMapping.get(pm), value);
242 ricToThroughputMapping.put(ric, throughtputMap);
245 log.info("Throughput computed for RIC {}", ricToThroughputMapping);