blob: 7f984abebc54caf7627a1b9c6125a0ec17fffb6e [file] [log] [blame]
Madan Jampanic27b6b22016-02-05 11:36:31 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Madan Jampanic27b6b22016-02-05 11:36:31 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.net.statistic.impl;
18
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import com.google.common.base.MoreObjects;
20import com.google.common.base.Predicate;
21import com.google.common.collect.ImmutableSet;
Madan Jampanic27b6b22016-02-05 11:36:31 -080022import org.onosproject.net.ConnectPoint;
23import org.onosproject.net.Device;
24import org.onosproject.net.Port;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.device.DeviceService;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090027import org.onosproject.net.flow.DefaultFlowEntry;
Madan Jampanic27b6b22016-02-05 11:36:31 -080028import org.onosproject.net.flow.DefaultTypedFlowEntry;
29import org.onosproject.net.flow.FlowEntry;
30import org.onosproject.net.flow.FlowRule;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090031import org.onosproject.net.flow.StoredFlowEntry;
Madan Jampanic27b6b22016-02-05 11:36:31 -080032import org.onosproject.net.flow.TypedStoredFlowEntry;
33import org.onosproject.net.flow.instructions.Instruction;
34import org.onosproject.net.statistic.DefaultLoad;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090035import org.onosproject.net.statistic.FlowEntryWithLoad;
Madan Jampanic27b6b22016-02-05 11:36:31 -080036import org.onosproject.net.statistic.FlowStatisticService;
37import org.onosproject.net.statistic.Load;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090038import org.onosproject.net.statistic.PollInterval;
39import org.onosproject.net.statistic.StatisticStore;
Madan Jampanic27b6b22016-02-05 11:36:31 -080040import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;
41import org.onosproject.net.statistic.TypedFlowEntryWithLoad;
Ray Milkeya6957192017-06-01 13:04:16 -070042import org.onosproject.utils.Comparators;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070043import org.osgi.service.component.annotations.Activate;
44import org.osgi.service.component.annotations.Component;
45import org.osgi.service.component.annotations.Deactivate;
46import org.osgi.service.component.annotations.Reference;
47import org.osgi.service.component.annotations.ReferenceCardinality;
Madan Jampanic27b6b22016-02-05 11:36:31 -080048import org.slf4j.Logger;
49
Ray Milkeyd84f89b2018-08-17 14:54:17 -070050import java.util.ArrayList;
51import java.util.HashMap;
52import java.util.List;
53import java.util.Map;
54import java.util.Objects;
55import java.util.Set;
56import java.util.TreeMap;
57import java.util.stream.Collectors;
Madan Jampanic27b6b22016-02-05 11:36:31 -080058
59import static com.google.common.base.Preconditions.checkNotNull;
60import static org.onosproject.security.AppGuard.checkPermission;
Ray Milkeya6957192017-06-01 13:04:16 -070061import static org.onosproject.security.AppPermission.Type.STATISTIC_READ;
Madan Jampanic27b6b22016-02-05 11:36:31 -080062import static org.slf4j.LoggerFactory.getLogger;
Madan Jampanic27b6b22016-02-05 11:36:31 -080063
64/**
65 * Provides an implementation of the Flow Statistic Service.
66 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070067@Component(immediate = true, service = FlowStatisticService.class)
Madan Jampanic27b6b22016-02-05 11:36:31 -080068public class FlowStatisticManager implements FlowStatisticService {
69 private final Logger log = getLogger(getClass());
70
Ray Milkeyd84f89b2018-08-17 14:54:17 -070071 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090072 protected StatisticStore statisticStore;
Madan Jampanic27b6b22016-02-05 11:36:31 -080073
Ray Milkeyd84f89b2018-08-17 14:54:17 -070074 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampanic27b6b22016-02-05 11:36:31 -080075 protected DeviceService deviceService;
76
Madan Jampanic27b6b22016-02-05 11:36:31 -080077 @Activate
78 public void activate() {
Madan Jampanic27b6b22016-02-05 11:36:31 -080079 log.info("Started");
80 }
81
82 @Deactivate
83 public void deactivate() {
Madan Jampanic27b6b22016-02-05 11:36:31 -080084 log.info("Stopped");
85 }
86
87 @Override
88 public Map<ConnectPoint, SummaryFlowEntryWithLoad> loadSummary(Device device) {
89 checkPermission(STATISTIC_READ);
90
Sangsik Yoonb1b823f2016-05-16 18:55:39 +090091 Map<ConnectPoint, SummaryFlowEntryWithLoad> summaryLoad =
92 new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
Madan Jampanic27b6b22016-02-05 11:36:31 -080093
94 if (device == null) {
95 return summaryLoad;
96 }
97
98 List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
99
100 for (Port port : ports) {
101 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
102 SummaryFlowEntryWithLoad sfe = loadSummaryPortInternal(cp);
103 summaryLoad.put(cp, sfe);
104 }
105
106 return summaryLoad;
107 }
108
109 @Override
110 public SummaryFlowEntryWithLoad loadSummary(Device device, PortNumber pNumber) {
111 checkPermission(STATISTIC_READ);
112
113 ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
114 return loadSummaryPortInternal(cp);
115 }
116
117 @Override
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900118 public Map<ConnectPoint, List<FlowEntryWithLoad>> loadAllByType(Device device,
119 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800120 Instruction.Type instType) {
121 checkPermission(STATISTIC_READ);
122
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900123 Map<ConnectPoint, List<FlowEntryWithLoad>> allLoad =
124 new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800125
126 if (device == null) {
127 return allLoad;
128 }
129
130 List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
131
132 for (Port port : ports) {
133 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900134 List<FlowEntryWithLoad> fel = loadAllPortInternal(cp, liveType, instType);
135 allLoad.put(cp, fel);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800136 }
137
138 return allLoad;
139 }
140
141 @Override
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900142 public List<FlowEntryWithLoad> loadAllByType(Device device, PortNumber pNumber,
143 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800144 Instruction.Type instType) {
145 checkPermission(STATISTIC_READ);
146
147 ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
148 return loadAllPortInternal(cp, liveType, instType);
149 }
150
151 @Override
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900152 public Map<ConnectPoint, List<FlowEntryWithLoad>> loadTopnByType(Device device,
153 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800154 Instruction.Type instType,
155 int topn) {
156 checkPermission(STATISTIC_READ);
157
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900158 Map<ConnectPoint, List<FlowEntryWithLoad>> allLoad =
159 new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800160
161 if (device == null) {
162 return allLoad;
163 }
164
165 List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
166
167 for (Port port : ports) {
168 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900169 List<FlowEntryWithLoad> fel = loadTopnPortInternal(cp, liveType, instType, topn);
170 allLoad.put(cp, fel);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800171 }
172
173 return allLoad;
174 }
175
176 @Override
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900177 public List<FlowEntryWithLoad> loadTopnByType(Device device, PortNumber pNumber,
178 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800179 Instruction.Type instType,
180 int topn) {
181 checkPermission(STATISTIC_READ);
182
183 ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
184 return loadTopnPortInternal(cp, liveType, instType, topn);
185 }
186
187 private SummaryFlowEntryWithLoad loadSummaryPortInternal(ConnectPoint cp) {
188 checkPermission(STATISTIC_READ);
189
190 Set<FlowEntry> currentStats;
191 Set<FlowEntry> previousStats;
192
193 TypedStatistics typedStatistics;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900194 synchronized (statisticStore) {
195 currentStats = statisticStore.getCurrentStatistic(cp);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800196 if (currentStats == null) {
197 return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
198 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900199 previousStats = statisticStore.getPreviousStatistic(cp);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800200 if (previousStats == null) {
201 return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
202 }
203 // copy to local flow entry
204 typedStatistics = new TypedStatistics(currentStats, previousStats);
205
206 // Check for validity of this stats data
207 checkLoadValidity(currentStats, previousStats);
208 }
209
210 // current and previous set is not empty!
211 Set<FlowEntry> currentSet = typedStatistics.current();
212 Set<FlowEntry> previousSet = typedStatistics.previous();
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900213 PollInterval pollIntervalInstance = PollInterval.getInstance();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800214
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900215 // We assume that default pollInterval is flowPollFrequency in case adaptiveFlowSampling is true or false
216 Load totalLoad = new DefaultLoad(aggregateBytesSet(currentSet), aggregateBytesSet(previousSet),
217 pollIntervalInstance.getPollInterval());
218
219 Map<FlowRule, FlowEntry> currentMap;
220 Map<FlowRule, FlowEntry> previousMap;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800221
222 currentMap = typedStatistics.currentImmediate();
223 previousMap = typedStatistics.previousImmediate();
224 Load immediateLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900225 pollIntervalInstance.getPollInterval());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800226
227 currentMap = typedStatistics.currentShort();
228 previousMap = typedStatistics.previousShort();
229 Load shortLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900230 pollIntervalInstance.getPollInterval());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800231
232 currentMap = typedStatistics.currentMid();
233 previousMap = typedStatistics.previousMid();
234 Load midLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900235 pollIntervalInstance.getMidPollInterval());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800236
237 currentMap = typedStatistics.currentLong();
238 previousMap = typedStatistics.previousLong();
239 Load longLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900240 pollIntervalInstance.getLongPollInterval());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800241
242 currentMap = typedStatistics.currentUnknown();
243 previousMap = typedStatistics.previousUnknown();
244 Load unknownLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900245 pollIntervalInstance.getPollInterval());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800246
247 return new SummaryFlowEntryWithLoad(cp, totalLoad, immediateLoad, shortLoad, midLoad, longLoad, unknownLoad);
248 }
249
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900250 private List<FlowEntryWithLoad> loadAllPortInternal(ConnectPoint cp,
251 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800252 Instruction.Type instType) {
253 checkPermission(STATISTIC_READ);
254
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900255 List<FlowEntryWithLoad> retFel = new ArrayList<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800256
257 Set<FlowEntry> currentStats;
258 Set<FlowEntry> previousStats;
259
260 TypedStatistics typedStatistics;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900261 synchronized (statisticStore) {
262 currentStats = statisticStore.getCurrentStatistic(cp);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800263 if (currentStats == null) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900264 return retFel;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800265 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900266 previousStats = statisticStore.getPreviousStatistic(cp);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800267 if (previousStats == null) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900268 return retFel;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800269 }
270 // copy to local flow entry set
271 typedStatistics = new TypedStatistics(currentStats, previousStats);
272
273 // Check for validity of this stats data
274 checkLoadValidity(currentStats, previousStats);
275 }
276
277 // current and previous set is not empty!
Madan Jampanic27b6b22016-02-05 11:36:31 -0800278 boolean isAllInstType = (instType == null ? true : false); // null is all inst type
sivachidambaram subramaniandde26b62017-02-07 16:18:33 +0530279 boolean isAllLiveType = (liveType == null ? true : false); // null is all live type
Madan Jampanic27b6b22016-02-05 11:36:31 -0800280
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900281 Map<FlowRule, FlowEntry> currentMap;
282 Map<FlowRule, FlowEntry> previousMap;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800283
sivachidambaram subramaniandde26b62017-02-07 16:18:33 +0530284 if (isAllLiveType) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900285 currentMap = typedStatistics.currentAll();
286 previousMap = typedStatistics.previousAll();
287 } else {
288 switch (liveType) {
289 case IMMEDIATE:
290 currentMap = typedStatistics.currentImmediate();
291 previousMap = typedStatistics.previousImmediate();
292 break;
293 case SHORT:
294 currentMap = typedStatistics.currentShort();
295 previousMap = typedStatistics.previousShort();
296 break;
297 case MID:
298 currentMap = typedStatistics.currentMid();
299 previousMap = typedStatistics.previousMid();
300 break;
301 case LONG:
302 currentMap = typedStatistics.currentLong();
303 previousMap = typedStatistics.previousLong();
304 break;
305 case UNKNOWN:
306 currentMap = typedStatistics.currentUnknown();
307 previousMap = typedStatistics.previousUnknown();
308 break;
309 default:
310 currentMap = new HashMap<>();
311 previousMap = new HashMap<>();
312 break;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800313 }
314 }
315
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900316 return typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap, isAllInstType, instType);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800317 }
318
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900319 private List<FlowEntryWithLoad> typedFlowEntryLoadByInstInternal(ConnectPoint cp,
320 Map<FlowRule, FlowEntry> currentMap,
321 Map<FlowRule, FlowEntry> previousMap,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800322 boolean isAllInstType,
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900323 Instruction.Type instType) {
324 List<FlowEntryWithLoad> fel = new ArrayList<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800325
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900326 currentMap.values().forEach(fe -> {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800327 if (isAllInstType ||
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900328 fe.treatment().allInstructions().stream().
Madan Jampanic27b6b22016-02-05 11:36:31 -0800329 filter(i -> i.type() == instType).
330 findAny().isPresent()) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900331 long currentBytes = fe.bytes();
332 long previousBytes = previousMap.getOrDefault(fe, new DefaultFlowEntry(fe)).bytes();
333 long liveTypePollInterval = getLiveTypePollInterval(fe.liveType());
Madan Jampanic27b6b22016-02-05 11:36:31 -0800334 Load fLoad = new DefaultLoad(currentBytes, previousBytes, liveTypePollInterval);
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900335 fel.add(new FlowEntryWithLoad(cp, fe, fLoad));
Madan Jampanic27b6b22016-02-05 11:36:31 -0800336 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900337 });
Madan Jampanic27b6b22016-02-05 11:36:31 -0800338
339 return fel;
340 }
341
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900342 private List<FlowEntryWithLoad> loadTopnPortInternal(ConnectPoint cp,
343 FlowEntry.FlowLiveType liveType,
Madan Jampanic27b6b22016-02-05 11:36:31 -0800344 Instruction.Type instType,
345 int topn) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900346 List<FlowEntryWithLoad> fel = loadAllPortInternal(cp, liveType, instType);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800347
348 // Sort with descending order of load
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900349 List<FlowEntryWithLoad> retFel =
350 fel.stream().sorted(Comparators.FLOWENTRY_WITHLOAD_COMPARATOR).
Madan Jampanic27b6b22016-02-05 11:36:31 -0800351 limit(topn).collect(Collectors.toList());
352
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900353 return retFel;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800354 }
355
356 private long aggregateBytesSet(Set<FlowEntry> setFE) {
357 return setFE.stream().mapToLong(FlowEntry::bytes).sum();
358 }
359
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900360 private long aggregateBytesMap(Map<FlowRule, FlowEntry> mapFE) {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800361 return mapFE.values().stream().mapToLong(FlowEntry::bytes).sum();
362 }
363
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900364 private long getLiveTypePollInterval(FlowEntry.FlowLiveType liveType) {
365 // returns the flow live type poll interval value
366 PollInterval pollIntervalInstance = PollInterval.getInstance();
367
368 switch (liveType) {
369 case LONG:
370 return pollIntervalInstance.getLongPollInterval();
371 case MID:
372 return pollIntervalInstance.getMidPollInterval();
373 case SHORT:
374 case IMMEDIATE:
375 default: // UNKNOWN
376 return pollIntervalInstance.getPollInterval();
377 }
378 }
379
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900380 private TypedStoredFlowEntry.FlowLiveType toTypedStoredFlowEntryLiveType(FlowEntry.FlowLiveType liveType) {
381 if (liveType == null) {
382 return null;
383 }
384
385 // convert TypedStoredFlowEntry flow live type to FlowEntry one
386 switch (liveType) {
387 case IMMEDIATE:
388 return TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW;
389 case SHORT:
390 return TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW;
391 case MID:
392 return TypedStoredFlowEntry.FlowLiveType.MID_FLOW;
393 case LONG:
394 return TypedStoredFlowEntry.FlowLiveType.LONG_FLOW;
395 default:
396 return TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW;
397 }
398 }
399
400 private Map<ConnectPoint, List<TypedFlowEntryWithLoad>> toFlowEntryWithLoadMap(
401 Map<ConnectPoint, List<FlowEntryWithLoad>> loadMap) {
402 // convert FlowEntryWithLoad list to TypedFlowEntryWithLoad list
403 Map<ConnectPoint, List<TypedFlowEntryWithLoad>> allLoad =
404 new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
405
406 loadMap.forEach((k, v) -> {
407 List<TypedFlowEntryWithLoad> tfelList =
408 toFlowEntryWithLoad(v);
409 allLoad.put(k, tfelList);
410 });
411
412 return allLoad;
413 }
414
415 private List<TypedFlowEntryWithLoad> toFlowEntryWithLoad(List<FlowEntryWithLoad> loadList) {
416 // convert FlowEntryWithLoad list to TypedFlowEntryWithLoad list
417 List<TypedFlowEntryWithLoad> tfelList = new ArrayList<>();
418 loadList.forEach(fel -> {
419 StoredFlowEntry sfe = fel.storedFlowEntry();
420 TypedStoredFlowEntry.FlowLiveType liveType = toTypedStoredFlowEntryLiveType(sfe.liveType());
421 TypedStoredFlowEntry tfe = new DefaultTypedFlowEntry(sfe, liveType);
422 TypedFlowEntryWithLoad tfel = new TypedFlowEntryWithLoad(fel.connectPoint(), tfe, fel.load());
423 tfelList.add(tfel);
424 });
425
426 return tfelList;
427 }
428
Madan Jampanic27b6b22016-02-05 11:36:31 -0800429 /**
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900430 * Internal data class holding two set of flow entries included flow liveType.
Madan Jampanic27b6b22016-02-05 11:36:31 -0800431 */
432 private static class TypedStatistics {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900433 private final ImmutableSet<FlowEntry> current;
434 private final ImmutableSet<FlowEntry> previous;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800435
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900436 private final Map<FlowRule, FlowEntry> currentAll = new HashMap<>();
437 private final Map<FlowRule, FlowEntry> previousAll = new HashMap<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800438
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900439 private final Map<FlowRule, FlowEntry> currentImmediate = new HashMap<>();
440 private final Map<FlowRule, FlowEntry> previousImmediate = new HashMap<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800441
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900442 private final Map<FlowRule, FlowEntry> currentShort = new HashMap<>();
443 private final Map<FlowRule, FlowEntry> previousShort = new HashMap<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800444
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900445 private final Map<FlowRule, FlowEntry> currentMid = new HashMap<>();
446 private final Map<FlowRule, FlowEntry> previousMid = new HashMap<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800447
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900448 private final Map<FlowRule, FlowEntry> currentLong = new HashMap<>();
449 private final Map<FlowRule, FlowEntry> previousLong = new HashMap<>();
450
451 private final Map<FlowRule, FlowEntry> currentUnknown = new HashMap<>();
452 private final Map<FlowRule, FlowEntry> previousUnknown = new HashMap<>();
Madan Jampanic27b6b22016-02-05 11:36:31 -0800453
454 public TypedStatistics(Set<FlowEntry> current, Set<FlowEntry> previous) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900455 this.current = ImmutableSet.copyOf(checkNotNull(current));
456 this.previous = ImmutableSet.copyOf(checkNotNull(previous));
Madan Jampanic27b6b22016-02-05 11:36:31 -0800457
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900458 current.forEach(fe -> {
459 switch (fe.liveType()) {
460 case IMMEDIATE:
461 currentImmediate.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800462 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900463 case SHORT:
464 currentShort.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800465 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900466 case MID:
467 currentMid.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800468 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900469 case LONG:
470 currentLong.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800471 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900472 default: // unknown
473 currentUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800474 break;
475 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900476 currentAll.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800477 });
478
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900479 previous.forEach(fe -> {
480 switch (fe.liveType()) {
481 case IMMEDIATE:
Madan Jampanic27b6b22016-02-05 11:36:31 -0800482 if (currentImmediate.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900483 previousImmediate.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800484 } else if (currentShort.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900485 previousShort.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800486 } else if (currentMid.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900487 previousMid.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800488 } else if (currentLong.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900489 previousLong.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800490 } else {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900491 previousUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800492 }
493 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900494 case SHORT:
Madan Jampanic27b6b22016-02-05 11:36:31 -0800495 if (currentShort.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900496 previousShort.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800497 } else if (currentMid.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900498 previousMid.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800499 } else if (currentLong.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900500 previousLong.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800501 } else {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900502 previousUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800503 }
504 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900505 case MID:
Madan Jampanic27b6b22016-02-05 11:36:31 -0800506 if (currentMid.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900507 previousMid.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800508 } else if (currentLong.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900509 previousLong.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800510 } else {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900511 previousUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800512 }
513 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900514 case LONG:
Madan Jampanic27b6b22016-02-05 11:36:31 -0800515 if (currentLong.containsKey(fe)) {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900516 previousLong.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800517 } else {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900518 previousUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800519 }
520 break;
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900521 default: // unknown
522 previousUnknown.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800523 break;
524 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900525 previousAll.put(fe, fe);
Madan Jampanic27b6b22016-02-05 11:36:31 -0800526 });
527 }
528
529 /**
530 * Returns flow entries as the current value.
531 *
532 * @return flow entries as the current value
533 */
534 public ImmutableSet<FlowEntry> current() {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900535 return current;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800536 }
537
538 /**
539 * Returns flow entries as the previous value.
540 *
541 * @return flow entries as the previous value
542 */
543 public ImmutableSet<FlowEntry> previous() {
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900544 return previous;
545 }
546
547 public Map<FlowRule, FlowEntry> currentAll() {
548 return currentAll;
549 }
550
551 public Map<FlowRule, FlowEntry> previousAll() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800552 return previousAll;
553 }
554
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900555 public Map<FlowRule, FlowEntry> currentImmediate() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800556 return currentImmediate;
557 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900558 public Map<FlowRule, FlowEntry> previousImmediate() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800559 return previousImmediate;
560 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900561 public Map<FlowRule, FlowEntry> currentShort() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800562 return currentShort;
563 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900564 public Map<FlowRule, FlowEntry> previousShort() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800565 return previousShort;
566 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900567 public Map<FlowRule, FlowEntry> currentMid() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800568 return currentMid;
569 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900570 public Map<FlowRule, FlowEntry> previousMid() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800571 return previousMid;
572 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900573 public Map<FlowRule, FlowEntry> currentLong() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800574 return currentLong;
575 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900576 public Map<FlowRule, FlowEntry> previousLong() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800577 return previousLong;
578 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900579 public Map<FlowRule, FlowEntry> currentUnknown() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800580 return currentUnknown;
581 }
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900582 public Map<FlowRule, FlowEntry> previousUnknown() {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800583 return previousUnknown;
584 }
585
586 /**
587 * Validates values are not empty.
588 *
589 * @return false if either of the sets is empty. Otherwise, true.
590 */
591 public boolean isValid() {
592 return !(currentAll.isEmpty() || previousAll.isEmpty());
593 }
594
595 @Override
596 public int hashCode() {
597 return Objects.hash(currentAll, previousAll);
598 }
599
600 @Override
601 public boolean equals(Object obj) {
602 if (this == obj) {
603 return true;
604 }
605 if (!(obj instanceof TypedStatistics)) {
606 return false;
607 }
608 final TypedStatistics other = (TypedStatistics) obj;
609 return Objects.equals(this.currentAll, other.currentAll) &&
610 Objects.equals(this.previousAll, other.previousAll);
611 }
612
613 @Override
614 public String toString() {
615 return MoreObjects.toStringHelper(this)
616 .add("current", currentAll)
617 .add("previous", previousAll)
618 .toString();
619 }
620 }
621
622 private void checkLoadValidity(Set<FlowEntry> current, Set<FlowEntry> previous) {
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700623 current.forEach(c -> {
Madan Jampanic27b6b22016-02-05 11:36:31 -0800624 FlowEntry f = previous.stream().filter(p -> c.equals(p)).
625 findAny().orElse(null);
626 if (f != null && c.bytes() < f.bytes()) {
627 log.debug("FlowStatisticManager:checkLoadValidity():" +
628 "Error: " + c + " :Previous bytes=" + f.bytes() +
629 " is larger than current bytes=" + c.bytes() + " !!!");
630 }
631 });
632
633 }
634
635 /**
636 * Creates a predicate that checks the instruction type of a flow entry is the same as
637 * the specified instruction type.
638 *
639 * @param instType instruction type to be checked
640 * @return predicate
641 */
642 private static Predicate<FlowEntry> hasInstructionType(Instruction.Type instType) {
643 return new Predicate<FlowEntry>() {
644 @Override
645 public boolean apply(FlowEntry flowEntry) {
646 List<Instruction> allInstructions = flowEntry.treatment().allInstructions();
647
648 return allInstructions.stream().filter(i -> i.type() == instType).findAny().isPresent();
649 }
650 };
651 }
652
653 /**
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900654 * Creates a predicate that checks the flow type of a flow entry is the same as
655 * the specified live type.
656 *
657 * @param liveType flow live type to be checked
658 * @return predicate
Madan Jampanic27b6b22016-02-05 11:36:31 -0800659 */
Sangsik Yoonb1b823f2016-05-16 18:55:39 +0900660 private static Predicate<FlowEntry> hasLiveType(FlowEntry.FlowLiveType liveType) {
661 return flowEntry -> flowEntry.liveType() == liveType;
Madan Jampanic27b6b22016-02-05 11:36:31 -0800662 }
663}