alshabib

initial working impl of batch operations

Change-Id: Ie970543dec1104a394c7bcfa6eec24c0538278d6
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.
......
...@@ -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
......
...@@ -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 + }
229 359
230 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 + }
395 +
396 + }
397 +
231 } 398 }
......