alshabib

functional stats service

Change-Id: I90de3aa5d7721db8ef6a154e122af8b446243f60
1 +package org.onlab.onos.net.statistic;
2 +
3 +import org.onlab.onos.net.flow.FlowRuleProvider;
4 +
5 +/**
6 + * Implementation of a load.
7 + */
8 +public class DefaultLoad implements Load {
9 +
10 + private final boolean isValid;
11 + private final long current;
12 + private final long previous;
13 + private final long time;
14 +
15 + /**
16 + * Creates an invalid load.
17 + */
18 + public DefaultLoad() {
19 + this.isValid = false;
20 + this.time = System.currentTimeMillis();
21 + this.current = -1;
22 + this.previous = -1;
23 + }
24 +
25 + /**
26 + * Creates a load value from the parameters.
27 + * @param current the current value
28 + * @param previous the previous value
29 + */
30 + public DefaultLoad(long current, long previous) {
31 + this.current = current;
32 + this.previous = previous;
33 + this.time = System.currentTimeMillis();
34 + this.isValid = true;
35 + }
36 +
37 + @Override
38 + public long rate() {
39 + return (current - previous) / FlowRuleProvider.POLL_INTERVAL;
40 + }
41 +
42 + @Override
43 + public long latest() {
44 + return current;
45 + }
46 +
47 + @Override
48 + public boolean isValid() {
49 + return isValid;
50 + }
51 +
52 + @Override
53 + public long time() {
54 + return time;
55 + }
56 +}
...@@ -6,15 +6,27 @@ package org.onlab.onos.net.statistic; ...@@ -6,15 +6,27 @@ package org.onlab.onos.net.statistic;
6 public interface Load { 6 public interface Load {
7 7
8 /** 8 /**
9 - * Obtain the current observed rate on a link. 9 + * Obtain the current observed rate (in bytes/s) on a link.
10 * @return long value 10 * @return long value
11 */ 11 */
12 long rate(); 12 long rate();
13 13
14 /** 14 /**
15 - * Obtain the latest counter viewed on that link. 15 + * Obtain the latest bytes counter viewed on that link.
16 * @return long value 16 * @return long value
17 */ 17 */
18 long latest(); 18 long latest();
19 19
20 + /**
21 + * Indicates whether this load was built on valid values.
22 + * @return boolean
23 + */
24 + boolean isValid();
25 +
26 + /**
27 + * Returns when this value was seen.
28 + * @return epoch time
29 + */
30 + long time();
31 +
20 } 32 }
......
...@@ -108,6 +108,9 @@ public class FlowRuleManager ...@@ -108,6 +108,9 @@ public class FlowRuleManager
108 if (local) { 108 if (local) {
109 // TODO: aggregate all local rules and push down once? 109 // TODO: aggregate all local rules and push down once?
110 applyFlowRulesToProviders(f); 110 applyFlowRulesToProviders(f);
111 + eventDispatcher.post(
112 + new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, f));
113 +
111 } 114 }
112 } 115 }
113 } 116 }
...@@ -136,6 +139,8 @@ public class FlowRuleManager ...@@ -136,6 +139,8 @@ public class FlowRuleManager
136 if (local) { 139 if (local) {
137 // TODO: aggregate all local rules and push down once? 140 // TODO: aggregate all local rules and push down once?
138 removeFlowRulesFromProviders(f); 141 removeFlowRulesFromProviders(f);
142 + eventDispatcher.post(
143 + new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, f));
139 } 144 }
140 } 145 }
141 } 146 }
......
...@@ -68,7 +68,9 @@ implements PacketService, PacketProviderRegistry { ...@@ -68,7 +68,9 @@ implements PacketService, PacketProviderRegistry {
68 checkNotNull(packet, "Packet cannot be null"); 68 checkNotNull(packet, "Packet cannot be null");
69 final Device device = deviceService.getDevice(packet.sendThrough()); 69 final Device device = deviceService.getDevice(packet.sendThrough());
70 final PacketProvider packetProvider = getProvider(device.providerId()); 70 final PacketProvider packetProvider = getProvider(device.providerId());
71 - packetProvider.emit(packet); 71 + if (packetProvider != null) {
72 + packetProvider.emit(packet);
73 + }
72 } 74 }
73 75
74 @Override 76 @Override
......
...@@ -10,15 +10,19 @@ import org.onlab.onos.net.ConnectPoint; ...@@ -10,15 +10,19 @@ import org.onlab.onos.net.ConnectPoint;
10 import org.onlab.onos.net.Link; 10 import org.onlab.onos.net.Link;
11 import org.onlab.onos.net.Path; 11 import org.onlab.onos.net.Path;
12 12
13 +import org.onlab.onos.net.flow.FlowEntry;
13 import org.onlab.onos.net.flow.FlowRule; 14 import org.onlab.onos.net.flow.FlowRule;
14 import org.onlab.onos.net.flow.FlowRuleEvent; 15 import org.onlab.onos.net.flow.FlowRuleEvent;
15 import org.onlab.onos.net.flow.FlowRuleListener; 16 import org.onlab.onos.net.flow.FlowRuleListener;
16 import org.onlab.onos.net.flow.FlowRuleService; 17 import org.onlab.onos.net.flow.FlowRuleService;
18 +import org.onlab.onos.net.statistic.DefaultLoad;
17 import org.onlab.onos.net.statistic.Load; 19 import org.onlab.onos.net.statistic.Load;
18 import org.onlab.onos.net.statistic.StatisticService; 20 import org.onlab.onos.net.statistic.StatisticService;
19 import org.onlab.onos.net.statistic.StatisticStore; 21 import org.onlab.onos.net.statistic.StatisticStore;
20 import org.slf4j.Logger; 22 import org.slf4j.Logger;
21 23
24 +import java.util.Set;
25 +
22 import static org.slf4j.LoggerFactory.getLogger; 26 import static org.slf4j.LoggerFactory.getLogger;
23 27
24 /** 28 /**
...@@ -54,12 +58,12 @@ public class StatisticManager implements StatisticService { ...@@ -54,12 +58,12 @@ public class StatisticManager implements StatisticService {
54 58
55 @Override 59 @Override
56 public Load load(Link link) { 60 public Load load(Link link) {
57 - return null; 61 + return load(link.src());
58 } 62 }
59 63
60 @Override 64 @Override
61 public Load load(ConnectPoint connectPoint) { 65 public Load load(ConnectPoint connectPoint) {
62 - return null; 66 + return loadInternal(connectPoint);
63 } 67 }
64 68
65 @Override 69 @Override
...@@ -77,6 +81,35 @@ public class StatisticManager implements StatisticService { ...@@ -77,6 +81,35 @@ public class StatisticManager implements StatisticService {
77 return null; 81 return null;
78 } 82 }
79 83
84 + private Load loadInternal(ConnectPoint connectPoint) {
85 + Set<FlowEntry> current;
86 + Set<FlowEntry> previous;
87 + synchronized (statisticStore) {
88 + current = statisticStore.getCurrentStatistic(connectPoint);
89 + previous = statisticStore.getPreviousStatistic(connectPoint);
90 + }
91 + if (current == null || previous == null) {
92 + return new DefaultLoad();
93 + }
94 + long currentAggregate = aggregate(current);
95 + long previousAggregate = aggregate(previous);
96 +
97 + return new DefaultLoad(currentAggregate, previousAggregate);
98 + }
99 +
100 + /**
101 + * Aggregates a set of values.
102 + * @param values the values to aggregate
103 + * @return a long value
104 + */
105 + private long aggregate(Set<FlowEntry> values) {
106 + long sum = 0;
107 + for (FlowEntry f : values) {
108 + sum += f.bytes();
109 + }
110 + return sum;
111 + }
112 +
80 /** 113 /**
81 * Internal flow rule event listener. 114 * Internal flow rule event listener.
82 */ 115 */
...@@ -84,22 +117,29 @@ public class StatisticManager implements StatisticService { ...@@ -84,22 +117,29 @@ public class StatisticManager implements StatisticService {
84 117
85 @Override 118 @Override
86 public void event(FlowRuleEvent event) { 119 public void event(FlowRuleEvent event) {
87 -// FlowRule rule = event.subject(); 120 + FlowRule rule = event.subject();
88 -// switch (event.type()) { 121 + switch (event.type()) {
89 -// case RULE_ADDED: 122 + case RULE_ADDED:
90 -// case RULE_UPDATED: 123 + case RULE_UPDATED:
91 -// if (rule instanceof FlowEntry) { 124 + if (rule instanceof FlowEntry) {
92 -// statisticStore.addOrUpdateStatistic((FlowEntry) rule); 125 + statisticStore.addOrUpdateStatistic((FlowEntry) rule);
93 -// } 126 + } else {
94 -// break; 127 + log.warn("IT AIN'T A FLOWENTRY");
95 -// case RULE_ADD_REQUESTED: 128 + }
96 -// statisticStore.prepareForStatistics(rule); 129 + break;
97 -// break; 130 + case RULE_ADD_REQUESTED:
98 -// case RULE_REMOVE_REQUESTED: 131 + log.info("Preparing for stats");
99 -// case RULE_REMOVED: 132 + statisticStore.prepareForStatistics(rule);
100 -// statisticStore.removeFromStatistics(rule); 133 + break;
101 -// break; 134 + case RULE_REMOVE_REQUESTED:
102 -// } 135 + log.info("Removing stats");
136 + statisticStore.removeFromStatistics(rule);
137 + break;
138 + case RULE_REMOVED:
139 + break;
140 + default:
141 + log.warn("Unknown flow rule event {}", event);
142 + }
103 } 143 }
104 } 144 }
105 145
......
...@@ -6,9 +6,7 @@ import static org.junit.Assert.assertFalse; ...@@ -6,9 +6,7 @@ import static org.junit.Assert.assertFalse;
6 import static org.junit.Assert.assertNotNull; 6 import static org.junit.Assert.assertNotNull;
7 import static org.junit.Assert.assertTrue; 7 import static org.junit.Assert.assertTrue;
8 import static org.junit.Assert.fail; 8 import static org.junit.Assert.fail;
9 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED; 9 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
10 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
11 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
12 10
13 import java.util.ArrayList; 11 import java.util.ArrayList;
14 import java.util.Collections; 12 import java.util.Collections;
...@@ -164,7 +162,8 @@ public class FlowRuleManagerTest { ...@@ -164,7 +162,8 @@ public class FlowRuleManagerTest {
164 assertEquals("2 rules should exist", 2, flowCount()); 162 assertEquals("2 rules should exist", 2, flowCount());
165 163
166 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2)); 164 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
167 - validateEvents(RULE_ADDED, RULE_ADDED); 165 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
166 + RULE_ADDED, RULE_ADDED);
168 167
169 addFlowRule(1); 168 addFlowRule(1);
170 assertEquals("should still be 2 rules", 2, flowCount()); 169 assertEquals("should still be 2 rules", 2, flowCount());
...@@ -217,11 +216,12 @@ public class FlowRuleManagerTest { ...@@ -217,11 +216,12 @@ public class FlowRuleManagerTest {
217 FlowEntry fe2 = new DefaultFlowEntry(f2); 216 FlowEntry fe2 = new DefaultFlowEntry(f2);
218 FlowEntry fe3 = new DefaultFlowEntry(f3); 217 FlowEntry fe3 = new DefaultFlowEntry(f3);
219 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3)); 218 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
220 - validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED); 219 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
220 + RULE_ADDED, RULE_ADDED, RULE_ADDED);
221 221
222 mgr.removeFlowRules(f1, f2); 222 mgr.removeFlowRules(f1, f2);
223 //removing from north, so no events generated 223 //removing from north, so no events generated
224 - validateEvents(); 224 + validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
225 assertEquals("3 rule should exist", 3, flowCount()); 225 assertEquals("3 rule should exist", 3, flowCount());
226 assertTrue("Entries should be pending remove.", 226 assertTrue("Entries should be pending remove.",
227 validateState(ImmutableMap.of( 227 validateState(ImmutableMap.of(
...@@ -243,7 +243,8 @@ public class FlowRuleManagerTest { ...@@ -243,7 +243,8 @@ public class FlowRuleManagerTest {
243 service.removeFlowRules(f1); 243 service.removeFlowRules(f1);
244 fe1.setState(FlowEntryState.REMOVED); 244 fe1.setState(FlowEntryState.REMOVED);
245 providerService.flowRemoved(fe1); 245 providerService.flowRemoved(fe1);
246 - validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED); 246 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
247 + RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
247 248
248 providerService.flowRemoved(fe1); 249 providerService.flowRemoved(fe1);
249 validateEvents(); 250 validateEvents();
...@@ -252,7 +253,7 @@ public class FlowRuleManagerTest { ...@@ -252,7 +253,7 @@ public class FlowRuleManagerTest {
252 FlowEntry fe3 = new DefaultFlowEntry(f3); 253 FlowEntry fe3 = new DefaultFlowEntry(f3);
253 service.applyFlowRules(f3); 254 service.applyFlowRules(f3);
254 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3)); 255 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
255 - validateEvents(RULE_ADDED); 256 + validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
256 257
257 providerService.flowRemoved(fe3); 258 providerService.flowRemoved(fe3);
258 validateEvents(); 259 validateEvents();
...@@ -281,7 +282,8 @@ public class FlowRuleManagerTest { ...@@ -281,7 +282,8 @@ public class FlowRuleManagerTest {
281 f2, FlowEntryState.ADDED, 282 f2, FlowEntryState.ADDED,
282 f3, FlowEntryState.PENDING_ADD))); 283 f3, FlowEntryState.PENDING_ADD)));
283 284
284 - validateEvents(RULE_ADDED, RULE_ADDED); 285 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
286 + RULE_ADDED, RULE_ADDED);
285 } 287 }
286 288
287 @Test 289 @Test
...@@ -301,7 +303,7 @@ public class FlowRuleManagerTest { ...@@ -301,7 +303,7 @@ public class FlowRuleManagerTest {
301 303
302 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3)); 304 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
303 305
304 - validateEvents(RULE_ADDED, RULE_ADDED); 306 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
305 307
306 } 308 }
307 309
...@@ -326,7 +328,8 @@ public class FlowRuleManagerTest { ...@@ -326,7 +328,8 @@ public class FlowRuleManagerTest {
326 328
327 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2)); 329 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
328 330
329 - validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED); 331 + validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
332 + RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
330 333
331 } 334 }
332 335
......
1 +package org.onlab.onos.store.statistic.impl;
2 +
3 +import static org.onlab.onos.store.statistic.impl.StatisticStoreMessageSubjects.*;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import com.google.common.collect.ImmutableSet;
7 +import org.apache.felix.scr.annotations.Activate;
8 +import org.apache.felix.scr.annotations.Component;
9 +import org.apache.felix.scr.annotations.Deactivate;
10 +import org.apache.felix.scr.annotations.Reference;
11 +import org.apache.felix.scr.annotations.ReferenceCardinality;
12 +import org.apache.felix.scr.annotations.Service;
13 +import org.onlab.onos.cluster.ClusterService;
14 +import org.onlab.onos.net.ConnectPoint;
15 +import org.onlab.onos.net.PortNumber;
16 +import org.onlab.onos.net.flow.FlowEntry;
17 +import org.onlab.onos.net.flow.FlowRule;
18 +import org.onlab.onos.net.flow.instructions.Instruction;
19 +import org.onlab.onos.net.flow.instructions.Instructions;
20 +import org.onlab.onos.net.statistic.StatisticStore;
21 +import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
22 +import org.onlab.onos.store.cluster.messaging.ClusterMessage;
23 +import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
24 +import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse;
25 +import org.onlab.onos.store.flow.ReplicaInfo;
26 +import org.onlab.onos.store.flow.ReplicaInfoService;
27 +import org.onlab.onos.store.serializers.KryoNamespaces;
28 +import org.onlab.onos.store.serializers.KryoSerializer;
29 +import org.slf4j.Logger;
30 +
31 +
32 +import java.io.IOException;
33 +import java.util.HashSet;
34 +import java.util.Map;
35 +import java.util.Set;
36 +import java.util.concurrent.ConcurrentHashMap;
37 +import java.util.concurrent.TimeUnit;
38 +import java.util.concurrent.TimeoutException;
39 +import java.util.concurrent.atomic.AtomicInteger;
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
48 +public class DistributedStatisticStore implements StatisticStore {
49 +
50 + private final Logger log = getLogger(getClass());
51 +
52 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 + private ReplicaInfoService replicaInfoManager;
54 +
55 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 + private ClusterCommunicationService clusterCommunicator;
57 +
58 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 + private ClusterService clusterService;
60 +
61 + private Map<ConnectPoint, InternalStatisticRepresentation> representations =
62 + new ConcurrentHashMap<>();
63 +
64 + private Map<ConnectPoint, Set<FlowEntry>> previous =
65 + new ConcurrentHashMap<>();
66 +
67 + private Map<ConnectPoint, Set<FlowEntry>> current =
68 + new ConcurrentHashMap<>();
69 +
70 + protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
71 + @Override
72 + protected void setupKryoPool() {
73 + serializerPool = KryoNamespaces.API.newBuilder()
74 + .build()
75 + .populate(1);
76 + }
77 + };;
78 +
79 + private static final long STATISTIC_STORE_TIMEOUT_MILLIS = 3000;
80 +
81 + @Activate
82 + public void activate() {
83 + clusterCommunicator.addSubscriber(GET_CURRENT, new ClusterMessageHandler() {
84 +
85 + @Override
86 + public void handle(ClusterMessage message) {
87 + ConnectPoint cp = SERIALIZER.decode(message.payload());
88 + try {
89 + message.respond(SERIALIZER.encode(getCurrentStatisticInternal(cp)));
90 + } catch (IOException e) {
91 + log.error("Failed to respond back", e);
92 + }
93 + }
94 + });
95 +
96 + clusterCommunicator.addSubscriber(GET_PREVIOUS, new ClusterMessageHandler() {
97 +
98 + @Override
99 + public void handle(ClusterMessage message) {
100 + ConnectPoint cp = SERIALIZER.decode(message.payload());
101 + try {
102 + message.respond(SERIALIZER.encode(getPreviousStatisticInternal(cp)));
103 + } catch (IOException e) {
104 + log.error("Failed to respond back", e);
105 + }
106 + }
107 + });
108 + log.info("Started");
109 + }
110 +
111 + @Deactivate
112 + public void deactivate() {
113 + log.info("Stopped");
114 + }
115 +
116 + @Override
117 + public void prepareForStatistics(FlowRule rule) {
118 + ConnectPoint cp = buildConnectPoint(rule);
119 + if (cp == null) {
120 + return;
121 + }
122 + InternalStatisticRepresentation rep;
123 + synchronized (representations) {
124 + rep = getOrCreateRepresentation(cp);
125 + }
126 + rep.prepare();
127 + }
128 +
129 + @Override
130 + public void removeFromStatistics(FlowRule rule) {
131 + ConnectPoint cp = buildConnectPoint(rule);
132 + if (cp == null) {
133 + return;
134 + }
135 + InternalStatisticRepresentation rep = representations.get(cp);
136 + if (rep != null) {
137 + rep.remove(rule);
138 + }
139 + }
140 +
141 + @Override
142 + public void addOrUpdateStatistic(FlowEntry rule) {
143 + ConnectPoint cp = buildConnectPoint(rule);
144 + if (cp == null) {
145 + return;
146 + }
147 + InternalStatisticRepresentation rep = representations.get(cp);
148 + if (rep != null && rep.submit(rule)) {
149 + updatePublishedStats(cp, rep.get());
150 + }
151 + }
152 +
153 + private synchronized void updatePublishedStats(ConnectPoint cp,
154 + Set<FlowEntry> flowEntries) {
155 + Set<FlowEntry> curr = current.get(cp);
156 + if (curr == null) {
157 + curr = new HashSet<>();
158 + }
159 + previous.put(cp, curr);
160 + current.put(cp, flowEntries);
161 +
162 + }
163 +
164 + @Override
165 + public Set<FlowEntry> getCurrentStatistic(ConnectPoint connectPoint) {
166 + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(connectPoint.deviceId());
167 + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
168 + return getCurrentStatisticInternal(connectPoint);
169 + } else {
170 + ClusterMessage message = new ClusterMessage(
171 + clusterService.getLocalNode().id(),
172 + GET_CURRENT,
173 + SERIALIZER.encode(connectPoint));
174 +
175 + try {
176 + ClusterMessageResponse response =
177 + clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
178 + return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS,
179 + TimeUnit.MILLISECONDS));
180 + } catch (IOException | TimeoutException e) {
181 + // FIXME: throw a FlowStoreException
182 + throw new RuntimeException(e);
183 + }
184 + }
185 +
186 + }
187 +
188 + private synchronized Set<FlowEntry> getCurrentStatisticInternal(ConnectPoint connectPoint) {
189 + return current.get(connectPoint);
190 + }
191 +
192 + @Override
193 + public Set<FlowEntry> getPreviousStatistic(ConnectPoint connectPoint) {
194 + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(connectPoint.deviceId());
195 + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
196 + return getPreviousStatisticInternal(connectPoint);
197 + } else {
198 + ClusterMessage message = new ClusterMessage(
199 + clusterService.getLocalNode().id(),
200 + GET_CURRENT,
201 + SERIALIZER.encode(connectPoint));
202 +
203 + try {
204 + ClusterMessageResponse response =
205 + clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
206 + return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS,
207 + TimeUnit.MILLISECONDS));
208 + } catch (IOException | TimeoutException e) {
209 + // FIXME: throw a FlowStoreException
210 + throw new RuntimeException(e);
211 + }
212 + }
213 +
214 + }
215 +
216 + private synchronized Set<FlowEntry> getPreviousStatisticInternal(ConnectPoint connectPoint) {
217 + return previous.get(connectPoint);
218 + }
219 +
220 + private InternalStatisticRepresentation getOrCreateRepresentation(ConnectPoint cp) {
221 +
222 + if (representations.containsKey(cp)) {
223 + return representations.get(cp);
224 + } else {
225 + InternalStatisticRepresentation rep = new InternalStatisticRepresentation();
226 + representations.put(cp, rep);
227 + return rep;
228 + }
229 +
230 + }
231 +
232 + private ConnectPoint buildConnectPoint(FlowRule rule) {
233 + PortNumber port = getOutput(rule);
234 + if (port == null) {
235 + log.warn("Rule {} has no output.", rule);
236 + return null;
237 + }
238 + ConnectPoint cp = new ConnectPoint(rule.deviceId(), port);
239 + return cp;
240 + }
241 +
242 + private PortNumber getOutput(FlowRule rule) {
243 + for (Instruction i : rule.treatment().instructions()) {
244 + if (i.type() == Instruction.Type.OUTPUT) {
245 + Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
246 + return out.port();
247 + }
248 + if (i.type() == Instruction.Type.DROP) {
249 + return PortNumber.P0;
250 + }
251 + }
252 + return null;
253 + }
254 +
255 + private class InternalStatisticRepresentation {
256 +
257 + private final AtomicInteger counter = new AtomicInteger(0);
258 + private final Set<FlowEntry> rules = new HashSet<>();
259 +
260 + public void prepare() {
261 + counter.incrementAndGet();
262 + }
263 +
264 + public synchronized void remove(FlowRule rule) {
265 + rules.remove(rule);
266 + counter.decrementAndGet();
267 + }
268 +
269 + public synchronized boolean submit(FlowEntry rule) {
270 + if (rules.contains(rule)) {
271 + rules.remove(rule);
272 + }
273 + rules.add(rule);
274 + if (counter.get() == 0) {
275 + return true;
276 + } else {
277 + return counter.decrementAndGet() == 0;
278 + }
279 + }
280 +
281 + public synchronized Set<FlowEntry> get() {
282 + counter.set(rules.size());
283 + return ImmutableSet.copyOf(rules);
284 + }
285 +
286 +
287 + }
288 +
289 +}
1 +package org.onlab.onos.store.statistic.impl;
2 +
3 +import org.onlab.onos.store.cluster.messaging.MessageSubject;
4 +
5 +/**
6 + * MessageSubjects used by DistributedStatisticStore peer-peer communication.
7 + */
8 +public final class StatisticStoreMessageSubjects {
9 + private StatisticStoreMessageSubjects() {}
10 + public static final MessageSubject GET_CURRENT =
11 + new MessageSubject("peer-return-current");
12 + public static final MessageSubject GET_PREVIOUS =
13 + new MessageSubject("peer-return-previous");
14 +
15 +}
1 +/**
2 + * Implementation of the statistic store.
3 + */
4 +package org.onlab.onos.store.statistic.impl;
...\ No newline at end of file ...\ No newline at end of file
...@@ -4,6 +4,7 @@ import java.net.URI; ...@@ -4,6 +4,7 @@ import java.net.URI;
4 import java.util.ArrayList; 4 import java.util.ArrayList;
5 import java.util.Arrays; 5 import java.util.Arrays;
6 import java.util.HashMap; 6 import java.util.HashMap;
7 +import java.util.HashSet;
7 8
8 import org.onlab.onos.cluster.ControllerNode; 9 import org.onlab.onos.cluster.ControllerNode;
9 import org.onlab.onos.cluster.DefaultControllerNode; 10 import org.onlab.onos.cluster.DefaultControllerNode;
...@@ -26,6 +27,7 @@ import org.onlab.onos.net.Port; ...@@ -26,6 +27,7 @@ import org.onlab.onos.net.Port;
26 import org.onlab.onos.net.PortNumber; 27 import org.onlab.onos.net.PortNumber;
27 import org.onlab.onos.net.device.DefaultDeviceDescription; 28 import org.onlab.onos.net.device.DefaultDeviceDescription;
28 import org.onlab.onos.net.device.DefaultPortDescription; 29 import org.onlab.onos.net.device.DefaultPortDescription;
30 +import org.onlab.onos.net.flow.DefaultFlowEntry;
29 import org.onlab.onos.net.flow.DefaultFlowRule; 31 import org.onlab.onos.net.flow.DefaultFlowRule;
30 import org.onlab.onos.net.flow.DefaultTrafficSelector; 32 import org.onlab.onos.net.flow.DefaultTrafficSelector;
31 import org.onlab.onos.net.flow.DefaultTrafficTreatment; 33 import org.onlab.onos.net.flow.DefaultTrafficTreatment;
...@@ -75,6 +77,7 @@ public final class KryoNamespaces { ...@@ -75,6 +77,7 @@ public final class KryoNamespaces {
75 ArrayList.class, 77 ArrayList.class,
76 Arrays.asList().getClass(), 78 Arrays.asList().getClass(),
77 HashMap.class, 79 HashMap.class,
80 + HashSet.class,
78 // 81 //
79 // 82 //
80 ControllerNode.State.class, 83 ControllerNode.State.class,
...@@ -94,6 +97,7 @@ public final class KryoNamespaces { ...@@ -94,6 +97,7 @@ public final class KryoNamespaces {
94 HostDescription.class, 97 HostDescription.class,
95 DefaultHostDescription.class, 98 DefaultHostDescription.class,
96 DefaultFlowRule.class, 99 DefaultFlowRule.class,
100 + DefaultFlowEntry.class,
97 FlowId.class, 101 FlowId.class,
98 DefaultTrafficSelector.class, 102 DefaultTrafficSelector.class,
99 Criteria.PortCriterion.class, 103 Criteria.PortCriterion.class,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onlab.onos.provider.lldp.impl; 16 package org.onlab.onos.provider.lldp.impl;
17 17
18 18
19 +import static com.google.common.base.Preconditions.checkNotNull;
19 import static org.slf4j.LoggerFactory.getLogger; 20 import static org.slf4j.LoggerFactory.getLogger;
20 21
21 import java.nio.ByteBuffer; 22 import java.nio.ByteBuffer;
...@@ -95,11 +96,13 @@ public class LinkDiscovery implements TimerTask { ...@@ -95,11 +96,13 @@ public class LinkDiscovery implements TimerTask {
95 */ 96 */
96 public LinkDiscovery(Device device, PacketService pktService, 97 public LinkDiscovery(Device device, PacketService pktService,
97 MastershipService masterService, LinkProviderService providerService, Boolean... useBDDP) { 98 MastershipService masterService, LinkProviderService providerService, Boolean... useBDDP) {
99 +
98 this.device = device; 100 this.device = device;
99 this.probeRate = 3000; 101 this.probeRate = 3000;
100 this.linkProvider = providerService; 102 this.linkProvider = providerService;
101 this.pktService = pktService; 103 this.pktService = pktService;
102 - this.mastershipService = masterService; 104 +
105 + this.mastershipService = checkNotNull(masterService, "WTF!");
103 this.slowPorts = Collections.synchronizedSet(new HashSet<Long>()); 106 this.slowPorts = Collections.synchronizedSet(new HashSet<Long>());
104 this.fastPorts = Collections.synchronizedSet(new HashSet<Long>()); 107 this.fastPorts = Collections.synchronizedSet(new HashSet<Long>());
105 this.portProbeCount = new HashMap<>(); 108 this.portProbeCount = new HashMap<>();
...@@ -344,6 +347,12 @@ public class LinkDiscovery implements TimerTask { ...@@ -344,6 +347,12 @@ public class LinkDiscovery implements TimerTask {
344 } 347 }
345 348
346 private void sendProbes(Long portNumber) { 349 private void sendProbes(Long portNumber) {
350 + if (device == null) {
351 + log.warn("CRAZY SHIT");
352 + }
353 + if (mastershipService == null) {
354 + log.warn("INSANE");
355 + }
347 if (device.type() != Device.Type.ROADM && 356 if (device.type() != Device.Type.ROADM &&
348 mastershipService.getLocalRole(this.device.id()) == 357 mastershipService.getLocalRole(this.device.id()) ==
349 MastershipRole.MASTER) { 358 MastershipRole.MASTER) {
......
...@@ -103,6 +103,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -103,6 +103,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
103 private final Map<Long, InstallationFuture> pendingFMs = 103 private final Map<Long, InstallationFuture> pendingFMs =
104 new ConcurrentHashMap<Long, InstallationFuture>(); 104 new ConcurrentHashMap<Long, InstallationFuture>();
105 105
106 + private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
107 +
106 /** 108 /**
107 * Creates an OpenFlow host provider. 109 * Creates an OpenFlow host provider.
108 */ 110 */
...@@ -115,6 +117,14 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -115,6 +117,14 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
115 providerService = providerRegistry.register(this); 117 providerService = providerRegistry.register(this);
116 controller.addListener(listener); 118 controller.addListener(listener);
117 controller.addEventListener(listener); 119 controller.addEventListener(listener);
120 +
121 + for (OpenFlowSwitch sw : controller.getSwitches()) {
122 + FlowStatsCollector fsc = new FlowStatsCollector(sw, POLL_INTERVAL);
123 + fsc.start();
124 + collectors.put(new Dpid(sw.getId()), fsc);
125 + }
126 +
127 +
118 log.info("Started"); 128 log.info("Started");
119 } 129 }
120 130
...@@ -213,7 +223,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -213,7 +223,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
213 private class InternalFlowProvider 223 private class InternalFlowProvider
214 implements OpenFlowSwitchListener, OpenFlowEventListener { 224 implements OpenFlowSwitchListener, OpenFlowEventListener {
215 225
216 - private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap(); 226 +
217 private final Multimap<DeviceId, FlowEntry> completeEntries = 227 private final Multimap<DeviceId, FlowEntry> completeEntries =
218 ArrayListMultimap.create(); 228 ArrayListMultimap.create();
219 229
......