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 | } | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -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)); | ... | ... |
This diff is collapsed. Click to expand it.
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? | ... | ... |
providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
... | @@ -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 | ... | ... |
-
Please register or login to post a comment