Brian O'Connor
Committed by Gerrit Code Review

Updating Intent Manager to deal with failures.

Added ids to Flow batch futures.
Adding some basic unit tests for IntentManger
Adding failedIds to the completedOperation in FlowRuleManager

Change-Id: I7645cead193299f70d319d254cd1e82d96909e7b
Showing 20 changed files with 339 additions and 91 deletions
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
15 */ 15 */
16 package org.onlab.onos.net.flow; 16 package org.onlab.onos.net.flow;
17 17
18 +
19 +import java.util.Collections;
20 +
18 import java.util.Set; 21 import java.util.Set;
19 22
20 import com.google.common.collect.ImmutableSet; 23 import com.google.common.collect.ImmutableSet;
...@@ -26,6 +29,21 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -26,6 +29,21 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
26 29
27 private final boolean success; 30 private final boolean success;
28 private final Set<FlowRule> failures; 31 private final Set<FlowRule> failures;
32 + private final Set<Long> failedIds;
33 +
34 + /**
35 + * Creates a new batch completion result.
36 + *
37 + * @param success indicates whether the completion is successful.
38 + * @param failures set of any failures encountered
39 + * @param failedIds (optional) set of failed operation ids
40 + */
41 + public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures,
42 + Set<Long> failedIds) {
43 + this.success = success;
44 + this.failures = ImmutableSet.copyOf(failures);
45 + this.failedIds = ImmutableSet.copyOf(failedIds);
46 + }
29 47
30 /** 48 /**
31 * Creates a new batch completion result. 49 * Creates a new batch completion result.
...@@ -36,8 +54,11 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -36,8 +54,11 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
36 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures) { 54 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures) {
37 this.success = success; 55 this.success = success;
38 this.failures = ImmutableSet.copyOf(failures); 56 this.failures = ImmutableSet.copyOf(failures);
57 + this.failedIds = Collections.emptySet();
39 } 58 }
40 59
60 +
61 +
41 @Override 62 @Override
42 public boolean isSuccess() { 63 public boolean isSuccess() {
43 return success; 64 return success;
...@@ -48,4 +69,8 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -48,4 +69,8 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
48 return failures; 69 return failures;
49 } 70 }
50 71
72 + public Set<Long> failedIds() {
73 + return failedIds;
74 + }
75 +
51 } 76 }
......
...@@ -21,8 +21,20 @@ import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation; ...@@ -21,8 +21,20 @@ import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
21 public class FlowRuleBatchEntry 21 public class FlowRuleBatchEntry
22 extends BatchOperationEntry<FlowRuleOperation, FlowRule> { 22 extends BatchOperationEntry<FlowRuleOperation, FlowRule> {
23 23
24 + private final Long id; // FIXME: consider using Optional<Long>
25 +
24 public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target) { 26 public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target) {
25 super(operator, target); 27 super(operator, target);
28 + this.id = null;
29 + }
30 +
31 + public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target, Long id) {
32 + super(operator, target);
33 + this.id = id;
34 + }
35 +
36 + public Long id() {
37 + return id;
26 } 38 }
27 39
28 public enum FlowRuleOperation { 40 public enum FlowRuleOperation {
......
...@@ -18,38 +18,52 @@ package org.onlab.onos.net.flow; ...@@ -18,38 +18,52 @@ package org.onlab.onos.net.flow;
18 import java.util.Collections; 18 import java.util.Collections;
19 import java.util.List; 19 import java.util.List;
20 20
21 -import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation; 21 +import com.google.common.base.Function;
22 +import com.google.common.collect.FluentIterable;
23 +
24 +
22 25
23 import com.google.common.collect.Lists; 26 import com.google.common.collect.Lists;
24 27
25 public class FlowRuleBatchRequest { 28 public class FlowRuleBatchRequest {
26 29
27 private final int batchId; 30 private final int batchId;
28 - private final List<FlowRule> toAdd; 31 + private final List<FlowRuleBatchEntry> toAdd;
29 - private final List<FlowRule> toRemove; 32 + private final List<FlowRuleBatchEntry> toRemove;
30 33
31 - public FlowRuleBatchRequest(int batchId, List<? extends FlowRule> toAdd, List<? extends FlowRule> toRemove) { 34 + public FlowRuleBatchRequest(int batchId, List<FlowRuleBatchEntry> toAdd,
35 + List<FlowRuleBatchEntry> toRemove) {
32 this.batchId = batchId; 36 this.batchId = batchId;
33 this.toAdd = Collections.unmodifiableList(toAdd); 37 this.toAdd = Collections.unmodifiableList(toAdd);
34 this.toRemove = Collections.unmodifiableList(toRemove); 38 this.toRemove = Collections.unmodifiableList(toRemove);
35 } 39 }
36 40
37 public List<FlowRule> toAdd() { 41 public List<FlowRule> toAdd() {
38 - return toAdd; 42 + return FluentIterable.from(toAdd).transform(
43 + new Function<FlowRuleBatchEntry, FlowRule>() {
44 +
45 + @Override
46 + public FlowRule apply(FlowRuleBatchEntry input) {
47 + return input.getTarget();
48 + }
49 + }).toList();
39 } 50 }
40 51
41 public List<FlowRule> toRemove() { 52 public List<FlowRule> toRemove() {
42 - return toRemove; 53 + return FluentIterable.from(toRemove).transform(
54 + new Function<FlowRuleBatchEntry, FlowRule>() {
55 +
56 + @Override
57 + public FlowRule apply(FlowRuleBatchEntry input) {
58 + return input.getTarget();
59 + }
60 + }).toList();
43 } 61 }
44 62
45 public FlowRuleBatchOperation asBatchOperation() { 63 public FlowRuleBatchOperation asBatchOperation() {
46 List<FlowRuleBatchEntry> entries = Lists.newArrayList(); 64 List<FlowRuleBatchEntry> entries = Lists.newArrayList();
47 - for (FlowRule e : toAdd) { 65 + entries.addAll(toAdd);
48 - entries.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, e)); 66 + entries.addAll(toRemove);
49 - }
50 - for (FlowRule e : toRemove) {
51 - entries.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, e));
52 - }
53 return new FlowRuleBatchOperation(entries); 67 return new FlowRuleBatchOperation(entries);
54 } 68 }
55 69
......
...@@ -37,10 +37,16 @@ public interface IntentBatchService { ...@@ -37,10 +37,16 @@ public interface IntentBatchService {
37 void removeIntentOperations(IntentOperations operations); 37 void removeIntentOperations(IntentOperations operations);
38 38
39 /** 39 /**
40 - * Returns the set of intent batches currently being tracked. 40 + * Returns the set of intent batches that are pending.
41 * @return set of batches 41 * @return set of batches
42 */ 42 */
43 - Set<IntentOperations> getIntentOperations(); 43 + Set<IntentOperations> getPendingOperations();
44 +
45 + /**
46 + * Returns the set of intent batches currently being processed.
47 + * @return set of batches
48 + */
49 + Set<IntentOperations> getCurrentOperations();
44 50
45 /** 51 /**
46 * Sets the batch service delegate. 52 * Sets the batch service delegate.
......
...@@ -67,6 +67,18 @@ public enum IntentState { ...@@ -67,6 +67,18 @@ public enum IntentState {
67 RECOMPILING, 67 RECOMPILING,
68 68
69 /** 69 /**
70 + * TODO: Indicated that an intent will soon be recompiled.
71 + */
72 + //UPDATE,
73 +
74 + /**
75 + * TODO.
76 + * Indicates that an application has requested that an intent be withdrawn.
77 + * It will start withdrawing short, but not necessarily on this instance.
78 + */
79 + //WITHDRAW_REQ,
80 +
81 + /**
70 * Indicates that the intent is being withdrawn. This is a transitional 82 * Indicates that the intent is being withdrawn. This is a transitional
71 * state, triggered by invocation of the 83 * state, triggered by invocation of the
72 * {@link IntentService#withdraw(Intent)} but one with only one outcome, 84 * {@link IntentService#withdraw(Intent)} but one with only one outcome,
......
...@@ -21,6 +21,8 @@ import java.util.List; ...@@ -21,6 +21,8 @@ import java.util.List;
21 import org.junit.Test; 21 import org.junit.Test;
22 import org.onlab.onos.net.intent.IntentTestsMocks; 22 import org.onlab.onos.net.intent.IntentTestsMocks;
23 23
24 +import static org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation.*;
25 +
24 import static org.hamcrest.MatcherAssert.assertThat; 26 import static org.hamcrest.MatcherAssert.assertThat;
25 import static org.hamcrest.Matchers.hasSize; 27 import static org.hamcrest.Matchers.hasSize;
26 import static org.hamcrest.Matchers.is; 28 import static org.hamcrest.Matchers.is;
...@@ -38,10 +40,10 @@ public class FlowRuleBatchRequestTest { ...@@ -38,10 +40,10 @@ public class FlowRuleBatchRequestTest {
38 public void testConstruction() { 40 public void testConstruction() {
39 final FlowRule rule1 = new IntentTestsMocks.MockFlowRule(1); 41 final FlowRule rule1 = new IntentTestsMocks.MockFlowRule(1);
40 final FlowRule rule2 = new IntentTestsMocks.MockFlowRule(2); 42 final FlowRule rule2 = new IntentTestsMocks.MockFlowRule(2);
41 - final List<FlowRule> toAdd = new LinkedList<>(); 43 + final List<FlowRuleBatchEntry> toAdd = new LinkedList<>();
42 - toAdd.add(rule1); 44 + toAdd.add(new FlowRuleBatchEntry(ADD, rule1));
43 - final List<FlowRule> toRemove = new LinkedList<>(); 45 + final List<FlowRuleBatchEntry> toRemove = new LinkedList<>();
44 - toRemove.add(rule2); 46 + toRemove.add(new FlowRuleBatchEntry(REMOVE, rule2));
45 47
46 48
47 final FlowRuleBatchRequest request = 49 final FlowRuleBatchRequest request =
......
...@@ -26,6 +26,7 @@ import java.util.Collections; ...@@ -26,6 +26,7 @@ import java.util.Collections;
26 import java.util.HashSet; 26 import java.util.HashSet;
27 import java.util.LinkedList; 27 import java.util.LinkedList;
28 import java.util.List; 28 import java.util.List;
29 +import java.util.Objects;
29 import java.util.Set; 30 import java.util.Set;
30 31
31 import org.onlab.onos.net.DeviceId; 32 import org.onlab.onos.net.DeviceId;
...@@ -331,7 +332,22 @@ public class IntentTestsMocks { ...@@ -331,7 +332,22 @@ public class IntentTestsMocks {
331 return false; 332 return false;
332 } 333 }
333 334
335 + @Override
336 + public int hashCode() {
337 + return Objects.hash(priority);
338 + }
334 339
340 + @Override
341 + public boolean equals(Object obj) {
342 + if (this == obj) {
343 + return true;
344 + }
345 + if (obj == null || getClass() != obj.getClass()) {
346 + return false;
347 + }
348 + final MockFlowRule other = (MockFlowRule) obj;
349 + return Objects.equals(this.priority, other.priority);
350 + }
335 } 351 }
336 352
337 353
......
...@@ -488,13 +488,14 @@ public class FlowRuleManager ...@@ -488,13 +488,14 @@ public class FlowRuleManager
488 488
489 boolean success = true; 489 boolean success = true;
490 Set<FlowRule> failed = Sets.newHashSet(); 490 Set<FlowRule> failed = Sets.newHashSet();
491 + Set<Long> failedIds = Sets.newHashSet();
491 CompletedBatchOperation completed; 492 CompletedBatchOperation completed;
492 for (Future<CompletedBatchOperation> future : futures) { 493 for (Future<CompletedBatchOperation> future : futures) {
493 completed = future.get(); 494 completed = future.get();
494 - success = validateBatchOperation(failed, completed); 495 + success = validateBatchOperation(failed, failedIds, completed);
495 } 496 }
496 497
497 - return finalizeBatchOperation(success, failed); 498 + return finalizeBatchOperation(success, failed, failedIds);
498 499
499 } 500 }
500 501
...@@ -508,15 +509,17 @@ public class FlowRuleManager ...@@ -508,15 +509,17 @@ public class FlowRuleManager
508 } 509 }
509 boolean success = true; 510 boolean success = true;
510 Set<FlowRule> failed = Sets.newHashSet(); 511 Set<FlowRule> failed = Sets.newHashSet();
512 + Set<Long> failedIds = Sets.newHashSet();
511 CompletedBatchOperation completed; 513 CompletedBatchOperation completed;
512 for (Future<CompletedBatchOperation> future : futures) { 514 for (Future<CompletedBatchOperation> future : futures) {
513 completed = future.get(timeout, unit); 515 completed = future.get(timeout, unit);
514 - success = validateBatchOperation(failed, completed); 516 + success = validateBatchOperation(failed, failedIds, completed);
515 } 517 }
516 - return finalizeBatchOperation(success, failed); 518 + return finalizeBatchOperation(success, failed, failedIds);
517 } 519 }
518 520
519 private boolean validateBatchOperation(Set<FlowRule> failed, 521 private boolean validateBatchOperation(Set<FlowRule> failed,
522 + Set<Long> failedIds,
520 CompletedBatchOperation completed) { 523 CompletedBatchOperation completed) {
521 524
522 if (isCancelled()) { 525 if (isCancelled()) {
...@@ -524,6 +527,7 @@ public class FlowRuleManager ...@@ -524,6 +527,7 @@ public class FlowRuleManager
524 } 527 }
525 if (!completed.isSuccess()) { 528 if (!completed.isSuccess()) {
526 failed.addAll(completed.failedItems()); 529 failed.addAll(completed.failedItems());
530 + failedIds.addAll(completed.failedIds());
527 cleanUpBatch(); 531 cleanUpBatch();
528 cancelAllSubBatches(); 532 cancelAllSubBatches();
529 return false; 533 return false;
...@@ -538,7 +542,8 @@ public class FlowRuleManager ...@@ -538,7 +542,8 @@ public class FlowRuleManager
538 } 542 }
539 543
540 private CompletedBatchOperation finalizeBatchOperation(boolean success, 544 private CompletedBatchOperation finalizeBatchOperation(boolean success,
541 - Set<FlowRule> failed) { 545 + Set<FlowRule> failed,
546 + Set<Long> failedIds) {
542 synchronized (this) { 547 synchronized (this) {
543 if (!state.compareAndSet(BatchState.STARTED, BatchState.FINISHED)) { 548 if (!state.compareAndSet(BatchState.STARTED, BatchState.FINISHED)) {
544 if (state.get() == BatchState.FINISHED) { 549 if (state.get() == BatchState.FINISHED) {
...@@ -546,7 +551,7 @@ public class FlowRuleManager ...@@ -546,7 +551,7 @@ public class FlowRuleManager
546 } 551 }
547 throw new CancellationException(); 552 throw new CancellationException();
548 } 553 }
549 - overall = new CompletedBatchOperation(success, failed); 554 + overall = new CompletedBatchOperation(success, failed, failedIds);
550 return overall; 555 return overall;
551 } 556 }
552 } 557 }
......
...@@ -101,7 +101,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -101,7 +101,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
101 FlowRule rule = new DefaultFlowRule(link.src().deviceId(), 101 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
102 builder.build(), treatment, 123, //FIXME 123 102 builder.build(), treatment, 123, //FIXME 123
103 appId, (short) (intent.id().fingerprint() & 0xffff), 0, true); 103 appId, (short) (intent.id().fingerprint() & 0xffff), 0, true);
104 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)); 104 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule,
105 + intent.id().fingerprint()));
105 prev = link.dst(); 106 prev = link.dst();
106 } 107 }
107 return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 108 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
...@@ -127,7 +128,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -127,7 +128,8 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
127 FlowRule rule = new DefaultFlowRule(link.src().deviceId(), 128 FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
128 builder.build(), treatment, 129 builder.build(), treatment,
129 123, appId, (short) (intent.id().fingerprint() & 0xffff), 0, true); 130 123, appId, (short) (intent.id().fingerprint() & 0xffff), 0, true);
130 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule)); 131 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule,
132 + intent.id().fingerprint()));
131 prev = link.dst(); 133 prev = link.dst();
132 } 134 }
133 return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 135 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import com.google.common.collect.Sets;
4 +import com.google.common.util.concurrent.Futures;
5 +import org.onlab.onos.core.ApplicationId;
6 +import org.onlab.onos.net.DeviceId;
7 +import org.onlab.onos.net.flow.CompletedBatchOperation;
8 +import org.onlab.onos.net.flow.FlowEntry;
9 +import org.onlab.onos.net.flow.FlowRule;
10 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
11 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
12 +import org.onlab.onos.net.flow.FlowRuleListener;
13 +import org.onlab.onos.net.flow.FlowRuleService;
14 +
15 +import java.util.Collections;
16 +import java.util.Set;
17 +import java.util.concurrent.Future;
18 +
19 +
20 +public class MockFlowRuleService implements FlowRuleService {
21 +
22 + private Future<CompletedBatchOperation> future;
23 + final Set<FlowRule> flows = Sets.newHashSet();
24 +
25 + public void setFuture(boolean success) {
26 + future = Futures.immediateFuture(new CompletedBatchOperation(true, Collections.emptySet()));
27 + }
28 +
29 + @Override
30 + public Future<CompletedBatchOperation> applyBatch(FlowRuleBatchOperation batch) {
31 + for (FlowRuleBatchEntry fbe : batch.getOperations()) {
32 + FlowRule fr = fbe.getTarget();
33 + switch (fbe.getOperator()) {
34 + case ADD:
35 + flows.add(fr);
36 + break;
37 + case REMOVE:
38 + flows.remove(fr);
39 + break;
40 + case MODIFY:
41 + break;
42 + default:
43 + break;
44 + }
45 + }
46 + return future;
47 + }
48 +
49 + @Override
50 + public int getFlowRuleCount() {
51 + return flows.size();
52 + }
53 +
54 + @Override
55 + public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
56 + return null;
57 + }
58 +
59 + @Override
60 + public void applyFlowRules(FlowRule... flowRules) {
61 + }
62 +
63 + @Override
64 + public void removeFlowRules(FlowRule... flowRules) {
65 + }
66 +
67 + @Override
68 + public void removeFlowRulesById(ApplicationId appId) {
69 + }
70 +
71 + @Override
72 + public Iterable<FlowRule> getFlowRulesById(ApplicationId id) {
73 + return null;
74 + }
75 +
76 + @Override
77 + public Iterable<FlowRule> getFlowRulesByGroupId(ApplicationId appId, short groupId) {
78 + return null;
79 + }
80 +
81 + @Override
82 + public void addListener(FlowRuleListener listener) {
83 +
84 + }
85 +
86 + @Override
87 + public void removeListener(FlowRuleListener listener) {
88 +
89 + }
90 +}
91 +
...@@ -340,7 +340,8 @@ public class DistributedFlowRuleStore ...@@ -340,7 +340,8 @@ public class DistributedFlowRuleStore
340 public Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation operation) { 340 public Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation operation) {
341 341
342 if (operation.getOperations().isEmpty()) { 342 if (operation.getOperations().isEmpty()) {
343 - return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowRule>emptySet())); 343 + return Futures.immediateFuture(new CompletedBatchOperation(true,
344 + Collections.<FlowRule>emptySet()));
344 } 345 }
345 346
346 DeviceId deviceId = operation.getOperations().get(0).getTarget().deviceId(); 347 DeviceId deviceId = operation.getOperations().get(0).getTarget().deviceId();
...@@ -379,8 +380,8 @@ public class DistributedFlowRuleStore ...@@ -379,8 +380,8 @@ public class DistributedFlowRuleStore
379 private ListenableFuture<CompletedBatchOperation> 380 private ListenableFuture<CompletedBatchOperation>
380 storeBatchInternal(FlowRuleBatchOperation operation) { 381 storeBatchInternal(FlowRuleBatchOperation operation) {
381 382
382 - final List<StoredFlowEntry> toRemove = new ArrayList<>(); 383 + final List<FlowRuleBatchEntry> toRemove = new ArrayList<>();
383 - final List<StoredFlowEntry> toAdd = new ArrayList<>(); 384 + final List<FlowRuleBatchEntry> toAdd = new ArrayList<>();
384 DeviceId did = null; 385 DeviceId did = null;
385 386
386 387
...@@ -396,14 +397,14 @@ public class DistributedFlowRuleStore ...@@ -396,14 +397,14 @@ public class DistributedFlowRuleStore
396 StoredFlowEntry entry = getFlowEntryInternal(flowRule); 397 StoredFlowEntry entry = getFlowEntryInternal(flowRule);
397 if (entry != null) { 398 if (entry != null) {
398 entry.setState(FlowEntryState.PENDING_REMOVE); 399 entry.setState(FlowEntryState.PENDING_REMOVE);
399 - toRemove.add(entry); 400 + toRemove.add(batchEntry);
400 } 401 }
401 } else if (op.equals(FlowRuleOperation.ADD)) { 402 } else if (op.equals(FlowRuleOperation.ADD)) {
402 StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule); 403 StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule);
403 DeviceId deviceId = flowRule.deviceId(); 404 DeviceId deviceId = flowRule.deviceId();
404 if (!flowEntries.containsEntry(deviceId, flowEntry)) { 405 if (!flowEntries.containsEntry(deviceId, flowEntry)) {
405 flowEntries.put(deviceId, flowEntry); 406 flowEntries.put(deviceId, flowEntry);
406 - toAdd.add(flowEntry); 407 + toAdd.add(batchEntry);
407 } 408 }
408 } 409 }
409 } 410 }
...@@ -427,8 +428,8 @@ public class DistributedFlowRuleStore ...@@ -427,8 +428,8 @@ public class DistributedFlowRuleStore
427 } 428 }
428 429
429 private void updateBackup(final DeviceId deviceId, 430 private void updateBackup(final DeviceId deviceId,
430 - final List<StoredFlowEntry> toAdd, 431 + final List<FlowRuleBatchEntry> toAdd,
431 - final List<? extends FlowRule> list) { 432 + final List<FlowRuleBatchEntry> list) {
432 433
433 Future<?> submit = backupExecutors.submit(new UpdateBackup(deviceId, toAdd, list)); 434 Future<?> submit = backupExecutors.submit(new UpdateBackup(deviceId, toAdd, list));
434 435
...@@ -442,8 +443,9 @@ public class DistributedFlowRuleStore ...@@ -442,8 +443,9 @@ public class DistributedFlowRuleStore
442 } 443 }
443 } 444 }
444 445
445 - private void updateBackup(DeviceId deviceId, List<StoredFlowEntry> toAdd) { 446 + private void updateBackup(DeviceId deviceId, List<FlowRuleBatchEntry> toAdd) {
446 - updateBackup(deviceId, toAdd, Collections.<FlowEntry>emptyList()); 447 +
448 + updateBackup(deviceId, toAdd, Collections.<FlowRuleBatchEntry>emptyList());
447 } 449 }
448 450
449 @Override 451 @Override
...@@ -477,8 +479,9 @@ public class DistributedFlowRuleStore ...@@ -477,8 +479,9 @@ public class DistributedFlowRuleStore
477 stored.setPackets(rule.packets()); 479 stored.setPackets(rule.packets());
478 if (stored.state() == FlowEntryState.PENDING_ADD) { 480 if (stored.state() == FlowEntryState.PENDING_ADD) {
479 stored.setState(FlowEntryState.ADDED); 481 stored.setState(FlowEntryState.ADDED);
480 - // update backup. 482 + FlowRuleBatchEntry entry =
481 - updateBackup(did, Arrays.asList(stored)); 483 + new FlowRuleBatchEntry(FlowRuleOperation.ADD, stored);
484 + updateBackup(did, Arrays.asList(entry));
482 return new FlowRuleEvent(Type.RULE_ADDED, rule); 485 return new FlowRuleEvent(Type.RULE_ADDED, rule);
483 } 486 }
484 return new FlowRuleEvent(Type.RULE_UPDATED, rule); 487 return new FlowRuleEvent(Type.RULE_UPDATED, rule);
...@@ -515,7 +518,9 @@ public class DistributedFlowRuleStore ...@@ -515,7 +518,9 @@ public class DistributedFlowRuleStore
515 try { 518 try {
516 // This is where one could mark a rule as removed and still keep it in the store. 519 // This is where one could mark a rule as removed and still keep it in the store.
517 final boolean removed = flowEntries.remove(deviceId, rule); 520 final boolean removed = flowEntries.remove(deviceId, rule);
518 - updateBackup(deviceId, Collections.<StoredFlowEntry>emptyList(), Arrays.asList(rule)); 521 + FlowRuleBatchEntry entry =
522 + new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule);
523 + updateBackup(deviceId, Collections.<FlowRuleBatchEntry>emptyList(), Arrays.asList(entry));
519 if (removed) { 524 if (removed) {
520 return new FlowRuleEvent(RULE_REMOVED, rule); 525 return new FlowRuleEvent(RULE_REMOVED, rule);
521 } else { 526 } else {
...@@ -687,15 +692,17 @@ public class DistributedFlowRuleStore ...@@ -687,15 +692,17 @@ public class DistributedFlowRuleStore
687 } 692 }
688 693
689 // Task to update FlowEntries in backup HZ store 694 // Task to update FlowEntries in backup HZ store
695 + // TODO: Should be refactored to contain only one list and not
696 + // toAdd and toRemove
690 private final class UpdateBackup implements Runnable { 697 private final class UpdateBackup implements Runnable {
691 698
692 private final DeviceId deviceId; 699 private final DeviceId deviceId;
693 - private final List<StoredFlowEntry> toAdd; 700 + private final List<FlowRuleBatchEntry> toAdd;
694 - private final List<? extends FlowRule> toRemove; 701 + private final List<FlowRuleBatchEntry> toRemove;
695 702
696 public UpdateBackup(DeviceId deviceId, 703 public UpdateBackup(DeviceId deviceId,
697 - List<StoredFlowEntry> toAdd, 704 + List<FlowRuleBatchEntry> toAdd,
698 - List<? extends FlowRule> list) { 705 + List<FlowRuleBatchEntry> list) {
699 this.deviceId = checkNotNull(deviceId); 706 this.deviceId = checkNotNull(deviceId);
700 this.toAdd = checkNotNull(toAdd); 707 this.toAdd = checkNotNull(toAdd);
701 this.toRemove = checkNotNull(list); 708 this.toRemove = checkNotNull(list);
...@@ -707,7 +714,8 @@ public class DistributedFlowRuleStore ...@@ -707,7 +714,8 @@ public class DistributedFlowRuleStore
707 log.trace("update backup {} +{} -{}", deviceId, toAdd, toRemove); 714 log.trace("update backup {} +{} -{}", deviceId, toAdd, toRemove);
708 final SMap<FlowId, ImmutableList<StoredFlowEntry>> backupFlowTable = smaps.get(deviceId); 715 final SMap<FlowId, ImmutableList<StoredFlowEntry>> backupFlowTable = smaps.get(deviceId);
709 // Following should be rewritten using async APIs 716 // Following should be rewritten using async APIs
710 - for (StoredFlowEntry entry : toAdd) { 717 + for (FlowRuleBatchEntry bEntry : toAdd) {
718 + final FlowRule entry = bEntry.getTarget();
711 final FlowId id = entry.id(); 719 final FlowId id = entry.id();
712 ImmutableList<StoredFlowEntry> original = backupFlowTable.get(id); 720 ImmutableList<StoredFlowEntry> original = backupFlowTable.get(id);
713 List<StoredFlowEntry> list = new ArrayList<>(); 721 List<StoredFlowEntry> list = new ArrayList<>();
...@@ -715,8 +723,8 @@ public class DistributedFlowRuleStore ...@@ -715,8 +723,8 @@ public class DistributedFlowRuleStore
715 list.addAll(original); 723 list.addAll(original);
716 } 724 }
717 725
718 - list.remove(entry); 726 + list.remove(bEntry.getTarget());
719 - list.add(entry); 727 + list.add((StoredFlowEntry) entry);
720 728
721 ImmutableList<StoredFlowEntry> newValue = ImmutableList.copyOf(list); 729 ImmutableList<StoredFlowEntry> newValue = ImmutableList.copyOf(list);
722 boolean success; 730 boolean success;
...@@ -730,7 +738,8 @@ public class DistributedFlowRuleStore ...@@ -730,7 +738,8 @@ public class DistributedFlowRuleStore
730 log.error("Updating backup failed."); 738 log.error("Updating backup failed.");
731 } 739 }
732 } 740 }
733 - for (FlowRule entry : toRemove) { 741 + for (FlowRuleBatchEntry bEntry : toRemove) {
742 + final FlowRule entry = bEntry.getTarget();
734 final FlowId id = entry.id(); 743 final FlowId id = entry.id();
735 ImmutableList<StoredFlowEntry> original = backupFlowTable.get(id); 744 ImmutableList<StoredFlowEntry> original = backupFlowTable.get(id);
736 List<StoredFlowEntry> list = new ArrayList<>(); 745 List<StoredFlowEntry> list = new ArrayList<>();
...@@ -738,7 +747,7 @@ public class DistributedFlowRuleStore ...@@ -738,7 +747,7 @@ public class DistributedFlowRuleStore
738 list.addAll(original); 747 list.addAll(original);
739 } 748 }
740 749
741 - list.remove(entry); 750 + list.remove(bEntry.getTarget());
742 751
743 ImmutableList<StoredFlowEntry> newValue = ImmutableList.copyOf(list); 752 ImmutableList<StoredFlowEntry> newValue = ImmutableList.copyOf(list);
744 boolean success; 753 boolean success;
......
...@@ -25,7 +25,6 @@ import org.onlab.onos.net.intent.IntentBatchService; ...@@ -25,7 +25,6 @@ import org.onlab.onos.net.intent.IntentBatchService;
25 import org.onlab.onos.net.intent.IntentOperations; 25 import org.onlab.onos.net.intent.IntentOperations;
26 import org.slf4j.Logger; 26 import org.slf4j.Logger;
27 27
28 -import java.util.Collection;
29 import java.util.LinkedList; 28 import java.util.LinkedList;
30 import java.util.Queue; 29 import java.util.Queue;
31 import java.util.Set; 30 import java.util.Set;
...@@ -82,10 +81,17 @@ public class DistributedIntentBatchQueue implements IntentBatchService { ...@@ -82,10 +81,17 @@ public class DistributedIntentBatchQueue implements IntentBatchService {
82 } 81 }
83 82
84 @Override 83 @Override
85 - public Set<IntentOperations> getIntentOperations() { 84 + public Set<IntentOperations> getPendingOperations() {
86 - Set<IntentOperations> set = Sets.newHashSet(currentBatches); 85 + synchronized (this) {
87 - set.addAll((Collection) pendingBatches); 86 + return Sets.newHashSet(pendingBatches);
88 - return set; 87 + }
88 + }
89 +
90 + @Override
91 + public Set<IntentOperations> getCurrentOperations() {
92 + synchronized (this) {
93 + return Sets.newHashSet(currentBatches);
94 + }
89 } 95 }
90 96
91 @Override 97 @Override
......
...@@ -263,19 +263,19 @@ public class SimpleFlowRuleStore ...@@ -263,19 +263,19 @@ public class SimpleFlowRuleStore
263 @Override 263 @Override
264 public Future<CompletedBatchOperation> storeBatch( 264 public Future<CompletedBatchOperation> storeBatch(
265 FlowRuleBatchOperation batchOperation) { 265 FlowRuleBatchOperation batchOperation) {
266 - List<FlowRule> toAdd = new ArrayList<>(); 266 + List<FlowRuleBatchEntry> toAdd = new ArrayList<>();
267 - List<FlowRule> toRemove = new ArrayList<>(); 267 + List<FlowRuleBatchEntry> toRemove = new ArrayList<>();
268 for (FlowRuleBatchEntry entry : batchOperation.getOperations()) { 268 for (FlowRuleBatchEntry entry : batchOperation.getOperations()) {
269 final FlowRule flowRule = entry.getTarget(); 269 final FlowRule flowRule = entry.getTarget();
270 if (entry.getOperator().equals(FlowRuleOperation.ADD)) { 270 if (entry.getOperator().equals(FlowRuleOperation.ADD)) {
271 if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) { 271 if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) {
272 storeFlowRule(flowRule); 272 storeFlowRule(flowRule);
273 - toAdd.add(flowRule); 273 + toAdd.add(entry);
274 } 274 }
275 } else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) { 275 } else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) {
276 if (getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) { 276 if (getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) {
277 deleteFlowRule(flowRule); 277 deleteFlowRule(flowRule);
278 - toRemove.add(flowRule); 278 + toRemove.add(entry);
279 } 279 }
280 } else { 280 } else {
281 throw new UnsupportedOperationException("Unsupported operation type"); 281 throw new UnsupportedOperationException("Unsupported operation type");
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onlab.onos.store.trivial.impl; 16 package org.onlab.onos.store.trivial.impl;
17 17
18 -import com.google.common.collect.ImmutableSet; 18 +import com.google.common.collect.Sets;
19 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
20 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -25,7 +25,8 @@ import org.onlab.onos.net.intent.IntentBatchService; ...@@ -25,7 +25,8 @@ import org.onlab.onos.net.intent.IntentBatchService;
25 import org.onlab.onos.net.intent.IntentOperations; 25 import org.onlab.onos.net.intent.IntentOperations;
26 import org.slf4j.Logger; 26 import org.slf4j.Logger;
27 27
28 -import java.util.HashSet; 28 +import java.util.LinkedList;
29 +import java.util.Queue;
29 import java.util.Set; 30 import java.util.Set;
30 31
31 import static com.google.common.base.Preconditions.checkNotNull; 32 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -37,7 +38,8 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -37,7 +38,8 @@ import static org.slf4j.LoggerFactory.getLogger;
37 public class SimpleIntentBatchQueue implements IntentBatchService { 38 public class SimpleIntentBatchQueue implements IntentBatchService {
38 39
39 private final Logger log = getLogger(getClass()); 40 private final Logger log = getLogger(getClass());
40 - private final Set<IntentOperations> pendingBatches = new HashSet<>(); 41 + private final Queue<IntentOperations> pendingBatches = new LinkedList<>();
42 + private final Set<IntentOperations> currentBatches = Sets.newHashSet();
41 private IntentBatchDelegate delegate; 43 private IntentBatchDelegate delegate;
42 44
43 @Activate 45 @Activate
...@@ -53,18 +55,42 @@ public class SimpleIntentBatchQueue implements IntentBatchService { ...@@ -53,18 +55,42 @@ public class SimpleIntentBatchQueue implements IntentBatchService {
53 @Override 55 @Override
54 public void addIntentOperations(IntentOperations operations) { 56 public void addIntentOperations(IntentOperations operations) {
55 checkState(delegate != null, "No delegate set"); 57 checkState(delegate != null, "No delegate set");
58 + synchronized (this) {
56 pendingBatches.add(operations); 59 pendingBatches.add(operations);
57 - delegate.execute(operations); 60 + if (currentBatches.isEmpty()) {
61 + IntentOperations work = pendingBatches.poll();
62 + currentBatches.add(work);
63 + delegate.execute(work);
64 + }
65 + }
58 } 66 }
59 67
60 @Override 68 @Override
61 public void removeIntentOperations(IntentOperations operations) { 69 public void removeIntentOperations(IntentOperations operations) {
62 - pendingBatches.remove(operations); 70 + // we allow at most one outstanding batch at a time
71 + synchronized (this) {
72 + checkState(currentBatches.remove(operations), "Operations not found in current ops.");
73 + checkState(currentBatches.isEmpty(), "More than one outstanding batch.");
74 + IntentOperations work = pendingBatches.poll();
75 + if (work != null) {
76 + currentBatches.add(work);
77 + delegate.execute(work);
78 + }
79 + }
63 } 80 }
64 81
65 @Override 82 @Override
66 - public Set<IntentOperations> getIntentOperations() { 83 + public Set<IntentOperations> getPendingOperations() {
67 - return ImmutableSet.copyOf(pendingBatches); 84 + synchronized (this) {
85 + return Sets.newHashSet(pendingBatches);
86 + }
87 + }
88 +
89 + @Override
90 + public Set<IntentOperations> getCurrentOperations() {
91 + synchronized (this) {
92 + return Sets.newHashSet(currentBatches);
93 + }
68 } 94 }
69 95
70 @Override 96 @Override
......
...@@ -53,6 +53,8 @@ import org.projectfloodlight.openflow.types.VlanPcp; ...@@ -53,6 +53,8 @@ import org.projectfloodlight.openflow.types.VlanPcp;
53 import org.projectfloodlight.openflow.types.VlanVid; 53 import org.projectfloodlight.openflow.types.VlanVid;
54 import org.slf4j.Logger; 54 import org.slf4j.Logger;
55 55
56 +import java.util.Optional;
57 +
56 /** 58 /**
57 * Builder for OpenFlow flow mods based on FlowRules. 59 * Builder for OpenFlow flow mods based on FlowRules.
58 */ 60 */
...@@ -63,6 +65,7 @@ public abstract class FlowModBuilder { ...@@ -63,6 +65,7 @@ public abstract class FlowModBuilder {
63 private final OFFactory factory; 65 private final OFFactory factory;
64 private final FlowRule flowRule; 66 private final FlowRule flowRule;
65 private final TrafficSelector selector; 67 private final TrafficSelector selector;
68 + protected final Long xid;
66 69
67 /** 70 /**
68 * Creates a new flow mod builder. 71 * Creates a new flow mod builder.
...@@ -71,12 +74,13 @@ public abstract class FlowModBuilder { ...@@ -71,12 +74,13 @@ public abstract class FlowModBuilder {
71 * @param factory the OpenFlow factory to use to build the flow mod 74 * @param factory the OpenFlow factory to use to build the flow mod
72 * @return the new flow mod builder 75 * @return the new flow mod builder
73 */ 76 */
74 - public static FlowModBuilder builder(FlowRule flowRule, OFFactory factory) { 77 + public static FlowModBuilder builder(FlowRule flowRule,
78 + OFFactory factory, Optional<Long> xid) {
75 switch (factory.getVersion()) { 79 switch (factory.getVersion()) {
76 case OF_10: 80 case OF_10:
77 - return new FlowModBuilderVer10(flowRule, factory); 81 + return new FlowModBuilderVer10(flowRule, factory, xid);
78 case OF_13: 82 case OF_13:
79 - return new FlowModBuilderVer13(flowRule, factory); 83 + return new FlowModBuilderVer13(flowRule, factory, xid);
80 default: 84 default:
81 throw new UnsupportedOperationException( 85 throw new UnsupportedOperationException(
82 "No flow mod builder for protocol version " + factory.getVersion()); 86 "No flow mod builder for protocol version " + factory.getVersion());
...@@ -89,10 +93,12 @@ public abstract class FlowModBuilder { ...@@ -89,10 +93,12 @@ public abstract class FlowModBuilder {
89 * @param flowRule the flow rule to transform into a flow mod 93 * @param flowRule the flow rule to transform into a flow mod
90 * @param factory the OpenFlow factory to use to build the flow mod 94 * @param factory the OpenFlow factory to use to build the flow mod
91 */ 95 */
92 - protected FlowModBuilder(FlowRule flowRule, OFFactory factory) { 96 + protected FlowModBuilder(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
93 this.factory = factory; 97 this.factory = factory;
94 this.flowRule = flowRule; 98 this.flowRule = flowRule;
95 this.selector = flowRule.selector(); 99 this.selector = flowRule.selector();
100 + this.xid = xid.orElse((long) 0);
101 +
96 } 102 }
97 103
98 /** 104 /**
......
...@@ -18,6 +18,7 @@ package org.onlab.onos.provider.of.flow.impl; ...@@ -18,6 +18,7 @@ package org.onlab.onos.provider.of.flow.impl;
18 import java.util.Collections; 18 import java.util.Collections;
19 import java.util.LinkedList; 19 import java.util.LinkedList;
20 import java.util.List; 20 import java.util.List;
21 +import java.util.Optional;
21 22
22 import org.onlab.onos.net.flow.FlowRule; 23 import org.onlab.onos.net.flow.FlowRule;
23 import org.onlab.onos.net.flow.TrafficTreatment; 24 import org.onlab.onos.net.flow.TrafficTreatment;
...@@ -62,8 +63,9 @@ public class FlowModBuilderVer10 extends FlowModBuilder { ...@@ -62,8 +63,9 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
62 * @param flowRule the flow rule to transform into a flow mod 63 * @param flowRule the flow rule to transform into a flow mod
63 * @param factory the OpenFlow factory to use to build the flow mod 64 * @param factory the OpenFlow factory to use to build the flow mod
64 */ 65 */
65 - protected FlowModBuilderVer10(FlowRule flowRule, OFFactory factory) { 66 + protected FlowModBuilderVer10(FlowRule flowRule,
66 - super(flowRule, factory); 67 + OFFactory factory, Optional<Long> xid) {
68 + super(flowRule, factory, xid);
67 69
68 this.treatment = flowRule.treatment(); 70 this.treatment = flowRule.treatment();
69 } 71 }
...@@ -77,7 +79,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { ...@@ -77,7 +79,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
77 79
78 //TODO: what to do without bufferid? do we assume that there will be a pktout as well? 80 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
79 OFFlowAdd fm = factory().buildFlowAdd() 81 OFFlowAdd fm = factory().buildFlowAdd()
80 - .setXid(cookie) 82 + .setXid(xid)
81 .setCookie(U64.of(cookie)) 83 .setCookie(U64.of(cookie))
82 .setBufferId(OFBufferId.NO_BUFFER) 84 .setBufferId(OFBufferId.NO_BUFFER)
83 .setActions(actions) 85 .setActions(actions)
...@@ -98,7 +100,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { ...@@ -98,7 +100,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
98 100
99 //TODO: what to do without bufferid? do we assume that there will be a pktout as well? 101 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
100 OFFlowMod fm = factory().buildFlowModify() 102 OFFlowMod fm = factory().buildFlowModify()
101 - .setXid(cookie) 103 + .setXid(xid)
102 .setCookie(U64.of(cookie)) 104 .setCookie(U64.of(cookie))
103 .setBufferId(OFBufferId.NO_BUFFER) 105 .setBufferId(OFBufferId.NO_BUFFER)
104 .setActions(actions) 106 .setActions(actions)
...@@ -118,7 +120,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { ...@@ -118,7 +120,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
118 long cookie = flowRule().id().value(); 120 long cookie = flowRule().id().value();
119 121
120 OFFlowDelete fm = factory().buildFlowDelete() 122 OFFlowDelete fm = factory().buildFlowDelete()
121 - .setXid(cookie) 123 + .setXid(xid)
122 .setCookie(U64.of(cookie)) 124 .setCookie(U64.of(cookie))
123 .setBufferId(OFBufferId.NO_BUFFER) 125 .setBufferId(OFBufferId.NO_BUFFER)
124 .setActions(actions) 126 .setActions(actions)
......
...@@ -18,6 +18,7 @@ package org.onlab.onos.provider.of.flow.impl; ...@@ -18,6 +18,7 @@ package org.onlab.onos.provider.of.flow.impl;
18 import java.util.Collections; 18 import java.util.Collections;
19 import java.util.LinkedList; 19 import java.util.LinkedList;
20 import java.util.List; 20 import java.util.List;
21 +import java.util.Optional;
21 22
22 import org.onlab.onos.net.flow.FlowRule; 23 import org.onlab.onos.net.flow.FlowRule;
23 import org.onlab.onos.net.flow.TrafficTreatment; 24 import org.onlab.onos.net.flow.TrafficTreatment;
...@@ -70,8 +71,8 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -70,8 +71,8 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
70 * @param flowRule the flow rule to transform into a flow mod 71 * @param flowRule the flow rule to transform into a flow mod
71 * @param factory the OpenFlow factory to use to build the flow mod 72 * @param factory the OpenFlow factory to use to build the flow mod
72 */ 73 */
73 - protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory) { 74 + protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
74 - super(flowRule, factory); 75 + super(flowRule, factory, xid);
75 76
76 this.treatment = flowRule.treatment(); 77 this.treatment = flowRule.treatment();
77 } 78 }
...@@ -93,7 +94,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -93,7 +94,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
93 94
94 //TODO: what to do without bufferid? do we assume that there will be a pktout as well? 95 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
95 OFFlowAdd fm = factory().buildFlowAdd() 96 OFFlowAdd fm = factory().buildFlowAdd()
96 - .setXid(cookie) 97 + .setXid(xid)
97 .setCookie(U64.of(cookie)) 98 .setCookie(U64.of(cookie))
98 .setBufferId(OFBufferId.NO_BUFFER) 99 .setBufferId(OFBufferId.NO_BUFFER)
99 .setActions(actions) 100 .setActions(actions)
...@@ -117,7 +118,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -117,7 +118,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
117 118
118 //TODO: what to do without bufferid? do we assume that there will be a pktout as well? 119 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
119 OFFlowMod fm = factory().buildFlowModify() 120 OFFlowMod fm = factory().buildFlowModify()
120 - .setXid(cookie) 121 + .setXid(xid)
121 .setCookie(U64.of(cookie)) 122 .setCookie(U64.of(cookie))
122 .setBufferId(OFBufferId.NO_BUFFER) 123 .setBufferId(OFBufferId.NO_BUFFER)
123 .setActions(actions) 124 .setActions(actions)
...@@ -140,7 +141,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -140,7 +141,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
140 long cookie = flowRule().id().value(); 141 long cookie = flowRule().id().value();
141 142
142 OFFlowDelete fm = factory().buildFlowDelete() 143 OFFlowDelete fm = factory().buildFlowDelete()
143 - .setXid(cookie) 144 + .setXid(xid)
144 .setCookie(U64.of(cookie)) 145 .setCookie(U64.of(cookie))
145 .setBufferId(OFBufferId.NO_BUFFER) 146 .setBufferId(OFBufferId.NO_BUFFER)
146 //.setActions(actions) //FIXME do we want to send actions in flowdel? 147 //.setActions(actions) //FIXME do we want to send actions in flowdel?
......
...@@ -19,7 +19,6 @@ import com.google.common.collect.ArrayListMultimap; ...@@ -19,7 +19,6 @@ import com.google.common.collect.ArrayListMultimap;
19 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
20 import com.google.common.collect.Multimap; 20 import com.google.common.collect.Multimap;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
22 -import com.google.common.util.concurrent.ExecutionList;
23 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
24 import org.apache.felix.scr.annotations.Component; 23 import org.apache.felix.scr.annotations.Component;
25 import org.apache.felix.scr.annotations.Deactivate; 24 import org.apache.felix.scr.annotations.Deactivate;
...@@ -76,6 +75,7 @@ import java.util.Collections; ...@@ -76,6 +75,7 @@ import java.util.Collections;
76 import java.util.HashMap; 75 import java.util.HashMap;
77 import java.util.List; 76 import java.util.List;
78 import java.util.Map; 77 import java.util.Map;
78 +import java.util.Optional;
79 import java.util.Set; 79 import java.util.Set;
80 import java.util.concurrent.ConcurrentHashMap; 80 import java.util.concurrent.ConcurrentHashMap;
81 import java.util.concurrent.CountDownLatch; 81 import java.util.concurrent.CountDownLatch;
...@@ -122,7 +122,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -122,7 +122,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
122 122
123 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap(); 123 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
124 124
125 - private final AtomicLong xidCounter = new AtomicLong(0); 125 + private final AtomicLong xidCounter = new AtomicLong(1);
126 126
127 /** 127 /**
128 * Creates an OpenFlow host provider. 128 * Creates an OpenFlow host provider.
...@@ -164,7 +164,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -164,7 +164,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
164 164
165 private void applyRule(FlowRule flowRule) { 165 private void applyRule(FlowRule flowRule) {
166 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); 166 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
167 - sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowAdd()); 167 + sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
168 + Optional.empty()).buildFlowAdd());
168 } 169 }
169 170
170 171
...@@ -178,7 +179,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -178,7 +179,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
178 179
179 private void removeRule(FlowRule flowRule) { 180 private void removeRule(FlowRule flowRule) {
180 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); 181 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
181 - sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowDel()); 182 + sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
183 + Optional.empty()).buildFlowDel());
182 } 184 }
183 185
184 @Override 186 @Override
...@@ -211,7 +213,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -211,7 +213,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
211 return failed; 213 return failed;
212 } 214 }
213 sws.add(new Dpid(sw.getId())); 215 sws.add(new Dpid(sw.getId()));
214 - FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory()); 216 + Long flowModXid = xidCounter.getAndIncrement();
217 + FlowModBuilder builder =
218 + FlowModBuilder.builder(flowRule, sw.factory(),
219 + Optional.of(flowModXid));
215 OFFlowMod mod = null; 220 OFFlowMod mod = null;
216 switch (fbe.getOperator()) { 221 switch (fbe.getOperator()) {
217 case ADD: 222 case ADD:
...@@ -228,7 +233,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -228,7 +233,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
228 } 233 }
229 if (mod != null) { 234 if (mod != null) {
230 mods.put(mod, sw); 235 mods.put(mod, sw);
231 - fmXids.put(xidCounter.getAndIncrement(), fbe); 236 + fmXids.put(flowModXid, fbe);
232 } else { 237 } else {
233 log.error("Conversion of flowrule {} failed.", flowRule); 238 log.error("Conversion of flowrule {} failed.", flowRule);
234 } 239 }
...@@ -237,6 +242,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -237,6 +242,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
237 for (Long xid : fmXids.keySet()) { 242 for (Long xid : fmXids.keySet()) {
238 pendingFMs.put(xid, installation); 243 pendingFMs.put(xid, installation);
239 } 244 }
245 +
240 pendingFutures.put(installation.xid(), installation); 246 pendingFutures.put(installation.xid(), installation);
241 for (Map.Entry<OFFlowMod, OpenFlowSwitch> entry : mods.entrySet()) { 247 for (Map.Entry<OFFlowMod, OpenFlowSwitch> entry : mods.entrySet()) {
242 OpenFlowSwitch sw = entry.getValue(); 248 OpenFlowSwitch sw = entry.getValue();
...@@ -368,13 +374,13 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -368,13 +374,13 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
368 private final AtomicBoolean ok = new AtomicBoolean(true); 374 private final AtomicBoolean ok = new AtomicBoolean(true);
369 private final Map<Long, FlowRuleBatchEntry> fms; 375 private final Map<Long, FlowRuleBatchEntry> fms;
370 376
377 +
371 private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet(); 378 private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet();
379 + private Long failedId;
372 380
373 private final CountDownLatch countDownLatch; 381 private final CountDownLatch countDownLatch;
374 private BatchState state; 382 private BatchState state;
375 383
376 - private final ExecutionList executionList = new ExecutionList();
377 -
378 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) { 384 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
379 this.xid = xidCounter.getAndIncrement(); 385 this.xid = xidCounter.getAndIncrement();
380 this.state = BatchState.STARTED; 386 this.state = BatchState.STARTED;
...@@ -393,6 +399,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -393,6 +399,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
393 removeRequirement(dpid); 399 removeRequirement(dpid);
394 FlowEntry fe = null; 400 FlowEntry fe = null;
395 FlowRuleBatchEntry fbe = fms.get(msg.getXid()); 401 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
402 + failedId = fbe.id();
396 FlowRule offending = fbe.getTarget(); 403 FlowRule offending = fbe.getTarget();
397 //TODO handle specific error msgs 404 //TODO handle specific error msgs
398 switch (msg.getErrType()) { 405 switch (msg.getErrType()) {
...@@ -492,8 +499,11 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -492,8 +499,11 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
492 public CompletedBatchOperation get() throws InterruptedException, ExecutionException { 499 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
493 countDownLatch.await(); 500 countDownLatch.await();
494 this.state = BatchState.FINISHED; 501 this.state = BatchState.FINISHED;
495 - CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); 502 + Set<Long> failedIds = (failedId != null) ? Sets.newHashSet(failedId) : Collections.emptySet();
496 - //FIXME do cleanup here 503 + CompletedBatchOperation result =
504 + new CompletedBatchOperation(ok.get(), offendingFlowMods, failedIds);
505 + //FIXME do cleanup here (moved by BOC)
506 + cleanUp();
497 return result; 507 return result;
498 } 508 }
499 509
...@@ -503,8 +513,11 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -503,8 +513,11 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
503 TimeoutException { 513 TimeoutException {
504 if (countDownLatch.await(timeout, unit)) { 514 if (countDownLatch.await(timeout, unit)) {
505 this.state = BatchState.FINISHED; 515 this.state = BatchState.FINISHED;
506 - CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); 516 + Set<Long> failedIds = (failedId != null) ? Sets.newHashSet(failedId) : Collections.emptySet();
507 - // FIXME do cleanup here 517 + CompletedBatchOperation result =
518 + new CompletedBatchOperation(ok.get(), offendingFlowMods, failedIds);
519 + // FIXME do cleanup here (moved by BOC)
520 + cleanUp();
508 return result; 521 return result;
509 } 522 }
510 throw new TimeoutException(); 523 throw new TimeoutException();
...@@ -522,8 +535,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -522,8 +535,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
522 private void removeRequirement(Dpid dpid) { 535 private void removeRequirement(Dpid dpid) {
523 countDownLatch.countDown(); 536 countDownLatch.countDown();
524 sws.remove(dpid); 537 sws.remove(dpid);
525 - //FIXME don't do cleanup here 538 + //FIXME don't do cleanup here (moved by BOC)
526 - cleanUp(); 539 + //cleanUp();
527 } 540 }
528 } 541 }
529 542
......