blob: 421227345b608cdd4b248ca99a0a756c9376f7f6 [file] [log] [blame]
Thomas Vachuska7c27ad72014-11-14 16:20:10 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska7c27ad72014-11-14 16:20:10 -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 */
Thomas Vachuskac97aa612015-06-23 16:00:18 -070016package org.onosproject.store.trivial;
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080017
18import com.google.common.collect.Sets;
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.flow.FlowEntry;
26import org.onosproject.net.flow.FlowRule;
27import org.onosproject.net.flow.instructions.Instruction;
28import org.onosproject.net.flow.instructions.Instructions;
29import org.onosproject.net.statistic.StatisticStore;
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080030import org.slf4j.Logger;
31
alshabib9c57bdd2014-11-28 19:14:06 -050032import java.util.Collections;
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080033import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
36import java.util.concurrent.ConcurrentHashMap;
37import java.util.concurrent.atomic.AtomicInteger;
38
39import static org.slf4j.LoggerFactory.getLogger;
40
41
42/**
43 * Maintains statistics using RPC calls to collect stats from remote instances
44 * on demand.
45 */
46@Component(immediate = true)
47@Service
48public class SimpleStatisticStore implements StatisticStore {
49
50 private final Logger log = getLogger(getClass());
51
52 private Map<ConnectPoint, InternalStatisticRepresentation>
53 representations = new ConcurrentHashMap<>();
54
55 private Map<ConnectPoint, Set<FlowEntry>> previous = new ConcurrentHashMap<>();
56 private Map<ConnectPoint, Set<FlowEntry>> current = new ConcurrentHashMap<>();
57
58 @Activate
59 public void activate() {
60 log.info("Started");
61 }
62
63 @Deactivate
64 public void deactivate() {
65 log.info("Stopped");
66 }
67
68 @Override
69 public void prepareForStatistics(FlowRule rule) {
70 ConnectPoint cp = buildConnectPoint(rule);
71 if (cp == null) {
72 return;
73 }
74 InternalStatisticRepresentation rep;
75 synchronized (representations) {
76 rep = getOrCreateRepresentation(cp);
77 }
78 rep.prepare();
79 }
80
81 @Override
82 public synchronized void removeFromStatistics(FlowRule rule) {
83 ConnectPoint cp = buildConnectPoint(rule);
84 if (cp == null) {
85 return;
86 }
87 InternalStatisticRepresentation rep = representations.get(cp);
alshabib9c57bdd2014-11-28 19:14:06 -050088 if (rep != null && rep.remove(rule)) {
89 updatePublishedStats(cp, Collections.emptySet());
Thomas Vachuska7c27ad72014-11-14 16:20:10 -080090 }
91 Set<FlowEntry> values = current.get(cp);
92 if (values != null) {
93 values.remove(rule);
94 }
95 values = previous.get(cp);
96 if (values != null) {
97 values.remove(rule);
98 }
99
100 }
101
102 @Override
103 public void addOrUpdateStatistic(FlowEntry rule) {
104 ConnectPoint cp = buildConnectPoint(rule);
105 if (cp == null) {
106 return;
107 }
108 InternalStatisticRepresentation rep = representations.get(cp);
109 if (rep != null && rep.submit(rule)) {
110 updatePublishedStats(cp, rep.get());
111 }
112 }
113
114 private synchronized void updatePublishedStats(ConnectPoint cp,
115 Set<FlowEntry> flowEntries) {
116 Set<FlowEntry> curr = current.get(cp);
117 if (curr == null) {
118 curr = new HashSet<>();
119 }
120 previous.put(cp, curr);
121 current.put(cp, flowEntries);
122
123 }
124
125 @Override
126 public Set<FlowEntry> getCurrentStatistic(ConnectPoint connectPoint) {
127 return getCurrentStatisticInternal(connectPoint);
128 }
129
130 private synchronized Set<FlowEntry> getCurrentStatisticInternal(ConnectPoint connectPoint) {
131 return current.get(connectPoint);
132 }
133
134 @Override
135 public Set<FlowEntry> getPreviousStatistic(ConnectPoint connectPoint) {
136 return getPreviousStatisticInternal(connectPoint);
137 }
138
139 private synchronized Set<FlowEntry> getPreviousStatisticInternal(ConnectPoint connectPoint) {
140 return previous.get(connectPoint);
141 }
142
143 private InternalStatisticRepresentation getOrCreateRepresentation(ConnectPoint cp) {
144
145 if (representations.containsKey(cp)) {
146 return representations.get(cp);
147 } else {
148 InternalStatisticRepresentation rep = new InternalStatisticRepresentation();
149 representations.put(cp, rep);
150 return rep;
151 }
152
153 }
154
155 private ConnectPoint buildConnectPoint(FlowRule rule) {
156 PortNumber port = getOutput(rule);
Jonathan Hart7baba072015-02-23 14:27:59 -0800157
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800158 if (port == null) {
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800159 return null;
160 }
161 ConnectPoint cp = new ConnectPoint(rule.deviceId(), port);
162 return cp;
163 }
164
165 private PortNumber getOutput(FlowRule rule) {
Ray Milkey42507352015-03-20 15:16:10 -0700166 for (Instruction i : rule.treatment().immediate()) {
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800167 if (i.type() == Instruction.Type.OUTPUT) {
168 Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
169 return out.port();
170 }
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800171 }
172 return null;
173 }
174
175 private class InternalStatisticRepresentation {
176
177 private final AtomicInteger counter = new AtomicInteger(0);
178 private final Set<FlowEntry> rules = new HashSet<>();
179
180 public void prepare() {
181 counter.incrementAndGet();
182 }
183
alshabib9c57bdd2014-11-28 19:14:06 -0500184 public synchronized boolean remove(FlowRule rule) {
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800185 rules.remove(rule);
alshabib9c57bdd2014-11-28 19:14:06 -0500186 return counter.decrementAndGet() == 0;
Thomas Vachuska7c27ad72014-11-14 16:20:10 -0800187 }
188
189 public synchronized boolean submit(FlowEntry rule) {
190 if (rules.contains(rule)) {
191 rules.remove(rule);
192 }
193 rules.add(rule);
194 if (counter.get() == 0) {
195 return true;
196 } else {
197 return counter.decrementAndGet() == 0;
198 }
199 }
200
201 public synchronized Set<FlowEntry> get() {
202 counter.set(rules.size());
203 return Sets.newHashSet(rules);
204 }
205
206 }
207
208}