For ONOS-356
- Add current InstallationFuture information on TimeoutException - Set timeout values propotional to batch size - Fix for ConcurrentModificationException - Check if src/dst is part of the graph before path computation Change-Id: Iabeac7939c52502b83bf9ebcbe2023539de3ae99
Showing
8 changed files
with
94 additions
and
23 deletions
| ... | @@ -132,7 +132,7 @@ public class IntentPushTestCommand extends AbstractShellCommand | ... | @@ -132,7 +132,7 @@ public class IntentPushTestCommand extends AbstractShellCommand |
| 132 | start = System.currentTimeMillis(); | 132 | start = System.currentTimeMillis(); |
| 133 | service.execute(ops); | 133 | service.execute(ops); |
| 134 | try { | 134 | try { |
| 135 | - if (latch.await(30, TimeUnit.SECONDS)) { | 135 | + if (latch.await(100 + count * 200, TimeUnit.MILLISECONDS)) { |
| 136 | printResults(count); | 136 | printResults(count); |
| 137 | } else { | 137 | } else { |
| 138 | print("Failure: %d intents not installed", latch.getCount()); | 138 | print("Failure: %d intents not installed", latch.getCount()); | ... | ... |
| ... | @@ -17,9 +17,9 @@ package org.onlab.onos.net.flow; | ... | @@ -17,9 +17,9 @@ package org.onlab.onos.net.flow; |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | import java.util.Collections; | 19 | import java.util.Collections; |
| 20 | - | ||
| 21 | import java.util.Set; | 20 | import java.util.Set; |
| 22 | 21 | ||
| 22 | +import com.google.common.base.MoreObjects; | ||
| 23 | import com.google.common.collect.ImmutableSet; | 23 | import com.google.common.collect.ImmutableSet; |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| ... | @@ -73,4 +73,12 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { | ... | @@ -73,4 +73,12 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { |
| 73 | return failedIds; | 73 | return failedIds; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | + @Override | ||
| 77 | + public String toString() { | ||
| 78 | + return MoreObjects.toStringHelper(getClass()) | ||
| 79 | + .add("success?", success) | ||
| 80 | + .add("failedItems", failures) | ||
| 81 | + .add("failedIds", failedIds) | ||
| 82 | + .toString(); | ||
| 83 | + } | ||
| 76 | } | 84 | } | ... | ... |
| ... | @@ -67,7 +67,6 @@ import java.util.concurrent.Future; | ... | @@ -67,7 +67,6 @@ import java.util.concurrent.Future; |
| 67 | import java.util.concurrent.TimeUnit; | 67 | import java.util.concurrent.TimeUnit; |
| 68 | import java.util.concurrent.TimeoutException; | 68 | import java.util.concurrent.TimeoutException; |
| 69 | import java.util.concurrent.atomic.AtomicReference; | 69 | import java.util.concurrent.atomic.AtomicReference; |
| 70 | - | ||
| 71 | import static com.google.common.base.Preconditions.checkNotNull; | 70 | import static com.google.common.base.Preconditions.checkNotNull; |
| 72 | import static org.onlab.util.Tools.namedThreads; | 71 | import static org.onlab.util.Tools.namedThreads; |
| 73 | import static org.slf4j.LoggerFactory.getLogger; | 72 | import static org.slf4j.LoggerFactory.getLogger; |
| ... | @@ -232,7 +231,7 @@ public class FlowRuleManager | ... | @@ -232,7 +231,7 @@ public class FlowRuleManager |
| 232 | lastSeen.remove(flowEntry); | 231 | lastSeen.remove(flowEntry); |
| 233 | FlowEntry stored = store.getFlowEntry(flowEntry); | 232 | FlowEntry stored = store.getFlowEntry(flowEntry); |
| 234 | if (stored == null) { | 233 | if (stored == null) { |
| 235 | - log.info("Rule already evicted from store: {}", flowEntry); | 234 | + log.debug("Rule already evicted from store: {}", flowEntry); |
| 236 | return; | 235 | return; |
| 237 | } | 236 | } |
| 238 | Device device = deviceService.getDevice(flowEntry.deviceId()); | 237 | Device device = deviceService.getDevice(flowEntry.deviceId()); |
| ... | @@ -378,7 +377,8 @@ public class FlowRuleManager | ... | @@ -378,7 +377,8 @@ public class FlowRuleManager |
| 378 | // Store delegate to re-post events emitted from the store. | 377 | // Store delegate to re-post events emitted from the store. |
| 379 | private class InternalStoreDelegate implements FlowRuleStoreDelegate { | 378 | private class InternalStoreDelegate implements FlowRuleStoreDelegate { |
| 380 | 379 | ||
| 381 | - private static final int TIMEOUT = 5000; // ms | 380 | + // FIXME set appropriate default and make it configurable |
| 381 | + private static final int TIMEOUT_PER_OP = 500; // ms | ||
| 382 | 382 | ||
| 383 | // TODO: Right now we only dispatch events at individual flowEntry level. | 383 | // TODO: Right now we only dispatch events at individual flowEntry level. |
| 384 | // It may be more efficient for also dispatch events as a batch. | 384 | // It may be more efficient for also dispatch events as a batch. |
| ... | @@ -407,7 +407,7 @@ public class FlowRuleManager | ... | @@ -407,7 +407,7 @@ public class FlowRuleManager |
| 407 | public void run() { | 407 | public void run() { |
| 408 | CompletedBatchOperation res; | 408 | CompletedBatchOperation res; |
| 409 | try { | 409 | try { |
| 410 | - res = result.get(TIMEOUT, TimeUnit.MILLISECONDS); | 410 | + res = result.get(TIMEOUT_PER_OP * batchOperation.size(), TimeUnit.MILLISECONDS); |
| 411 | store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res)); | 411 | store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res)); |
| 412 | } catch (TimeoutException | InterruptedException | ExecutionException e) { | 412 | } catch (TimeoutException | InterruptedException | ExecutionException e) { |
| 413 | log.warn("Something went wrong with the batch operation {}", | 413 | log.warn("Something went wrong with the batch operation {}", |
| ... | @@ -457,6 +457,10 @@ public class FlowRuleManager | ... | @@ -457,6 +457,10 @@ public class FlowRuleManager |
| 457 | if (state.get() == BatchState.FINISHED) { | 457 | if (state.get() == BatchState.FINISHED) { |
| 458 | return false; | 458 | return false; |
| 459 | } | 459 | } |
| 460 | + if (log.isDebugEnabled()) { | ||
| 461 | + log.debug("Cancelling FlowRuleBatchFuture", | ||
| 462 | + new RuntimeException("Just printing backtrace")); | ||
| 463 | + } | ||
| 460 | if (!state.compareAndSet(BatchState.STARTED, BatchState.CANCELLED)) { | 464 | if (!state.compareAndSet(BatchState.STARTED, BatchState.CANCELLED)) { |
| 461 | return false; | 465 | return false; |
| 462 | } | 466 | } |
| ... | @@ -526,6 +530,7 @@ public class FlowRuleManager | ... | @@ -526,6 +530,7 @@ public class FlowRuleManager |
| 526 | throw new CancellationException(); | 530 | throw new CancellationException(); |
| 527 | } | 531 | } |
| 528 | if (!completed.isSuccess()) { | 532 | if (!completed.isSuccess()) { |
| 533 | + log.warn("FlowRuleBatch failed: {}", completed); | ||
| 529 | failed.addAll(completed.failedItems()); | 534 | failed.addAll(completed.failedItems()); |
| 530 | failedIds.addAll(completed.failedIds()); | 535 | failedIds.addAll(completed.failedIds()); |
| 531 | cleanUpBatch(); | 536 | cleanUpBatch(); |
| ... | @@ -557,9 +562,11 @@ public class FlowRuleManager | ... | @@ -557,9 +562,11 @@ public class FlowRuleManager |
| 557 | } | 562 | } |
| 558 | 563 | ||
| 559 | private void cleanUpBatch() { | 564 | private void cleanUpBatch() { |
| 565 | + log.debug("cleaning up batch"); | ||
| 566 | + // TODO convert these into a batch? | ||
| 560 | for (FlowRuleBatchEntry fbe : batches.values()) { | 567 | for (FlowRuleBatchEntry fbe : batches.values()) { |
| 561 | if (fbe.getOperator() == FlowRuleOperation.ADD || | 568 | if (fbe.getOperator() == FlowRuleOperation.ADD || |
| 562 | - fbe.getOperator() == FlowRuleOperation.MODIFY) { | 569 | + fbe.getOperator() == FlowRuleOperation.MODIFY) { |
| 563 | store.deleteFlowRule(fbe.getTarget()); | 570 | store.deleteFlowRule(fbe.getTarget()); |
| 564 | } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) { | 571 | } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) { |
| 565 | store.removeFlowRule(new DefaultFlowEntry(fbe.getTarget())); | 572 | store.removeFlowRule(new DefaultFlowEntry(fbe.getTarget())); | ... | ... |
| ... | @@ -734,7 +734,8 @@ public class IntentManager | ... | @@ -734,7 +734,8 @@ public class IntentManager |
| 734 | 734 | ||
| 735 | private class IntentInstallMonitor implements Runnable { | 735 | private class IntentInstallMonitor implements Runnable { |
| 736 | 736 | ||
| 737 | - private static final long TIMEOUT = 5000; // ms | 737 | + // TODO make this configurable |
| 738 | + private static final int TIMEOUT_PER_OP = 500; // ms | ||
| 738 | private static final int MAX_ATTEMPTS = 3; | 739 | private static final int MAX_ATTEMPTS = 3; |
| 739 | 740 | ||
| 740 | private final IntentOperations ops; | 741 | private final IntentOperations ops; |
| ... | @@ -742,11 +743,18 @@ public class IntentManager | ... | @@ -742,11 +743,18 @@ public class IntentManager |
| 742 | 743 | ||
| 743 | private Future<CompletedBatchOperation> future; | 744 | private Future<CompletedBatchOperation> future; |
| 744 | private long startTime = System.currentTimeMillis(); | 745 | private long startTime = System.currentTimeMillis(); |
| 745 | - private long endTime = startTime + TIMEOUT; | 746 | + private long endTime; |
| 746 | private int installAttempt; | 747 | private int installAttempt; |
| 747 | 748 | ||
| 748 | public IntentInstallMonitor(IntentOperations ops) { | 749 | public IntentInstallMonitor(IntentOperations ops) { |
| 749 | this.ops = ops; | 750 | this.ops = ops; |
| 751 | + resetTimeoutLimit(); | ||
| 752 | + } | ||
| 753 | + | ||
| 754 | + private void resetTimeoutLimit() { | ||
| 755 | + // FIXME compute reasonable timeouts | ||
| 756 | + this.endTime = System.currentTimeMillis() | ||
| 757 | + + ops.operations().size() * TIMEOUT_PER_OP; | ||
| 750 | } | 758 | } |
| 751 | 759 | ||
| 752 | private void buildIntentUpdates() { | 760 | private void buildIntentUpdates() { |
| ... | @@ -805,6 +813,7 @@ public class IntentManager | ... | @@ -805,6 +813,7 @@ public class IntentManager |
| 805 | */ | 813 | */ |
| 806 | private void processFutures() { | 814 | private void processFutures() { |
| 807 | if (future == null) { | 815 | if (future == null) { |
| 816 | + log.warn("I have no Future."); | ||
| 808 | return; //FIXME look at this | 817 | return; //FIXME look at this |
| 809 | } | 818 | } |
| 810 | try { | 819 | try { |
| ... | @@ -818,9 +827,10 @@ public class IntentManager | ... | @@ -818,9 +827,10 @@ public class IntentManager |
| 818 | } | 827 | } |
| 819 | 828 | ||
| 820 | private void retry() { | 829 | private void retry() { |
| 830 | + log.debug("Execution timed out, retrying."); | ||
| 821 | if (future.cancel(true)) { // cancel success; batch is reverted | 831 | if (future.cancel(true)) { // cancel success; batch is reverted |
| 822 | // reset the timer | 832 | // reset the timer |
| 823 | - endTime = System.currentTimeMillis() + TIMEOUT; | 833 | + resetTimeoutLimit(); |
| 824 | if (installAttempt++ >= MAX_ATTEMPTS) { | 834 | if (installAttempt++ >= MAX_ATTEMPTS) { |
| 825 | log.warn("Install request timed out: {}", ops); | 835 | log.warn("Install request timed out: {}", ops); |
| 826 | for (IntentUpdate update : intentUpdates) { | 836 | for (IntentUpdate update : intentUpdates) { | ... | ... |
| ... | @@ -169,8 +169,10 @@ public class ObjectiveTracker implements ObjectiveTrackerService { | ... | @@ -169,8 +169,10 @@ public class ObjectiveTracker implements ObjectiveTrackerService { |
| 169 | linkEvent.subject().isDurable())) { | 169 | linkEvent.subject().isDurable())) { |
| 170 | final LinkKey linkKey = linkKey(linkEvent.subject()); | 170 | final LinkKey linkKey = linkKey(linkEvent.subject()); |
| 171 | Set<IntentId> intentIds = intentsByLink.get(linkKey); | 171 | Set<IntentId> intentIds = intentsByLink.get(linkKey); |
| 172 | - log.debug("recompile triggered by LinkDown {} {}", linkKey, intentIds); | 172 | + synchronized (intentsByLink) { |
| 173 | - toBeRecompiled.addAll(intentIds); | 173 | + log.debug("recompile triggered by LinkDown {} {}", linkKey, intentIds); |
| 174 | + toBeRecompiled.addAll(intentIds); | ||
| 175 | + } | ||
| 174 | } | 176 | } |
| 175 | recompileOnly = recompileOnly && | 177 | recompileOnly = recompileOnly && |
| 176 | (linkEvent.type() == LINK_REMOVED || | 178 | (linkEvent.type() == LINK_REMOVED || | ... | ... |
| ... | @@ -262,9 +262,16 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -262,9 +262,16 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 262 | * @return set of shortest paths | 262 | * @return set of shortest paths |
| 263 | */ | 263 | */ |
| 264 | Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { | 264 | Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { |
| 265 | + final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); | ||
| 266 | + final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); | ||
| 267 | + Set<TopologyVertex> vertices = graph.getVertexes(); | ||
| 268 | + if (!vertices.contains(srcV) || !vertices.contains(dstV)) { | ||
| 269 | + // src or dst not part of the current graph | ||
| 270 | + return ImmutableSet.of(); | ||
| 271 | + } | ||
| 272 | + | ||
| 265 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = | 273 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = |
| 266 | - DIJKSTRA.search(graph, new DefaultTopologyVertex(src), | 274 | + DIJKSTRA.search(graph, srcV, dstV, weight); |
| 267 | - new DefaultTopologyVertex(dst), weight); | ||
| 268 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); | 275 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); |
| 269 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | 276 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { |
| 270 | builder.add(networkPath(path)); | 277 | builder.add(networkPath(path)); | ... | ... |
| ... | @@ -262,9 +262,16 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -262,9 +262,16 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 262 | * @return set of shortest paths | 262 | * @return set of shortest paths |
| 263 | */ | 263 | */ |
| 264 | Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { | 264 | Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { |
| 265 | + final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); | ||
| 266 | + final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); | ||
| 267 | + Set<TopologyVertex> vertices = graph.getVertexes(); | ||
| 268 | + if (!vertices.contains(srcV) || !vertices.contains(dstV)) { | ||
| 269 | + // src or dst not part of the current graph | ||
| 270 | + return ImmutableSet.of(); | ||
| 271 | + } | ||
| 272 | + | ||
| 265 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = | 273 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = |
| 266 | - DIJKSTRA.search(graph, new DefaultTopologyVertex(src), | 274 | + DIJKSTRA.search(graph, srcV, dstV, weight); |
| 267 | - new DefaultTopologyVertex(dst), weight); | ||
| 268 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); | 275 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); |
| 269 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | 276 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { |
| 270 | builder.add(networkPath(path)); | 277 | builder.add(networkPath(path)); | ... | ... |
providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
| ... | @@ -15,10 +15,12 @@ | ... | @@ -15,10 +15,12 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onlab.onos.provider.of.flow.impl; | 16 | package org.onlab.onos.provider.of.flow.impl; |
| 17 | 17 | ||
| 18 | +import com.google.common.base.MoreObjects; | ||
| 18 | import com.google.common.collect.ArrayListMultimap; | 19 | import com.google.common.collect.ArrayListMultimap; |
| 19 | import com.google.common.collect.Maps; | 20 | import com.google.common.collect.Maps; |
| 20 | import com.google.common.collect.Multimap; | 21 | import com.google.common.collect.Multimap; |
| 21 | import com.google.common.collect.Sets; | 22 | import com.google.common.collect.Sets; |
| 23 | + | ||
| 22 | import org.apache.felix.scr.annotations.Activate; | 24 | import org.apache.felix.scr.annotations.Activate; |
| 23 | import org.apache.felix.scr.annotations.Component; | 25 | import org.apache.felix.scr.annotations.Component; |
| 24 | import org.apache.felix.scr.annotations.Deactivate; | 26 | import org.apache.felix.scr.annotations.Deactivate; |
| ... | @@ -85,7 +87,9 @@ import java.util.concurrent.TimeUnit; | ... | @@ -85,7 +87,9 @@ import java.util.concurrent.TimeUnit; |
| 85 | import java.util.concurrent.TimeoutException; | 87 | import java.util.concurrent.TimeoutException; |
| 86 | import java.util.concurrent.atomic.AtomicBoolean; | 88 | import java.util.concurrent.atomic.AtomicBoolean; |
| 87 | import java.util.concurrent.atomic.AtomicLong; | 89 | import java.util.concurrent.atomic.AtomicLong; |
| 90 | +import java.util.stream.Collectors; | ||
| 88 | 91 | ||
| 92 | +import static com.google.common.base.Preconditions.checkState; | ||
| 89 | import static org.slf4j.LoggerFactory.getLogger; | 93 | import static org.slf4j.LoggerFactory.getLogger; |
| 90 | 94 | ||
| 91 | /** | 95 | /** |
| ... | @@ -191,9 +195,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -191,9 +195,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 191 | 195 | ||
| 192 | @Override | 196 | @Override |
| 193 | public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) { | 197 | public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) { |
| 194 | - final Set<Dpid> sws = | 198 | + final Set<Dpid> sws = Sets.newConcurrentHashSet(); |
| 195 | - Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>()); | 199 | + final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<>(); |
| 196 | - final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>(); | ||
| 197 | /* | 200 | /* |
| 198 | * Use identity hash map for reference equality as we could have equal | 201 | * Use identity hash map for reference equality as we could have equal |
| 199 | * flow mods for different switches. | 202 | * flow mods for different switches. |
| ... | @@ -201,7 +204,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -201,7 +204,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 201 | Map<OFFlowMod, OpenFlowSwitch> mods = Maps.newIdentityHashMap(); | 204 | Map<OFFlowMod, OpenFlowSwitch> mods = Maps.newIdentityHashMap(); |
| 202 | for (FlowRuleBatchEntry fbe : batch.getOperations()) { | 205 | for (FlowRuleBatchEntry fbe : batch.getOperations()) { |
| 203 | FlowRule flowRule = fbe.getTarget(); | 206 | FlowRule flowRule = fbe.getTarget(); |
| 204 | - OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); | 207 | + final Dpid dpid = Dpid.dpid(flowRule.deviceId().uri()); |
| 208 | + OpenFlowSwitch sw = controller.getSwitch(dpid); | ||
| 205 | if (sw == null) { | 209 | if (sw == null) { |
| 206 | /* | 210 | /* |
| 207 | * if a switch we are supposed to install to is gone then | 211 | * if a switch we are supposed to install to is gone then |
| ... | @@ -212,8 +216,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -212,8 +216,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 212 | failed.cancel(true); | 216 | failed.cancel(true); |
| 213 | return failed; | 217 | return failed; |
| 214 | } | 218 | } |
| 215 | - sws.add(new Dpid(sw.getId())); | 219 | + sws.add(dpid); |
| 216 | - Long flowModXid = xidCounter.getAndIncrement(); | 220 | + final Long flowModXid = xidCounter.getAndIncrement(); |
| 217 | FlowModBuilder builder = | 221 | FlowModBuilder builder = |
| 218 | FlowModBuilder.builder(flowRule, sw.factory(), | 222 | FlowModBuilder.builder(flowRule, sw.factory(), |
| 219 | Optional.of(flowModXid)); | 223 | Optional.of(flowModXid)); |
| ... | @@ -302,12 +306,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -302,12 +306,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 302 | future = pendingFutures.get(msg.getXid()); | 306 | future = pendingFutures.get(msg.getXid()); |
| 303 | if (future != null) { | 307 | if (future != null) { |
| 304 | future.satisfyRequirement(dpid); | 308 | future.satisfyRequirement(dpid); |
| 309 | + } else { | ||
| 310 | + log.warn("Received unknown Barrier Reply: {}", msg.getXid()); | ||
| 305 | } | 311 | } |
| 306 | break; | 312 | break; |
| 307 | case ERROR: | 313 | case ERROR: |
| 314 | + log.warn("received Error message {} from {}", msg, dpid); | ||
| 308 | future = pendingFMs.get(msg.getXid()); | 315 | future = pendingFMs.get(msg.getXid()); |
| 309 | if (future != null) { | 316 | if (future != null) { |
| 310 | future.fail((OFErrorMsg) msg, dpid); | 317 | future.fail((OFErrorMsg) msg, dpid); |
| 318 | + } else { | ||
| 319 | + log.warn("Received unknown Error Reply: {} {}", msg.getXid(), msg); | ||
| 311 | } | 320 | } |
| 312 | break; | 321 | break; |
| 313 | default: | 322 | default: |
| ... | @@ -369,13 +378,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -369,13 +378,17 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 369 | 378 | ||
| 370 | private class InstallationFuture implements Future<CompletedBatchOperation> { | 379 | private class InstallationFuture implements Future<CompletedBatchOperation> { |
| 371 | 380 | ||
| 381 | + // barrier xid | ||
| 372 | private final Long xid; | 382 | private final Long xid; |
| 383 | + // waiting for barrier reply from... | ||
| 373 | private final Set<Dpid> sws; | 384 | private final Set<Dpid> sws; |
| 374 | private final AtomicBoolean ok = new AtomicBoolean(true); | 385 | private final AtomicBoolean ok = new AtomicBoolean(true); |
| 386 | + // FlowMod xid -> | ||
| 375 | private final Map<Long, FlowRuleBatchEntry> fms; | 387 | private final Map<Long, FlowRuleBatchEntry> fms; |
| 376 | 388 | ||
| 377 | 389 | ||
| 378 | private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet(); | 390 | private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet(); |
| 391 | + // Failed batch operation id | ||
| 379 | private Long failedId; | 392 | private Long failedId; |
| 380 | 393 | ||
| 381 | private final CountDownLatch countDownLatch; | 394 | private final CountDownLatch countDownLatch; |
| ... | @@ -456,6 +469,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -456,6 +469,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 456 | 469 | ||
| 457 | 470 | ||
| 458 | public void verify() { | 471 | public void verify() { |
| 472 | + checkState(!sws.isEmpty()); | ||
| 459 | for (Dpid dpid : sws) { | 473 | for (Dpid dpid : sws) { |
| 460 | OpenFlowSwitch sw = controller.getSwitch(dpid); | 474 | OpenFlowSwitch sw = controller.getSwitch(dpid); |
| 461 | OFBarrierRequest.Builder builder = sw.factory() | 475 | OFBarrierRequest.Builder builder = sw.factory() |
| ... | @@ -520,7 +534,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -520,7 +534,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 520 | cleanUp(); | 534 | cleanUp(); |
| 521 | return result; | 535 | return result; |
| 522 | } | 536 | } |
| 523 | - throw new TimeoutException(); | 537 | + throw new TimeoutException(this.toString()); |
| 524 | } | 538 | } |
| 525 | 539 | ||
| 526 | private void cleanUp() { | 540 | private void cleanUp() { |
| ... | @@ -538,6 +552,22 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -538,6 +552,22 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
| 538 | //FIXME don't do cleanup here (moved by BOC) | 552 | //FIXME don't do cleanup here (moved by BOC) |
| 539 | //cleanUp(); | 553 | //cleanUp(); |
| 540 | } | 554 | } |
| 555 | + | ||
| 556 | + @Override | ||
| 557 | + public String toString() { | ||
| 558 | + return MoreObjects.toStringHelper(getClass()) | ||
| 559 | + .add("xid", xid) | ||
| 560 | + .add("pending devices", sws) | ||
| 561 | + .add("devices in batch", | ||
| 562 | + fms.values().stream() | ||
| 563 | + .map((fbe) -> fbe.getTarget().deviceId()) | ||
| 564 | + .distinct().collect(Collectors.toList())) | ||
| 565 | + .add("failedId", failedId) | ||
| 566 | + .add("latchCount", countDownLatch.getCount()) | ||
| 567 | + .add("state", state) | ||
| 568 | + .add("no error?", ok.get()) | ||
| 569 | + .toString(); | ||
| 570 | + } | ||
| 541 | } | 571 | } |
| 542 | 572 | ||
| 543 | } | 573 | } | ... | ... |
-
Please register or login to post a comment