ONOS-4604 Fixed flow objective installation
Removed context from objective toString methods. Removed duplicate flow objective delegate notifications in the store for next objectives. Synchronized queueing of forwarding objectives for pending next objectives to avoid notifications race. Changed logging for better readability. Change-Id: Ic2bd411a891ea035a2c5513b24dea5fbd48f187d
Showing
6 changed files
with
38 additions
and
28 deletions
... | @@ -160,7 +160,6 @@ public final class DefaultFilteringObjective implements FilteringObjective { | ... | @@ -160,7 +160,6 @@ public final class DefaultFilteringObjective implements FilteringObjective { |
160 | .add("appId", appId()) | 160 | .add("appId", appId()) |
161 | .add("permanent", permanent()) | 161 | .add("permanent", permanent()) |
162 | .add("timeout", timeout()) | 162 | .add("timeout", timeout()) |
163 | - .add("context", context()) | ||
164 | .toString(); | 163 | .toString(); |
165 | } | 164 | } |
166 | 165 | ... | ... |
... | @@ -169,7 +169,6 @@ public final class DefaultForwardingObjective implements ForwardingObjective { | ... | @@ -169,7 +169,6 @@ public final class DefaultForwardingObjective implements ForwardingObjective { |
169 | .add("appId", appId()) | 169 | .add("appId", appId()) |
170 | .add("permanent", permanent()) | 170 | .add("permanent", permanent()) |
171 | .add("timeout", timeout()) | 171 | .add("timeout", timeout()) |
172 | - .add("context", context()) | ||
173 | .toString(); | 172 | .toString(); |
174 | } | 173 | } |
175 | 174 | ... | ... |
... | @@ -138,7 +138,6 @@ public final class DefaultNextObjective implements NextObjective { | ... | @@ -138,7 +138,6 @@ public final class DefaultNextObjective implements NextObjective { |
138 | .add("appId", appId()) | 138 | .add("appId", appId()) |
139 | .add("permanent", permanent()) | 139 | .add("permanent", permanent()) |
140 | .add("timeout", timeout()) | 140 | .add("timeout", timeout()) |
141 | - .add("context", context()) | ||
142 | .toString(); | 141 | .toString(); |
143 | } | 142 | } |
144 | 143 | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | package org.onosproject.net.flowobjective.impl; | 16 | package org.onosproject.net.flowobjective.impl; |
17 | 17 | ||
18 | import com.google.common.collect.Maps; | 18 | import com.google.common.collect.Maps; |
19 | +import com.google.common.collect.Sets; | ||
19 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
20 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
21 | import org.apache.felix.scr.annotations.Deactivate; | 22 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -55,21 +56,17 @@ import org.slf4j.Logger; | ... | @@ -55,21 +56,17 @@ import org.slf4j.Logger; |
55 | import org.slf4j.LoggerFactory; | 56 | import org.slf4j.LoggerFactory; |
56 | 57 | ||
57 | import java.util.ArrayList; | 58 | import java.util.ArrayList; |
58 | -import java.util.Collections; | ||
59 | import java.util.List; | 59 | import java.util.List; |
60 | import java.util.Map; | 60 | import java.util.Map; |
61 | import java.util.Objects; | 61 | import java.util.Objects; |
62 | import java.util.Set; | 62 | import java.util.Set; |
63 | -import java.util.concurrent.ConcurrentHashMap; | ||
64 | import java.util.concurrent.ExecutorService; | 63 | import java.util.concurrent.ExecutorService; |
65 | 64 | ||
66 | import static com.google.common.base.Preconditions.checkNotNull; | 65 | import static com.google.common.base.Preconditions.checkNotNull; |
67 | import static java.util.concurrent.Executors.newFixedThreadPool; | 66 | import static java.util.concurrent.Executors.newFixedThreadPool; |
68 | import static org.onlab.util.Tools.groupedThreads; | 67 | import static org.onlab.util.Tools.groupedThreads; |
69 | import static org.onosproject.security.AppGuard.checkPermission; | 68 | import static org.onosproject.security.AppGuard.checkPermission; |
70 | -import static org.onosproject.security.AppPermission.Type.*; | 69 | +import static org.onosproject.security.AppPermission.Type.FLOWRULE_WRITE; |
71 | - | ||
72 | - | ||
73 | 70 | ||
74 | /** | 71 | /** |
75 | * Provides implementation of the flow objective programming service. | 72 | * Provides implementation of the flow objective programming service. |
... | @@ -124,7 +121,7 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -124,7 +121,7 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
124 | 121 | ||
125 | protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); | 122 | protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); |
126 | 123 | ||
127 | - private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap(); | 124 | + private final Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap(); |
128 | 125 | ||
129 | // local store to track which nextObjectives were sent to which device | 126 | // local store to track which nextObjectives were sent to which device |
130 | // for debugging purposes | 127 | // for debugging purposes |
... | @@ -237,21 +234,33 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -237,21 +234,33 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
237 | public void initPolicy(String policy) {} | 234 | public void initPolicy(String policy) {} |
238 | 235 | ||
239 | private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) { | 236 | private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) { |
240 | - if (fwd.nextId() != null && | 237 | + if (fwd.nextId() == null || |
241 | - flowObjectiveStore.getNextGroup(fwd.nextId()) == null) { | 238 | + flowObjectiveStore.getNextGroup(fwd.nextId()) != null) { |
242 | - log.debug("Queuing forwarding objective {} for nextId {} meant for device {}", | 239 | + // fast path |
243 | - fwd.id(), fwd.nextId(), deviceId); | 240 | + return false; |
244 | - // TODO: change to computeIfAbsent | 241 | + } |
245 | - Set<PendingNext> newset = Collections.newSetFromMap( | 242 | + boolean queued = false; |
246 | - new ConcurrentHashMap<PendingNext, Boolean>()); | 243 | + synchronized (pendingForwards) { |
247 | - newset.add(new PendingNext(deviceId, fwd)); | 244 | + // double check the flow objective store, because this block could run |
248 | - Set<PendingNext> pnext = pendingForwards.putIfAbsent(fwd.nextId(), newset); | 245 | + // after a notification arrives |
249 | - if (pnext != null) { | 246 | + if (flowObjectiveStore.getNextGroup(fwd.nextId()) == null) { |
250 | - pnext.add(new PendingNext(deviceId, fwd)); | 247 | + pendingForwards.compute(fwd.nextId(), (id, pending) -> { |
248 | + PendingNext next = new PendingNext(deviceId, fwd); | ||
249 | + if (pending == null) { | ||
250 | + return Sets.newHashSet(next); | ||
251 | + } else { | ||
252 | + pending.add(next); | ||
253 | + return pending; | ||
254 | + } | ||
255 | + }); | ||
256 | + queued = true; | ||
251 | } | 257 | } |
252 | - return true; | ||
253 | } | 258 | } |
254 | - return false; | 259 | + if (queued) { |
260 | + log.debug("Queued forwarding objective {} for nextId {} meant for device {}", | ||
261 | + fwd.id(), fwd.nextId(), deviceId); | ||
262 | + } | ||
263 | + return queued; | ||
255 | } | 264 | } |
256 | 265 | ||
257 | // Retrieves the device pipeline behaviour from the cache. | 266 | // Retrieves the device pipeline behaviour from the cache. |
... | @@ -396,7 +405,11 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -396,7 +405,11 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
396 | public void notify(ObjectiveEvent event) { | 405 | public void notify(ObjectiveEvent event) { |
397 | if (event.type() == Type.ADD) { | 406 | if (event.type() == Type.ADD) { |
398 | log.debug("Received notification of obj event {}", event); | 407 | log.debug("Received notification of obj event {}", event); |
399 | - Set<PendingNext> pending = pendingForwards.remove(event.subject()); | 408 | + Set<PendingNext> pending; |
409 | + synchronized (pendingForwards) { | ||
410 | + // needs to be synchronized for queueObjective lookup | ||
411 | + pending = pendingForwards.remove(event.subject()); | ||
412 | + } | ||
400 | 413 | ||
401 | if (pending == null) { | 414 | if (pending == null) { |
402 | log.debug("Nothing pending for this obj event {}", event); | 415 | log.debug("Nothing pending for this obj event {}", event); | ... | ... |
... | @@ -120,7 +120,7 @@ class IntentInstaller { | ... | @@ -120,7 +120,7 @@ class IntentInstaller { |
120 | // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT) | 120 | // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT) |
121 | if (toInstall.isPresent()) { | 121 | if (toInstall.isPresent()) { |
122 | IntentData installData = toInstall.get(); | 122 | IntentData installData = toInstall.get(); |
123 | - log.warn("Failed installation: {} {} on {}", | 123 | + log.warn("Failed installation: {} {} due to {}", |
124 | installData.key(), installData.intent(), ctx.error()); | 124 | installData.key(), installData.intent(), ctx.error()); |
125 | installData.setState(CORRUPT); | 125 | installData.setState(CORRUPT); |
126 | installData.incrementErrorCount(); | 126 | installData.incrementErrorCount(); |
... | @@ -129,7 +129,7 @@ class IntentInstaller { | ... | @@ -129,7 +129,7 @@ class IntentInstaller { |
129 | // if toUninstall was cause of error, then CORRUPT (another job will clean this up) | 129 | // if toUninstall was cause of error, then CORRUPT (another job will clean this up) |
130 | if (toUninstall.isPresent()) { | 130 | if (toUninstall.isPresent()) { |
131 | IntentData uninstallData = toUninstall.get(); | 131 | IntentData uninstallData = toUninstall.get(); |
132 | - log.warn("Failed withdrawal: {} {} on {}", | 132 | + log.warn("Failed withdrawal: {} {} due to {}", |
133 | uninstallData.key(), uninstallData.intent(), ctx.error()); | 133 | uninstallData.key(), uninstallData.intent(), ctx.error()); |
134 | uninstallData.setState(CORRUPT); | 134 | uninstallData.setState(CORRUPT); |
135 | uninstallData.incrementErrorCount(); | 135 | uninstallData.incrementErrorCount(); |
... | @@ -355,6 +355,7 @@ class IntentInstaller { | ... | @@ -355,6 +355,7 @@ class IntentInstaller { |
355 | private class FlowObjectiveInstallationContext implements ObjectiveContext { | 355 | private class FlowObjectiveInstallationContext implements ObjectiveContext { |
356 | Objective objective; | 356 | Objective objective; |
357 | DeviceId deviceId; | 357 | DeviceId deviceId; |
358 | + ObjectiveError error; | ||
358 | 359 | ||
359 | void setObjective(Objective objective, DeviceId deviceId) { | 360 | void setObjective(Objective objective, DeviceId deviceId) { |
360 | this.objective = objective; | 361 | this.objective = objective; |
... | @@ -368,6 +369,7 @@ class IntentInstaller { | ... | @@ -368,6 +369,7 @@ class IntentInstaller { |
368 | 369 | ||
369 | @Override | 370 | @Override |
370 | public void onError(Objective objective, ObjectiveError error) { | 371 | public void onError(Objective objective, ObjectiveError error) { |
372 | + this.error = error; | ||
371 | errorContexts.add(this); | 373 | errorContexts.add(this); |
372 | finish(); | 374 | finish(); |
373 | } | 375 | } |
... | @@ -387,7 +389,7 @@ class IntentInstaller { | ... | @@ -387,7 +389,7 @@ class IntentInstaller { |
387 | 389 | ||
388 | @Override | 390 | @Override |
389 | public String toString() { | 391 | public String toString() { |
390 | - return String.format("(%s, %s)", deviceId, objective); | 392 | + return String.format("(%s on %s for %s)", error, deviceId, objective); |
391 | } | 393 | } |
392 | } | 394 | } |
393 | } | 395 | } | ... | ... |
... | @@ -97,7 +97,6 @@ public class DistributedFlowObjectiveStore | ... | @@ -97,7 +97,6 @@ public class DistributedFlowObjectiveStore |
97 | @Override | 97 | @Override |
98 | public void putNextGroup(Integer nextId, NextGroup group) { | 98 | public void putNextGroup(Integer nextId, NextGroup group) { |
99 | nextGroups.put(nextId, group.data()); | 99 | nextGroups.put(nextId, group.data()); |
100 | - notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.ADD, nextId)); | ||
101 | } | 100 | } |
102 | 101 | ||
103 | @Override | 102 | @Override |
... | @@ -113,7 +112,6 @@ public class DistributedFlowObjectiveStore | ... | @@ -113,7 +112,6 @@ public class DistributedFlowObjectiveStore |
113 | public NextGroup removeNextGroup(Integer nextId) { | 112 | public NextGroup removeNextGroup(Integer nextId) { |
114 | Versioned<byte[]> versionGroup = nextGroups.remove(nextId); | 113 | Versioned<byte[]> versionGroup = nextGroups.remove(nextId); |
115 | if (versionGroup != null) { | 114 | if (versionGroup != null) { |
116 | - notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.REMOVE, nextId)); | ||
117 | return new DefaultNextGroup(versionGroup.value()); | 115 | return new DefaultNextGroup(versionGroup.value()); |
118 | } | 116 | } |
119 | return null; | 117 | return null; | ... | ... |
-
Please register or login to post a comment