tom

Merge remote-tracking branch 'origin/master'

Showing 27 changed files with 522 additions and 105 deletions
1 +package org.onlab.onos.net.flow;
2 +
3 +public class CompletedBatchOperation {
4 +
5 +
6 +}
...@@ -2,12 +2,13 @@ package org.onlab.onos.net.flow; ...@@ -2,12 +2,13 @@ package org.onlab.onos.net.flow;
2 2
3 import org.onlab.onos.ApplicationId; 3 import org.onlab.onos.ApplicationId;
4 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
5 +import org.onlab.onos.net.intent.BatchOperationTarget;
5 6
6 /** 7 /**
7 * Represents a generalized match & action pair to be applied to 8 * Represents a generalized match & action pair to be applied to
8 * an infrastucture device. 9 * an infrastucture device.
9 */ 10 */
10 -public interface FlowRule { 11 +public interface FlowRule extends BatchOperationTarget {
11 12
12 static final int MAX_TIMEOUT = 60; 13 static final int MAX_TIMEOUT = 60;
13 static final int MIN_PRIORITY = 0; 14 static final int MIN_PRIORITY = 0;
......
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
4 +import org.onlab.onos.net.intent.BatchOperationEntry;
5 +
6 +
7 +public class FlowRuleBatchEntry
8 + extends BatchOperationEntry<FlowRuleOperation, FlowRule> {
9 +
10 + public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target) {
11 + super(operator, target);
12 + }
13 +
14 + public enum FlowRuleOperation {
15 + ADD,
16 + REMOVE,
17 + MODIFY
18 + }
19 +
20 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import java.util.Collection;
4 +
5 +import org.onlab.onos.net.intent.BatchOperation;
6 +
7 +public class FlowRuleBatchOperation
8 + extends BatchOperation<FlowRuleBatchEntry> {
9 +
10 + public FlowRuleBatchOperation(Collection<FlowRuleBatchEntry> operations) {
11 + super(operations);
12 + }
13 +}
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import java.util.concurrent.Future;
4 +
3 import org.onlab.onos.ApplicationId; 5 import org.onlab.onos.ApplicationId;
6 +import org.onlab.onos.net.intent.BatchOperation;
4 import org.onlab.onos.net.provider.Provider; 7 import org.onlab.onos.net.provider.Provider;
5 8
6 /** 9 /**
...@@ -34,4 +37,6 @@ public interface FlowRuleProvider extends Provider { ...@@ -34,4 +37,6 @@ public interface FlowRuleProvider extends Provider {
34 */ 37 */
35 void removeRulesById(ApplicationId id, FlowRule... flowRules); 38 void removeRulesById(ApplicationId id, FlowRule... flowRules);
36 39
40 + Future<Void> executeBatch(BatchOperation<FlowRuleBatchEntry> batch);
41 +
37 } 42 }
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import java.util.concurrent.Future;
4 +
3 import org.onlab.onos.ApplicationId; 5 import org.onlab.onos.ApplicationId;
4 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
5 7
...@@ -66,7 +68,12 @@ public interface FlowRuleService { ...@@ -66,7 +68,12 @@ public interface FlowRuleService {
66 */ 68 */
67 Iterable<FlowRule> getFlowRulesById(ApplicationId id); 69 Iterable<FlowRule> getFlowRulesById(ApplicationId id);
68 70
69 - //Future<CompletedBatchOperation> applyBatch(BatchOperation<FlowRuleBatchEntry>) 71 + /**
72 + * Applies a batch operation of FlowRules.
73 + *
74 + * @return future indicating the state of the batch operation
75 + */
76 + Future<CompletedBatchOperation> applyBatch(FlowRuleBatchOperation batch);
70 77
71 /** 78 /**
72 * Adds the specified flow rule listener. 79 * Adds the specified flow rule listener.
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 //TODO is this the right package? 2 //TODO is this the right package?
3 3
4 +import static com.google.common.base.Preconditions.checkNotNull;
5 +
6 +import java.util.Collection;
4 import java.util.Collections; 7 import java.util.Collections;
5 import java.util.LinkedList; 8 import java.util.LinkedList;
6 import java.util.List; 9 import java.util.List;
7 10
8 -import static com.google.common.base.Preconditions.checkNotNull;
9 -
10 /** 11 /**
11 * A list of BatchOperationEntry. 12 * A list of BatchOperationEntry.
12 * 13 *
...@@ -15,7 +16,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -15,7 +16,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
15 */ 16 */
16 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { 17 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
17 18
18 - private List<T> ops; 19 + private final List<T> ops;
19 20
20 /** 21 /**
21 * Creates new {@link BatchOperation} object. 22 * Creates new {@link BatchOperation} object.
...@@ -30,7 +31,7 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { ...@@ -30,7 +31,7 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
30 * 31 *
31 * @param batchOperations the list of batch operation entries. 32 * @param batchOperations the list of batch operation entries.
32 */ 33 */
33 - public BatchOperation(List<T> batchOperations) { 34 + public BatchOperation(Collection<T> batchOperations) {
34 ops = new LinkedList<>(checkNotNull(batchOperations)); 35 ops = new LinkedList<>(checkNotNull(batchOperations));
35 } 36 }
36 37
...@@ -61,6 +62,10 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { ...@@ -61,6 +62,10 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
61 62
62 /** 63 /**
63 * Adds an operation. 64 * Adds an operation.
65 + * FIXME: Brian promises that the Intent Framework
66 + * will not modify the batch operation after it has submitted it.
67 + * Ali would prefer immutablity, but trusts brian for better or
68 + * for worse.
64 * 69 *
65 * @param entry the operation to be added 70 * @param entry the operation to be added
66 * @return this object if succeeded, null otherwise 71 * @return this object if succeeded, null otherwise
......
...@@ -15,14 +15,7 @@ public class BatchOperationEntry<T extends Enum<?>, U extends BatchOperationTarg ...@@ -15,14 +15,7 @@ public class BatchOperationEntry<T extends Enum<?>, U extends BatchOperationTarg
15 private final T operator; 15 private final T operator;
16 private final U target; 16 private final U target;
17 17
18 - /** 18 +
19 - * Default constructor for serializer.
20 - */
21 - @Deprecated
22 - protected BatchOperationEntry() {
23 - this.operator = null;
24 - this.target = null;
25 - }
26 19
27 /** 20 /**
28 * Constructs new instance for the entry of the BatchOperation. 21 * Constructs new instance for the entry of the BatchOperation.
......
...@@ -12,6 +12,7 @@ public interface ClockProviderService { ...@@ -12,6 +12,7 @@ public interface ClockProviderService {
12 12
13 /** 13 /**
14 * Updates the mastership term for the specified deviceId. 14 * Updates the mastership term for the specified deviceId.
15 + *
15 * @param deviceId device identifier. 16 * @param deviceId device identifier.
16 * @param term mastership term. 17 * @param term mastership term.
17 */ 18 */
......
...@@ -144,6 +144,10 @@ public class DeviceManager ...@@ -144,6 +144,10 @@ public class DeviceManager
144 private void applyRole(DeviceId deviceId, MastershipRole newRole) { 144 private void applyRole(DeviceId deviceId, MastershipRole newRole) {
145 if (newRole != MastershipRole.NONE) { 145 if (newRole != MastershipRole.NONE) {
146 Device device = store.getDevice(deviceId); 146 Device device = store.getDevice(deviceId);
147 + // FIXME: Device might not be there yet. (eventual consistent)
148 + if (device == null) {
149 + return;
150 + }
147 DeviceProvider provider = getProvider(device.providerId()); 151 DeviceProvider provider = getProvider(device.providerId());
148 if (provider != null) { 152 if (provider != null) {
149 provider.roleChanged(device, newRole); 153 provider.roleChanged(device, newRole);
...@@ -193,16 +197,38 @@ public class DeviceManager ...@@ -193,16 +197,38 @@ public class DeviceManager
193 checkNotNull(deviceId, DEVICE_ID_NULL); 197 checkNotNull(deviceId, DEVICE_ID_NULL);
194 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL); 198 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
195 checkValidity(); 199 checkValidity();
200 +
201 + log.info("Device {} connected", deviceId);
202 + // check my Role
203 + MastershipRole role = mastershipService.requestRoleFor(deviceId);
204 +
205 + if (role != MastershipRole.MASTER) {
206 + // TODO: Do we need to tell the Provider that
207 + // I am no longer the MASTER?
208 + return;
209 + }
210 +
211 + // Master:
212 + MastershipTerm term = mastershipService.requestTermService()
213 + .getMastershipTerm(deviceId);
214 + if (!term.master().equals(clusterService.getLocalNode().id())) {
215 + // I've lost mastership after I thought I was MASTER.
216 + return;
217 + }
218 + clockProviderService.setMastershipTerm(deviceId, term);
219 +
196 DeviceEvent event = store.createOrUpdateDevice(provider().id(), 220 DeviceEvent event = store.createOrUpdateDevice(provider().id(),
197 deviceId, deviceDescription); 221 deviceId, deviceDescription);
198 222
199 - // If there was a change of any kind, trigger role selection 223 + // If there was a change of any kind, tell the provider
200 - // process. 224 + // I am the master.
225 + // Note: can be null, if mastership was lost.
201 if (event != null) { 226 if (event != null) {
202 - log.info("Device {} connected", deviceId); 227 + // TODO: Check switch reconnected case, is it assured that
203 - mastershipService.requestRoleFor(deviceId); 228 + // event will not be null?
204 - provider().roleChanged(event.subject(), 229 +
205 - mastershipService.requestRoleFor(deviceId)); 230 + // FIXME: 1st argument should be deviceId
231 + provider().roleChanged(event.subject(), role);
206 post(event); 232 post(event);
207 } 233 }
208 } 234 }
...@@ -211,6 +237,10 @@ public class DeviceManager ...@@ -211,6 +237,10 @@ public class DeviceManager
211 public void deviceDisconnected(DeviceId deviceId) { 237 public void deviceDisconnected(DeviceId deviceId) {
212 checkNotNull(deviceId, DEVICE_ID_NULL); 238 checkNotNull(deviceId, DEVICE_ID_NULL);
213 checkValidity(); 239 checkValidity();
240 + if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
241 + log.debug("Device {} disconnected, but I am not the master", deviceId);
242 + return;
243 + }
214 DeviceEvent event = store.markOffline(deviceId); 244 DeviceEvent event = store.markOffline(deviceId);
215 245
216 //we're no longer capable of mastership. 246 //we're no longer capable of mastership.
...@@ -272,9 +302,15 @@ public class DeviceManager ...@@ -272,9 +302,15 @@ public class DeviceManager
272 @Override 302 @Override
273 public void event(MastershipEvent event) { 303 public void event(MastershipEvent event) {
274 if (event.master().equals(clusterService.getLocalNode().id())) { 304 if (event.master().equals(clusterService.getLocalNode().id())) {
305 +
275 MastershipTerm term = mastershipService.requestTermService() 306 MastershipTerm term = mastershipService.requestTermService()
276 .getMastershipTerm(event.subject()); 307 .getMastershipTerm(event.subject());
308 +
309 + if (term.master().equals(clusterService.getLocalNode().id())) {
310 + // only set if I am the master
277 clockProviderService.setMastershipTerm(event.subject(), term); 311 clockProviderService.setMastershipTerm(event.subject(), term);
312 + }
313 +
278 applyRole(event.subject(), MastershipRole.MASTER); 314 applyRole(event.subject(), MastershipRole.MASTER);
279 } else { 315 } else {
280 applyRole(event.subject(), MastershipRole.STANDBY); 316 applyRole(event.subject(), MastershipRole.STANDBY);
......
...@@ -5,6 +5,10 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,6 +5,10 @@ import static org.slf4j.LoggerFactory.getLogger;
5 5
6 import java.util.Iterator; 6 import java.util.Iterator;
7 import java.util.List; 7 import java.util.List;
8 +import java.util.concurrent.ExecutionException;
9 +import java.util.concurrent.Future;
10 +import java.util.concurrent.TimeUnit;
11 +import java.util.concurrent.TimeoutException;
8 12
9 import org.apache.felix.scr.annotations.Activate; 13 import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 14 import org.apache.felix.scr.annotations.Component;
...@@ -18,8 +22,11 @@ import org.onlab.onos.event.EventDeliveryService; ...@@ -18,8 +22,11 @@ import org.onlab.onos.event.EventDeliveryService;
18 import org.onlab.onos.net.Device; 22 import org.onlab.onos.net.Device;
19 import org.onlab.onos.net.DeviceId; 23 import org.onlab.onos.net.DeviceId;
20 import org.onlab.onos.net.device.DeviceService; 24 import org.onlab.onos.net.device.DeviceService;
25 +import org.onlab.onos.net.flow.CompletedBatchOperation;
21 import org.onlab.onos.net.flow.FlowEntry; 26 import org.onlab.onos.net.flow.FlowEntry;
22 import org.onlab.onos.net.flow.FlowRule; 27 import org.onlab.onos.net.flow.FlowRule;
28 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
29 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
23 import org.onlab.onos.net.flow.FlowRuleEvent; 30 import org.onlab.onos.net.flow.FlowRuleEvent;
24 import org.onlab.onos.net.flow.FlowRuleListener; 31 import org.onlab.onos.net.flow.FlowRuleListener;
25 import org.onlab.onos.net.flow.FlowRuleProvider; 32 import org.onlab.onos.net.flow.FlowRuleProvider;
...@@ -32,7 +39,9 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -32,7 +39,9 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
32 import org.onlab.onos.net.provider.AbstractProviderService; 39 import org.onlab.onos.net.provider.AbstractProviderService;
33 import org.slf4j.Logger; 40 import org.slf4j.Logger;
34 41
42 +import com.google.common.collect.ArrayListMultimap;
35 import com.google.common.collect.Lists; 43 import com.google.common.collect.Lists;
44 +import com.google.common.collect.Multimap;
36 45
37 /** 46 /**
38 * Provides implementation of the flow NB &amp; SB APIs. 47 * Provides implementation of the flow NB &amp; SB APIs.
...@@ -131,6 +140,38 @@ public class FlowRuleManager ...@@ -131,6 +140,38 @@ public class FlowRuleManager
131 } 140 }
132 141
133 @Override 142 @Override
143 + public Future<CompletedBatchOperation> applyBatch(
144 + FlowRuleBatchOperation batch) {
145 + Multimap<FlowRuleProvider, FlowRuleBatchEntry> batches =
146 + ArrayListMultimap.create();
147 + List<Future<Void>> futures = Lists.newArrayList();
148 + for (FlowRuleBatchEntry fbe : batch.getOperations()) {
149 + final FlowRule f = fbe.getTarget();
150 + final Device device = deviceService.getDevice(f.deviceId());
151 + final FlowRuleProvider frp = getProvider(device.providerId());
152 + batches.put(frp, fbe);
153 + switch (fbe.getOperator()) {
154 + case ADD:
155 + store.storeFlowRule(f);
156 + break;
157 + case REMOVE:
158 + store.deleteFlowRule(f);
159 + break;
160 + case MODIFY:
161 + default:
162 + log.error("Batch operation type {} unsupported.", fbe.getOperator());
163 + }
164 + }
165 + for (FlowRuleProvider provider : batches.keySet()) {
166 + FlowRuleBatchOperation b =
167 + new FlowRuleBatchOperation(batches.get(provider));
168 + Future<Void> future = provider.executeBatch(b);
169 + futures.add(future);
170 + }
171 + return new FlowRuleBatchFuture(futures);
172 + }
173 +
174 + @Override
134 public void addListener(FlowRuleListener listener) { 175 public void addListener(FlowRuleListener listener) {
135 listenerRegistry.addListener(listener); 176 listenerRegistry.addListener(listener);
136 } 177 }
...@@ -296,4 +337,63 @@ public class FlowRuleManager ...@@ -296,4 +337,63 @@ public class FlowRuleManager
296 eventDispatcher.post(event); 337 eventDispatcher.post(event);
297 } 338 }
298 } 339 }
340 +
341 + private class FlowRuleBatchFuture
342 + implements Future<CompletedBatchOperation> {
343 +
344 + private final List<Future<Void>> futures;
345 +
346 + public FlowRuleBatchFuture(List<Future<Void>> futures) {
347 + this.futures = futures;
348 + }
349 +
350 + @Override
351 + public boolean cancel(boolean mayInterruptIfRunning) {
352 + // TODO Auto-generated method stub
353 + return false;
354 + }
355 +
356 + @Override
357 + public boolean isCancelled() {
358 + // TODO Auto-generated method stub
359 + return false;
360 + }
361 +
362 + @Override
363 + public boolean isDone() {
364 + boolean isDone = true;
365 + for (Future<Void> future : futures) {
366 + isDone &= future.isDone();
367 + }
368 + return isDone;
369 + }
370 +
371 + @Override
372 + public CompletedBatchOperation get() throws InterruptedException,
373 + ExecutionException {
374 + // TODO Auto-generated method stub
375 + for (Future<Void> future : futures) {
376 + future.get();
377 + }
378 + return new CompletedBatchOperation();
379 + }
380 +
381 + @Override
382 + public CompletedBatchOperation get(long timeout, TimeUnit unit)
383 + throws InterruptedException, ExecutionException,
384 + TimeoutException {
385 + // TODO we should decrement the timeout
386 + long start = System.nanoTime();
387 + long end = start + unit.toNanos(timeout);
388 + for (Future<Void> future : futures) {
389 + long now = System.nanoTime();
390 + long thisTimeout = end - now;
391 + future.get(thisTimeout, TimeUnit.NANOSECONDS);
392 + }
393 + return new CompletedBatchOperation();
394 + }
395 +
396 + }
397 +
398 +
299 } 399 }
......
...@@ -4,6 +4,8 @@ import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; ...@@ -4,6 +4,8 @@ import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
4 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
5 5
6 import java.util.Iterator; 6 import java.util.Iterator;
7 +import java.util.List;
8 +import java.util.concurrent.ExecutionException;
7 9
8 import org.apache.felix.scr.annotations.Activate; 10 import org.apache.felix.scr.annotations.Activate;
9 import org.apache.felix.scr.annotations.Component; 11 import org.apache.felix.scr.annotations.Component;
...@@ -16,6 +18,9 @@ import org.onlab.onos.net.Link; ...@@ -16,6 +18,9 @@ import org.onlab.onos.net.Link;
16 import org.onlab.onos.net.flow.DefaultFlowRule; 18 import org.onlab.onos.net.flow.DefaultFlowRule;
17 import org.onlab.onos.net.flow.DefaultTrafficSelector; 19 import org.onlab.onos.net.flow.DefaultTrafficSelector;
18 import org.onlab.onos.net.flow.FlowRule; 20 import org.onlab.onos.net.flow.FlowRule;
21 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
22 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
23 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
19 import org.onlab.onos.net.flow.FlowRuleService; 24 import org.onlab.onos.net.flow.FlowRuleService;
20 import org.onlab.onos.net.flow.TrafficSelector; 25 import org.onlab.onos.net.flow.TrafficSelector;
21 import org.onlab.onos.net.flow.TrafficTreatment; 26 import org.onlab.onos.net.flow.TrafficTreatment;
...@@ -24,6 +29,8 @@ import org.onlab.onos.net.intent.IntentInstaller; ...@@ -24,6 +29,8 @@ import org.onlab.onos.net.intent.IntentInstaller;
24 import org.onlab.onos.net.intent.PathIntent; 29 import org.onlab.onos.net.intent.PathIntent;
25 import org.slf4j.Logger; 30 import org.slf4j.Logger;
26 31
32 +import com.google.common.collect.Lists;
33 +
27 /** 34 /**
28 * Installer for {@link PathIntent path connectivity intents}. 35 * Installer for {@link PathIntent path connectivity intents}.
29 */ 36 */
...@@ -56,19 +63,27 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -56,19 +63,27 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
56 DefaultTrafficSelector.builder(intent.selector()); 63 DefaultTrafficSelector.builder(intent.selector());
57 Iterator<Link> links = intent.path().links().iterator(); 64 Iterator<Link> links = intent.path().links().iterator();
58 ConnectPoint prev = links.next().dst(); 65 ConnectPoint prev = links.next().dst();
59 - 66 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
60 while (links.hasNext()) { 67 while (links.hasNext()) {
61 builder.matchInport(prev.port()); 68 builder.matchInport(prev.port());
62 Link link = links.next(); 69 Link link = links.next();
63 TrafficTreatment treatment = builder() 70 TrafficTreatment treatment = builder()
64 .setOutput(link.src().port()).build(); 71 .setOutput(link.src().port()).build();
72 +
65 FlowRule rule = new DefaultFlowRule(link.src().deviceId(), 73 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
66 builder.build(), treatment, 74 builder.build(), treatment,
67 123, appId, 600); 75 123, appId, 600);
68 - flowRuleService.applyFlowRules(rule); 76 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
77 + //flowRuleService.applyFlowRules(rule);
69 prev = link.dst(); 78 prev = link.dst();
70 } 79 }
71 - 80 + FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
81 + try {
82 + flowRuleService.applyBatch(batch).get();
83 + } catch (InterruptedException | ExecutionException e) {
84 + // TODO Auto-generated catch block
85 + e.printStackTrace();
86 + }
72 } 87 }
73 88
74 @Override 89 @Override
...@@ -77,6 +92,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -77,6 +92,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
77 DefaultTrafficSelector.builder(intent.selector()); 92 DefaultTrafficSelector.builder(intent.selector());
78 Iterator<Link> links = intent.path().links().iterator(); 93 Iterator<Link> links = intent.path().links().iterator();
79 ConnectPoint prev = links.next().dst(); 94 ConnectPoint prev = links.next().dst();
95 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
80 96
81 while (links.hasNext()) { 97 while (links.hasNext()) {
82 builder.matchInport(prev.port()); 98 builder.matchInport(prev.port());
...@@ -86,9 +102,16 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -86,9 +102,16 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
86 FlowRule rule = new DefaultFlowRule(link.src().deviceId(), 102 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
87 builder.build(), treatment, 103 builder.build(), treatment,
88 123, appId, 600); 104 123, appId, 600);
89 - 105 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
90 - flowRuleService.removeFlowRules(rule); 106 + //flowRuleService.removeFlowRules(rule);
91 prev = link.dst(); 107 prev = link.dst();
92 } 108 }
109 + FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
110 + try {
111 + flowRuleService.applyBatch(batch).get();
112 + } catch (InterruptedException | ExecutionException e) {
113 + // TODO Auto-generated catch block
114 + e.printStackTrace();
115 + }
93 } 116 }
94 } 117 }
......
...@@ -12,6 +12,7 @@ import java.util.ArrayList; ...@@ -12,6 +12,7 @@ import java.util.ArrayList;
12 import java.util.Collections; 12 import java.util.Collections;
13 import java.util.List; 13 import java.util.List;
14 import java.util.Set; 14 import java.util.Set;
15 +import java.util.concurrent.Future;
15 16
16 import org.junit.After; 17 import org.junit.After;
17 import org.junit.Before; 18 import org.junit.Before;
...@@ -32,6 +33,7 @@ import org.onlab.onos.net.flow.DefaultFlowRule; ...@@ -32,6 +33,7 @@ import org.onlab.onos.net.flow.DefaultFlowRule;
32 import org.onlab.onos.net.flow.FlowEntry; 33 import org.onlab.onos.net.flow.FlowEntry;
33 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState; 34 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
34 import org.onlab.onos.net.flow.FlowRule; 35 import org.onlab.onos.net.flow.FlowRule;
36 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
35 import org.onlab.onos.net.flow.FlowRuleEvent; 37 import org.onlab.onos.net.flow.FlowRuleEvent;
36 import org.onlab.onos.net.flow.FlowRuleListener; 38 import org.onlab.onos.net.flow.FlowRuleListener;
37 import org.onlab.onos.net.flow.FlowRuleProvider; 39 import org.onlab.onos.net.flow.FlowRuleProvider;
...@@ -42,6 +44,7 @@ import org.onlab.onos.net.flow.TrafficSelector; ...@@ -42,6 +44,7 @@ import org.onlab.onos.net.flow.TrafficSelector;
42 import org.onlab.onos.net.flow.TrafficTreatment; 44 import org.onlab.onos.net.flow.TrafficTreatment;
43 import org.onlab.onos.net.flow.criteria.Criterion; 45 import org.onlab.onos.net.flow.criteria.Criterion;
44 import org.onlab.onos.net.flow.instructions.Instruction; 46 import org.onlab.onos.net.flow.instructions.Instruction;
47 +import org.onlab.onos.net.intent.BatchOperation;
45 import org.onlab.onos.net.provider.AbstractProvider; 48 import org.onlab.onos.net.provider.AbstractProvider;
46 import org.onlab.onos.net.provider.ProviderId; 49 import org.onlab.onos.net.provider.ProviderId;
47 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore; 50 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
...@@ -404,6 +407,13 @@ public class FlowRuleManagerTest { ...@@ -404,6 +407,13 @@ public class FlowRuleManagerTest {
404 public void removeRulesById(ApplicationId id, FlowRule... flowRules) { 407 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
405 } 408 }
406 409
410 + @Override
411 + public Future<Void> executeBatch(
412 + BatchOperation<FlowRuleBatchEntry> batch) {
413 + // TODO Auto-generated method stub
414 + return null;
415 + }
416 +
407 417
408 } 418 }
409 419
......
...@@ -45,4 +45,9 @@ public class MessageSubject { ...@@ -45,4 +45,9 @@ public class MessageSubject {
45 MessageSubject that = (MessageSubject) obj; 45 MessageSubject that = (MessageSubject) obj;
46 return Objects.equals(this.value, that.value); 46 return Objects.equals(this.value, that.value);
47 } 47 }
48 +
49 + // for serializer
50 + protected MessageSubject() {
51 + this.value = "";
52 + }
48 } 53 }
......
...@@ -3,11 +3,11 @@ package org.onlab.onos.store.cluster.messaging.impl; ...@@ -3,11 +3,11 @@ package org.onlab.onos.store.cluster.messaging.impl;
3 import static com.google.common.base.Preconditions.checkArgument; 3 import static com.google.common.base.Preconditions.checkArgument;
4 4
5 import java.io.IOException; 5 import java.io.IOException;
6 -import java.util.HashMap;
7 -import java.util.Map;
8 import java.util.Set; 6 import java.util.Set;
9 import java.util.Timer; 7 import java.util.Timer;
10 import java.util.TimerTask; 8 import java.util.TimerTask;
9 +import java.util.concurrent.TimeUnit;
10 +import java.util.concurrent.TimeoutException;
11 11
12 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
13 import org.apache.felix.scr.annotations.Component; 13 import org.apache.felix.scr.annotations.Component;
...@@ -26,6 +26,7 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; ...@@ -26,6 +26,7 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
26 import org.onlab.onos.store.cluster.messaging.ClusterMessage; 26 import org.onlab.onos.store.cluster.messaging.ClusterMessage;
27 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; 27 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
28 import org.onlab.onos.store.cluster.messaging.MessageSubject; 28 import org.onlab.onos.store.cluster.messaging.MessageSubject;
29 +import org.onlab.onos.store.serializers.ClusterMessageSerializer;
29 import org.onlab.onos.store.serializers.KryoPoolUtil; 30 import org.onlab.onos.store.serializers.KryoPoolUtil;
30 import org.onlab.onos.store.serializers.KryoSerializer; 31 import org.onlab.onos.store.serializers.KryoSerializer;
31 import org.onlab.util.KryoPool; 32 import org.onlab.util.KryoPool;
...@@ -34,6 +35,7 @@ import org.onlab.netty.Message; ...@@ -34,6 +35,7 @@ import org.onlab.netty.Message;
34 import org.onlab.netty.MessageHandler; 35 import org.onlab.netty.MessageHandler;
35 import org.onlab.netty.MessagingService; 36 import org.onlab.netty.MessagingService;
36 import org.onlab.netty.NettyMessagingService; 37 import org.onlab.netty.NettyMessagingService;
38 +import org.onlab.netty.Response;
37 import org.slf4j.Logger; 39 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory; 40 import org.slf4j.LoggerFactory;
39 41
...@@ -50,8 +52,6 @@ public class ClusterCommunicationManager ...@@ -50,8 +52,6 @@ public class ClusterCommunicationManager
50 private ClusterService clusterService; 52 private ClusterService clusterService;
51 53
52 private ClusterNodesDelegate nodesDelegate; 54 private ClusterNodesDelegate nodesDelegate;
53 - // FIXME: `members` should go away and should be using ClusterService
54 - private Map<NodeId, ControllerNode> members = new HashMap<>();
55 private final Timer timer = new Timer("onos-controller-heatbeats"); 55 private final Timer timer = new Timer("onos-controller-heatbeats");
56 public static final long HEART_BEAT_INTERVAL_MILLIS = 1000L; 56 public static final long HEART_BEAT_INTERVAL_MILLIS = 1000L;
57 57
...@@ -59,11 +59,14 @@ public class ClusterCommunicationManager ...@@ -59,11 +59,14 @@ public class ClusterCommunicationManager
59 private MessagingService messagingService; 59 private MessagingService messagingService;
60 60
61 private static final KryoSerializer SERIALIZER = new KryoSerializer() { 61 private static final KryoSerializer SERIALIZER = new KryoSerializer() {
62 + @Override
62 protected void setupKryoPool() { 63 protected void setupKryoPool() {
63 serializerPool = KryoPool.newBuilder() 64 serializerPool = KryoPool.newBuilder()
64 .register(KryoPoolUtil.API) 65 .register(KryoPoolUtil.API)
65 - .register(ClusterMessage.class) 66 + .register(ClusterMessage.class, new ClusterMessageSerializer())
66 .register(ClusterMembershipEvent.class) 67 .register(ClusterMembershipEvent.class)
68 + .register(byte[].class)
69 + .register(MessageSubject.class)
67 .build() 70 .build()
68 .populate(1); 71 .populate(1);
69 } 72 }
...@@ -73,7 +76,15 @@ public class ClusterCommunicationManager ...@@ -73,7 +76,15 @@ public class ClusterCommunicationManager
73 @Activate 76 @Activate
74 public void activate() { 77 public void activate() {
75 localNode = clusterService.getLocalNode(); 78 localNode = clusterService.getLocalNode();
76 - messagingService = new NettyMessagingService(localNode.tcpPort()); 79 + NettyMessagingService netty = new NettyMessagingService(localNode.tcpPort());
80 + // FIXME: workaround until it becomes a service.
81 + try {
82 + netty.activate();
83 + } catch (Exception e) {
84 + // TODO Auto-generated catch block
85 + log.error("NettyMessagingService#activate", e);
86 + }
87 + messagingService = netty;
77 log.info("Started"); 88 log.info("Started");
78 } 89 }
79 90
...@@ -86,7 +97,7 @@ public class ClusterCommunicationManager ...@@ -86,7 +97,7 @@ public class ClusterCommunicationManager
86 @Override 97 @Override
87 public boolean broadcast(ClusterMessage message) { 98 public boolean broadcast(ClusterMessage message) {
88 boolean ok = true; 99 boolean ok = true;
89 - for (ControllerNode node : members.values()) { 100 + for (ControllerNode node : clusterService.getNodes()) {
90 if (!node.equals(localNode)) { 101 if (!node.equals(localNode)) {
91 ok = unicast(message, node.id()) && ok; 102 ok = unicast(message, node.id()) && ok;
92 } 103 }
...@@ -107,13 +118,16 @@ public class ClusterCommunicationManager ...@@ -107,13 +118,16 @@ public class ClusterCommunicationManager
107 118
108 @Override 119 @Override
109 public boolean unicast(ClusterMessage message, NodeId toNodeId) { 120 public boolean unicast(ClusterMessage message, NodeId toNodeId) {
110 - ControllerNode node = members.get(toNodeId); 121 + ControllerNode node = clusterService.getNode(toNodeId);
111 checkArgument(node != null, "Unknown nodeId: %s", toNodeId); 122 checkArgument(node != null, "Unknown nodeId: %s", toNodeId);
112 Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); 123 Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort());
113 try { 124 try {
114 - messagingService.sendAsync(nodeEp, message.subject().value(), SERIALIZER.encode(message)); 125 + log.info("sending...");
126 + Response resp = messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message));
127 + resp.get(1, TimeUnit.SECONDS);
128 + log.info("sent...");
115 return true; 129 return true;
116 - } catch (IOException e) { 130 + } catch (IOException | TimeoutException e) {
117 log.error("Failed to send cluster message to nodeId: " + toNodeId, e); 131 log.error("Failed to send cluster message to nodeId: " + toNodeId, e);
118 } 132 }
119 133
...@@ -137,7 +151,7 @@ public class ClusterCommunicationManager ...@@ -137,7 +151,7 @@ public class ClusterCommunicationManager
137 151
138 @Override 152 @Override
139 public void addNode(ControllerNode node) { 153 public void addNode(ControllerNode node) {
140 - members.put(node.id(), node); 154 + //members.put(node.id(), node);
141 } 155 }
142 156
143 @Override 157 @Override
...@@ -146,7 +160,7 @@ public class ClusterCommunicationManager ...@@ -146,7 +160,7 @@ public class ClusterCommunicationManager
146 localNode.id(), 160 localNode.id(),
147 new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"), 161 new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"),
148 SERIALIZER.encode(new ClusterMembershipEvent(ClusterMembershipEventType.LEAVING_MEMBER, node)))); 162 SERIALIZER.encode(new ClusterMembershipEvent(ClusterMembershipEventType.LEAVING_MEMBER, node))));
149 - members.remove(node.id()); 163 + //members.remove(node.id());
150 } 164 }
151 165
152 // Sends a heart beat to all peers. 166 // Sends a heart beat to all peers.
...@@ -181,7 +195,8 @@ public class ClusterCommunicationManager ...@@ -181,7 +195,8 @@ public class ClusterCommunicationManager
181 } 195 }
182 } 196 }
183 197
184 - private static class InternalClusterMessageHandler implements MessageHandler { 198 + // FIXME: revert static
199 + private class InternalClusterMessageHandler implements MessageHandler {
185 200
186 private final ClusterMessageHandler handler; 201 private final ClusterMessageHandler handler;
187 202
...@@ -191,8 +206,18 @@ public class ClusterCommunicationManager ...@@ -191,8 +206,18 @@ public class ClusterCommunicationManager
191 206
192 @Override 207 @Override
193 public void handle(Message message) { 208 public void handle(Message message) {
209 + // FIXME: remove me
210 + log.info("InternalClusterMessageHandler.handle({})", message);
211 + try {
212 + log.info("before decode");
194 ClusterMessage clusterMessage = SERIALIZER.decode(message.payload()); 213 ClusterMessage clusterMessage = SERIALIZER.decode(message.payload());
214 + log.info("Subject:({}), Sender:({})", clusterMessage.subject(), clusterMessage.sender());
195 handler.handle(clusterMessage); 215 handler.handle(clusterMessage);
216 + message.respond("ACK".getBytes());
217 + } catch (Exception e) {
218 + // TODO Auto-generated catch block
219 + log.error("failed", e);
220 + }
196 } 221 }
197 } 222 }
198 } 223 }
......
...@@ -113,6 +113,7 @@ public class GossipDeviceStore ...@@ -113,6 +113,7 @@ public class GossipDeviceStore
113 protected ClusterService clusterService; 113 protected ClusterService clusterService;
114 114
115 private static final KryoSerializer SERIALIZER = new KryoSerializer() { 115 private static final KryoSerializer SERIALIZER = new KryoSerializer() {
116 + @Override
116 protected void setupKryoPool() { 117 protected void setupKryoPool() {
117 serializerPool = KryoPool.newBuilder() 118 serializerPool = KryoPool.newBuilder()
118 .register(KryoPoolUtil.API) 119 .register(KryoPoolUtil.API)
......
...@@ -35,4 +35,11 @@ public class InternalDeviceEvent { ...@@ -35,4 +35,11 @@ public class InternalDeviceEvent {
35 public Timestamped<DeviceDescription> deviceDescription() { 35 public Timestamped<DeviceDescription> deviceDescription() {
36 return deviceDescription; 36 return deviceDescription;
37 } 37 }
38 +
39 + // for serializer
40 + protected InternalDeviceEvent() {
41 + this.providerId = null;
42 + this.deviceId = null;
43 + this.deviceDescription = null;
44 + }
38 } 45 }
......
...@@ -37,4 +37,11 @@ public class InternalPortEvent { ...@@ -37,4 +37,11 @@ public class InternalPortEvent {
37 public Timestamped<List<PortDescription>> portDescriptions() { 37 public Timestamped<List<PortDescription>> portDescriptions() {
38 return portDescriptions; 38 return portDescriptions;
39 } 39 }
40 +
41 + // for serializer
42 + protected InternalPortEvent() {
43 + this.providerId = null;
44 + this.deviceId = null;
45 + this.portDescriptions = null;
46 + }
40 } 47 }
......
...@@ -35,4 +35,11 @@ public class InternalPortStatusEvent { ...@@ -35,4 +35,11 @@ public class InternalPortStatusEvent {
35 public Timestamped<PortDescription> portDescription() { 35 public Timestamped<PortDescription> portDescription() {
36 return portDescription; 36 return portDescription;
37 } 37 }
38 +
39 + // for serializer
40 + protected InternalPortStatusEvent() {
41 + this.providerId = null;
42 + this.deviceId = null;
43 + this.portDescription = null;
44 + }
38 } 45 }
......
...@@ -119,8 +119,8 @@ implements MastershipStore { ...@@ -119,8 +119,8 @@ implements MastershipStore {
119 119
120 @Override 120 @Override
121 public MastershipTerm getTermFor(DeviceId deviceId) { 121 public MastershipTerm getTermFor(DeviceId deviceId) {
122 - // TODO Auto-generated method stub 122 + // FIXME: implement this
123 - return null; 123 + return MastershipTerm.of(getMaster(deviceId), 1);
124 } 124 }
125 125
126 @Override 126 @Override
......
...@@ -68,7 +68,7 @@ public class FlowModBuilder { ...@@ -68,7 +68,7 @@ public class FlowModBuilder {
68 this.cookie = flowRule.id(); 68 this.cookie = flowRule.id();
69 } 69 }
70 70
71 - public OFFlowMod buildFlowMod() { 71 + public OFFlowMod buildFlowAdd() {
72 Match match = buildMatch(); 72 Match match = buildMatch();
73 List<OFAction> actions = buildActions(); 73 List<OFAction> actions = buildActions();
74 74
...@@ -86,6 +86,24 @@ public class FlowModBuilder { ...@@ -86,6 +86,24 @@ public class FlowModBuilder {
86 86
87 } 87 }
88 88
89 + public OFFlowMod buildFlowMod() {
90 + Match match = buildMatch();
91 + List<OFAction> actions = buildActions();
92 +
93 + //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
94 + OFFlowMod fm = factory.buildFlowModify()
95 + .setCookie(U64.of(cookie.value()))
96 + .setBufferId(OFBufferId.NO_BUFFER)
97 + .setActions(actions)
98 + .setMatch(match)
99 + .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
100 + .setPriority(priority)
101 + .build();
102 +
103 + return fm;
104 +
105 + }
106 +
89 public OFFlowMod buildFlowDel() { 107 public OFFlowMod buildFlowDel() {
90 Match match = buildMatch(); 108 Match match = buildMatch();
91 List<OFAction> actions = buildActions(); 109 List<OFAction> actions = buildActions();
......
...@@ -2,8 +2,17 @@ package org.onlab.onos.provider.of.flow.impl; ...@@ -2,8 +2,17 @@ package org.onlab.onos.provider.of.flow.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 +import java.util.HashSet;
5 import java.util.List; 6 import java.util.List;
6 import java.util.Map; 7 import java.util.Map;
8 +import java.util.Set;
9 +import java.util.concurrent.ConcurrentHashMap;
10 +import java.util.concurrent.CountDownLatch;
11 +import java.util.concurrent.ExecutionException;
12 +import java.util.concurrent.Future;
13 +import java.util.concurrent.TimeUnit;
14 +import java.util.concurrent.TimeoutException;
15 +import java.util.concurrent.atomic.AtomicBoolean;
7 16
8 import org.apache.felix.scr.annotations.Activate; 17 import org.apache.felix.scr.annotations.Activate;
9 import org.apache.felix.scr.annotations.Component; 18 import org.apache.felix.scr.annotations.Component;
...@@ -14,9 +23,11 @@ import org.onlab.onos.ApplicationId; ...@@ -14,9 +23,11 @@ import org.onlab.onos.ApplicationId;
14 import org.onlab.onos.net.DeviceId; 23 import org.onlab.onos.net.DeviceId;
15 import org.onlab.onos.net.flow.FlowEntry; 24 import org.onlab.onos.net.flow.FlowEntry;
16 import org.onlab.onos.net.flow.FlowRule; 25 import org.onlab.onos.net.flow.FlowRule;
26 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
17 import org.onlab.onos.net.flow.FlowRuleProvider; 27 import org.onlab.onos.net.flow.FlowRuleProvider;
18 import org.onlab.onos.net.flow.FlowRuleProviderRegistry; 28 import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
19 import org.onlab.onos.net.flow.FlowRuleProviderService; 29 import org.onlab.onos.net.flow.FlowRuleProviderService;
30 +import org.onlab.onos.net.intent.BatchOperation;
20 import org.onlab.onos.net.provider.AbstractProvider; 31 import org.onlab.onos.net.provider.AbstractProvider;
21 import org.onlab.onos.net.provider.ProviderId; 32 import org.onlab.onos.net.provider.ProviderId;
22 import org.onlab.onos.net.topology.TopologyService; 33 import org.onlab.onos.net.topology.TopologyService;
...@@ -27,6 +38,8 @@ import org.onlab.onos.openflow.controller.OpenFlowSwitch; ...@@ -27,6 +38,8 @@ import org.onlab.onos.openflow.controller.OpenFlowSwitch;
27 import org.onlab.onos.openflow.controller.OpenFlowSwitchListener; 38 import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
28 import org.onlab.onos.openflow.controller.RoleState; 39 import org.onlab.onos.openflow.controller.RoleState;
29 import org.projectfloodlight.openflow.protocol.OFActionType; 40 import org.projectfloodlight.openflow.protocol.OFActionType;
41 +import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
42 +import org.projectfloodlight.openflow.protocol.OFErrorMsg;
30 import org.projectfloodlight.openflow.protocol.OFFlowRemoved; 43 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
31 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; 44 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
32 import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; 45 import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
...@@ -42,9 +55,11 @@ import org.projectfloodlight.openflow.protocol.action.OFActionOutput; ...@@ -42,9 +55,11 @@ import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
42 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; 55 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
43 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; 56 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
44 import org.projectfloodlight.openflow.types.OFPort; 57 import org.projectfloodlight.openflow.types.OFPort;
58 +import org.projectfloodlight.openflow.types.U32;
45 import org.slf4j.Logger; 59 import org.slf4j.Logger;
46 60
47 import com.google.common.collect.ArrayListMultimap; 61 import com.google.common.collect.ArrayListMultimap;
62 +import com.google.common.collect.Lists;
48 import com.google.common.collect.Maps; 63 import com.google.common.collect.Maps;
49 import com.google.common.collect.Multimap; 64 import com.google.common.collect.Multimap;
50 65
...@@ -70,6 +85,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -70,6 +85,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
70 85
71 private final InternalFlowProvider listener = new InternalFlowProvider(); 86 private final InternalFlowProvider listener = new InternalFlowProvider();
72 87
88 + private final Map<Long, InstallationFuture> pendingFutures =
89 + new ConcurrentHashMap<Long, InstallationFuture>();
90 +
73 /** 91 /**
74 * Creates an OpenFlow host provider. 92 * Creates an OpenFlow host provider.
75 */ 93 */
...@@ -101,7 +119,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -101,7 +119,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
101 119
102 private void applyRule(FlowRule flowRule) { 120 private void applyRule(FlowRule flowRule) {
103 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); 121 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
104 - sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod()); 122 + sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
105 } 123 }
106 124
107 125
...@@ -154,6 +172,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -154,6 +172,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
154 172
155 @Override 173 @Override
156 public void handleMessage(Dpid dpid, OFMessage msg) { 174 public void handleMessage(Dpid dpid, OFMessage msg) {
175 + InstallationFuture future = null;
157 switch (msg.getType()) { 176 switch (msg.getType()) {
158 case FLOW_REMOVED: 177 case FLOW_REMOVED:
159 //TODO: make this better 178 //TODO: make this better
...@@ -166,7 +185,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -166,7 +185,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
166 pushFlowMetrics(dpid, (OFStatsReply) msg); 185 pushFlowMetrics(dpid, (OFStatsReply) msg);
167 break; 186 break;
168 case BARRIER_REPLY: 187 case BARRIER_REPLY:
188 + future = pendingFutures.get(msg.getXid());
189 + if (future != null) {
190 + future.satisfyRequirement(dpid);
191 + }
192 + break;
169 case ERROR: 193 case ERROR:
194 + future = pendingFutures.get(msg.getXid());
195 + if (future != null) {
196 + future.fail((OFErrorMsg) msg, dpid);
197 + }
198 + break;
170 default: 199 default:
171 log.debug("Unhandled message type: {}", msg.getType()); 200 log.debug("Unhandled message type: {}", msg.getType());
172 } 201 }
...@@ -226,6 +255,144 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -226,6 +255,144 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
226 } 255 }
227 256
228 257
258 + @Override
259 + public Future<Void> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
260 + final Set<Dpid> sws = new HashSet<Dpid>();
261 +
262 + for (FlowRuleBatchEntry fbe : batch.getOperations()) {
263 + FlowRule flowRule = fbe.getTarget();
264 + OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
265 + sws.add(new Dpid(sw.getId()));
266 + switch (fbe.getOperator()) {
267 + case ADD:
268 + //TODO: Track XID for each flowmod
269 + sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
270 + break;
271 + case REMOVE:
272 + //TODO: Track XID for each flowmod
273 + sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
274 + break;
275 + case MODIFY:
276 + //TODO: Track XID for each flowmod
277 + sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
278 + break;
279 + default:
280 + log.error("Unsupported batch operation {}", fbe.getOperator());
281 + }
282 + }
283 + InstallationFuture installation = new InstallationFuture(sws);
284 + pendingFutures.put(U32.f(batch.hashCode()), installation);
285 + installation.verify(batch.hashCode());
286 + return installation;
287 + }
288 +
289 + private class InstallationFuture implements Future<Void> {
290 +
291 + private final Set<Dpid> sws;
292 + private final AtomicBoolean ok = new AtomicBoolean(true);
293 + private final List<FlowEntry> offendingFlowMods = Lists.newLinkedList();
294 +
295 + private final CountDownLatch countDownLatch;
296 +
297 + public InstallationFuture(Set<Dpid> sws) {
298 + this.sws = sws;
299 + countDownLatch = new CountDownLatch(sws.size());
300 + }
301 +
302 + public void fail(OFErrorMsg msg, Dpid dpid) {
303 + ok.set(false);
304 + //TODO add reason to flowentry
305 + //TODO handle specific error msgs
306 + //offendingFlowMods.add(new FlowEntryBuilder(dpid, msg.));
307 + switch (msg.getErrType()) {
308 + case BAD_ACTION:
309 + break;
310 + case BAD_INSTRUCTION:
311 + break;
312 + case BAD_MATCH:
313 + break;
314 + case BAD_REQUEST:
315 + break;
316 + case EXPERIMENTER:
317 + break;
318 + case FLOW_MOD_FAILED:
319 + break;
320 + case GROUP_MOD_FAILED:
321 + break;
322 + case HELLO_FAILED:
323 + break;
324 + case METER_MOD_FAILED:
325 + break;
326 + case PORT_MOD_FAILED:
327 + break;
328 + case QUEUE_OP_FAILED:
329 + break;
330 + case ROLE_REQUEST_FAILED:
331 + break;
332 + case SWITCH_CONFIG_FAILED:
333 + break;
334 + case TABLE_FEATURES_FAILED:
335 + break;
336 + case TABLE_MOD_FAILED:
337 + break;
338 + default:
339 + break;
340 +
341 + }
342 +
343 + }
344 +
345 + public void satisfyRequirement(Dpid dpid) {
346 + log.warn("Satisfaction from switch {}", dpid);
347 + sws.remove(controller.getSwitch(dpid));
348 + countDownLatch.countDown();
349 + }
350 +
351 + public void verify(Integer id) {
352 + for (Dpid dpid : sws) {
353 + OpenFlowSwitch sw = controller.getSwitch(dpid);
354 + OFBarrierRequest.Builder builder = sw.factory()
355 + .buildBarrierRequest()
356 + .setXid(id);
357 + sw.sendMsg(builder.build());
358 + }
359 +
360 +
361 + }
362 +
363 + @Override
364 + public boolean cancel(boolean mayInterruptIfRunning) {
365 + // TODO Auto-generated method stub
366 + return false;
367 + }
368 +
369 + @Override
370 + public boolean isCancelled() {
371 + // TODO Auto-generated method stub
372 + return false;
373 + }
374 +
375 + @Override
376 + public boolean isDone() {
377 + return sws.isEmpty();
378 + }
379 +
380 + @Override
381 + public Void get() throws InterruptedException, ExecutionException {
382 + countDownLatch.await();
383 + //return offendingFlowMods;
384 + return null;
385 + }
386 +
387 + @Override
388 + public Void get(long timeout, TimeUnit unit)
389 + throws InterruptedException, ExecutionException,
390 + TimeoutException {
391 + countDownLatch.await(timeout, unit);
392 + //return offendingFlowMods;
393 + return null;
394 + }
229 395
396 + }
230 397
231 } 398 }
......
...@@ -8,11 +8,16 @@ import io.netty.handler.codec.ReplayingDecoder; ...@@ -8,11 +8,16 @@ import io.netty.handler.codec.ReplayingDecoder;
8 import java.util.Arrays; 8 import java.util.Arrays;
9 import java.util.List; 9 import java.util.List;
10 10
11 +import org.slf4j.Logger;
12 +import org.slf4j.LoggerFactory;
13 +
11 /** 14 /**
12 * Decoder for inbound messages. 15 * Decoder for inbound messages.
13 */ 16 */
14 public class MessageDecoder extends ReplayingDecoder<DecoderState> { 17 public class MessageDecoder extends ReplayingDecoder<DecoderState> {
15 18
19 + private final Logger log = LoggerFactory.getLogger(getClass());
20 +
16 private final NettyMessagingService messagingService; 21 private final NettyMessagingService messagingService;
17 22
18 private static final KryoSerializer SERIALIZER = new KryoSerializer(); 23 private static final KryoSerializer SERIALIZER = new KryoSerializer();
...@@ -57,4 +62,10 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> { ...@@ -57,4 +62,10 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> {
57 checkState(false, "Must not be here"); 62 checkState(false, "Must not be here");
58 } 63 }
59 } 64 }
65 +
66 + @Override
67 + public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
68 + log.error("Exception inside channel handling pipeline.", cause);
69 + context.close();
70 + }
60 } 71 }
......
1 package org.onlab.netty; 1 package org.onlab.netty;
2 2
3 +import org.slf4j.Logger;
4 +import org.slf4j.LoggerFactory;
5 +
3 import io.netty.buffer.ByteBuf; 6 import io.netty.buffer.ByteBuf;
4 import io.netty.channel.ChannelHandler.Sharable; 7 import io.netty.channel.ChannelHandler.Sharable;
5 import io.netty.channel.ChannelHandlerContext; 8 import io.netty.channel.ChannelHandlerContext;
...@@ -11,6 +14,8 @@ import io.netty.handler.codec.MessageToByteEncoder; ...@@ -11,6 +14,8 @@ import io.netty.handler.codec.MessageToByteEncoder;
11 @Sharable 14 @Sharable
12 public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { 15 public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
13 16
17 + private final Logger log = LoggerFactory.getLogger(getClass());
18 +
14 // onosiscool in ascii 19 // onosiscool in ascii
15 public static final byte[] PREAMBLE = "onosiscool".getBytes(); 20 public static final byte[] PREAMBLE = "onosiscool".getBytes();
16 public static final int HEADER_VERSION = 1; 21 public static final int HEADER_VERSION = 1;
...@@ -47,4 +52,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -47,4 +52,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
47 // write payload. 52 // write payload.
48 out.writeBytes(payload); 53 out.writeBytes(payload);
49 } 54 }
55 +
56 + @Override
57 + public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
58 + log.error("Exception inside channel handling pipeline.", cause);
59 + context.close();
60 + }
50 } 61 }
......
...@@ -248,6 +248,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -248,6 +248,7 @@ public class NettyMessagingService implements MessagingService {
248 248
249 @Override 249 @Override
250 public void exceptionCaught(ChannelHandlerContext context, Throwable cause) { 250 public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
251 + log.error("Exception inside channel handling pipeline.", cause);
251 context.close(); 252 context.close();
252 } 253 }
253 } 254 }
......
1 -package org.onlab.netty;
2 -
3 -import java.util.concurrent.TimeUnit;
4 -
5 -import org.onlab.metrics.MetricsComponent;
6 -import org.onlab.metrics.MetricsFeature;
7 -import org.onlab.metrics.MetricsManager;
8 -
9 -import com.codahale.metrics.Timer;
10 -
11 -// FIXME: Should be move out to test or app
12 -public final class SimpleClient {
13 - private SimpleClient() {
14 - }
15 -
16 - public static void main(String... args) throws Exception {
17 - NettyMessagingService messaging = new TestNettyMessagingService(9081);
18 - MetricsManager metrics = new MetricsManager();
19 - messaging.activate();
20 - metrics.activate();
21 - MetricsFeature feature = new MetricsFeature("timers");
22 - MetricsComponent component = metrics.registerComponent("NettyMessaging");
23 - Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
24 - final int warmup = 100;
25 - for (int i = 0; i < warmup; i++) {
26 - Timer.Context context = sendAsyncTimer.time();
27 - messaging.sendAsync(new Endpoint("localhost", 8080), "simple", "Hello World".getBytes());
28 - context.stop();
29 - }
30 - metrics.registerMetric(component, feature, "AsyncTimer", sendAsyncTimer);
31 -
32 - Timer sendAndReceiveTimer = metrics.createTimer(component, feature, "SendAndReceive");
33 - final int iterations = 1000000;
34 - for (int i = 0; i < iterations; i++) {
35 - Timer.Context context = sendAndReceiveTimer.time();
36 - Response response = messaging
37 - .sendAndReceive(new Endpoint("localhost", 8080), "echo",
38 - "Hello World".getBytes());
39 - System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS)));
40 - context.stop();
41 - }
42 - metrics.registerMetric(component, feature, "AsyncTimer", sendAndReceiveTimer);
43 - }
44 -
45 - public static class TestNettyMessagingService extends NettyMessagingService {
46 - public TestNettyMessagingService(int port) throws Exception {
47 - super(port);
48 - }
49 - }
50 -}
1 -package org.onlab.netty;
2 -
3 -//FIXME: Should be move out to test or app
4 -public final class SimpleServer {
5 - private SimpleServer() {}
6 -
7 - public static void main(String... args) throws Exception {
8 - NettyMessagingService server = new NettyMessagingService(8080);
9 - server.activate();
10 - server.registerHandler("simple", new LoggingHandler());
11 - server.registerHandler("echo", new EchoHandler());
12 - }
13 -}