Committed by
Brian O'Connor
Various BMv2 bugfixes
Change-Id: Ia5a2a1c86b8a90ad68ddb92980377f6308e200d2
Showing
10 changed files
with
42 additions
and
34 deletions
... | @@ -64,6 +64,8 @@ import java.util.concurrent.ConcurrentMap; | ... | @@ -64,6 +64,8 @@ import java.util.concurrent.ConcurrentMap; |
64 | import java.util.concurrent.ExecutorService; | 64 | import java.util.concurrent.ExecutorService; |
65 | import java.util.concurrent.Executors; | 65 | import java.util.concurrent.Executors; |
66 | import java.util.concurrent.TimeUnit; | 66 | import java.util.concurrent.TimeUnit; |
67 | +import java.util.concurrent.locks.Lock; | ||
68 | +import java.util.concurrent.locks.ReentrantLock; | ||
67 | import java.util.stream.Collectors; | 69 | import java.util.stream.Collectors; |
68 | import java.util.stream.Stream; | 70 | import java.util.stream.Stream; |
69 | 71 | ||
... | @@ -87,7 +89,7 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -87,7 +89,7 @@ public abstract class AbstractUpgradableFabricApp { |
87 | private static final int NUM_SPINES = 3; | 89 | private static final int NUM_SPINES = 3; |
88 | private static final int FLOW_PRIORITY = 100; | 90 | private static final int FLOW_PRIORITY = 100; |
89 | 91 | ||
90 | - private static final int CLEANUP_SLEEP = 1000; | 92 | + private static final int CLEANUP_SLEEP = 2000; |
91 | 93 | ||
92 | protected final Logger log = getLogger(getClass()); | 94 | protected final Logger log = getLogger(getClass()); |
93 | 95 | ||
... | @@ -137,10 +139,11 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -137,10 +139,11 @@ public abstract class AbstractUpgradableFabricApp { |
137 | private Set<DeviceId> spineSwitches; | 139 | private Set<DeviceId> spineSwitches; |
138 | 140 | ||
139 | private Map<DeviceId, List<FlowRule>> deviceFlowRules; | 141 | private Map<DeviceId, List<FlowRule>> deviceFlowRules; |
142 | + private Map<DeviceId, Bmv2DeviceContext> previousContexts; | ||
140 | private Map<DeviceId, Boolean> contextFlags; | 143 | private Map<DeviceId, Boolean> contextFlags; |
141 | private Map<DeviceId, Boolean> ruleFlags; | 144 | private Map<DeviceId, Boolean> ruleFlags; |
142 | 145 | ||
143 | - private ConcurrentMap<DeviceId, Boolean> deployLocks = Maps.newConcurrentMap(); | 146 | + private ConcurrentMap<DeviceId, Lock> deviceLocks = Maps.newConcurrentMap(); |
144 | 147 | ||
145 | /** | 148 | /** |
146 | * Creates a new BMv2 fabric app. | 149 | * Creates a new BMv2 fabric app. |
... | @@ -270,7 +273,7 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -270,7 +273,7 @@ public abstract class AbstractUpgradableFabricApp { |
270 | public abstract List<FlowRule> generateSpineRules(DeviceId deviceId, Collection<Host> dstHosts, Topology topology) | 273 | public abstract List<FlowRule> generateSpineRules(DeviceId deviceId, Collection<Host> dstHosts, Topology topology) |
271 | throws FlowRuleGeneratorException; | 274 | throws FlowRuleGeneratorException; |
272 | 275 | ||
273 | - private void deployRoutine() { | 276 | + private void deployAllDevices() { |
274 | if (otherAppFound && otherApp.appActive) { | 277 | if (otherAppFound && otherApp.appActive) { |
275 | log.info("Deactivating other app..."); | 278 | log.info("Deactivating other app..."); |
276 | appService.deactivate(otherApp.appId); | 279 | appService.deactivate(otherApp.appId); |
... | @@ -297,9 +300,10 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -297,9 +300,10 @@ public abstract class AbstractUpgradableFabricApp { |
297 | DeviceId deviceId = device.id(); | 300 | DeviceId deviceId = device.id(); |
298 | 301 | ||
299 | // Synchronize executions over the same device. | 302 | // Synchronize executions over the same device. |
300 | - deployLocks.putIfAbsent(deviceId, new Boolean(true)); | 303 | + Lock lock = deviceLocks.computeIfAbsent(deviceId, k -> new ReentrantLock()); |
301 | - synchronized (deployLocks.get(deviceId)) { | 304 | + lock.lock(); |
302 | 305 | ||
306 | + try { | ||
303 | // Set context if not already done. | 307 | // Set context if not already done. |
304 | if (!contextFlags.getOrDefault(deviceId, false)) { | 308 | if (!contextFlags.getOrDefault(deviceId, false)) { |
305 | log.info("Setting context to {} for {}...", configurationName, deviceId); | 309 | log.info("Setting context to {} for {}...", configurationName, deviceId); |
... | @@ -321,6 +325,8 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -321,6 +325,8 @@ public abstract class AbstractUpgradableFabricApp { |
321 | ruleFlags.put(deviceId, true); | 325 | ruleFlags.put(deviceId, true); |
322 | } | 326 | } |
323 | } | 327 | } |
328 | + } finally { | ||
329 | + lock.unlock(); | ||
324 | } | 330 | } |
325 | } | 331 | } |
326 | 332 | ||
... | @@ -433,10 +439,9 @@ public abstract class AbstractUpgradableFabricApp { | ... | @@ -433,10 +439,9 @@ public abstract class AbstractUpgradableFabricApp { |
433 | // Avoid other executions to modify the generated flow rules. | 439 | // Avoid other executions to modify the generated flow rules. |
434 | flowRuleGenerated = true; | 440 | flowRuleGenerated = true; |
435 | 441 | ||
436 | - log.info("DONE! Generated {} flow rules for {} devices...", newFlowRules.size(), spines.size() + leafs.size()); | 442 | + log.info("Generated {} flow rules for {} devices", newFlowRules.size(), spines.size() + leafs.size()); |
437 | 443 | ||
438 | - // Deploy configuration. | 444 | + spawnTask(this::deployAllDevices); |
439 | - spawnTask(this::deployRoutine); | ||
440 | } | 445 | } |
441 | 446 | ||
442 | /** | 447 | /** | ... | ... |
1 | -/Users/carmelo/workspace/onos-p4-dev/p4src/build/ecmp.json | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
... | @@ -105,7 +105,7 @@ public class WcmpFabricApp extends AbstractUpgradableFabricApp { | ... | @@ -105,7 +105,7 @@ public class WcmpFabricApp extends AbstractUpgradableFabricApp { |
105 | } | 105 | } |
106 | return true; | 106 | return true; |
107 | } catch (Bmv2RuntimeException e) { | 107 | } catch (Bmv2RuntimeException e) { |
108 | - log.error("Unable to init device {}: {}", deviceId, e.explain()); | 108 | + log.debug("Exception while initializing device {}: {}", deviceId, e.explain()); |
109 | return false; | 109 | return false; |
110 | } | 110 | } |
111 | } | 111 | } | ... | ... |
1 | -/Users/carmelo/workspace/onos-p4-dev/p4src/build/wcmp.json | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
... | @@ -18,6 +18,7 @@ package org.onosproject.drivers.bmv2; | ... | @@ -18,6 +18,7 @@ package org.onosproject.drivers.bmv2; |
18 | 18 | ||
19 | import com.google.common.collect.ImmutableList; | 19 | import com.google.common.collect.ImmutableList; |
20 | import com.google.common.collect.Lists; | 20 | import com.google.common.collect.Lists; |
21 | +import org.onlab.osgi.ServiceNotFoundException; | ||
21 | import org.onlab.packet.ChassisId; | 22 | import org.onlab.packet.ChassisId; |
22 | import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent; | 23 | import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent; |
23 | import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; | 24 | import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; |
... | @@ -54,12 +55,13 @@ public class Bmv2DeviceDescriptionDiscovery extends AbstractHandlerBehaviour imp | ... | @@ -54,12 +55,13 @@ public class Bmv2DeviceDescriptionDiscovery extends AbstractHandlerBehaviour imp |
54 | private Bmv2Controller controller; | 55 | private Bmv2Controller controller; |
55 | 56 | ||
56 | private boolean init() { | 57 | private boolean init() { |
58 | + try { | ||
57 | controller = handler().get(Bmv2Controller.class); | 59 | controller = handler().get(Bmv2Controller.class); |
58 | - if (controller == null) { | 60 | + return true; |
59 | - log.warn("Failed to get a BMv2 controller"); | 61 | + } catch (ServiceNotFoundException e) { |
62 | + log.warn(e.getMessage()); | ||
60 | return false; | 63 | return false; |
61 | } | 64 | } |
62 | - return true; | ||
63 | } | 65 | } |
64 | 66 | ||
65 | @Override | 67 | @Override | ... | ... |
... | @@ -19,6 +19,7 @@ package org.onosproject.drivers.bmv2; | ... | @@ -19,6 +19,7 @@ package org.onosproject.drivers.bmv2; |
19 | import com.google.common.collect.Lists; | 19 | import com.google.common.collect.Lists; |
20 | import com.google.common.collect.Maps; | 20 | import com.google.common.collect.Maps; |
21 | import org.apache.commons.lang3.tuple.Pair; | 21 | import org.apache.commons.lang3.tuple.Pair; |
22 | +import org.onlab.osgi.ServiceNotFoundException; | ||
22 | import org.onosproject.bmv2.api.context.Bmv2Configuration; | 23 | import org.onosproject.bmv2.api.context.Bmv2Configuration; |
23 | import org.onosproject.bmv2.api.context.Bmv2DeviceContext; | 24 | import org.onosproject.bmv2.api.context.Bmv2DeviceContext; |
24 | import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator; | 25 | import org.onosproject.bmv2.api.context.Bmv2FlowRuleTranslator; |
... | @@ -70,22 +71,15 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement | ... | @@ -70,22 +71,15 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement |
70 | private Bmv2DeviceContextService contextService; | 71 | private Bmv2DeviceContextService contextService; |
71 | 72 | ||
72 | private boolean init() { | 73 | private boolean init() { |
74 | + try { | ||
73 | controller = handler().get(Bmv2Controller.class); | 75 | controller = handler().get(Bmv2Controller.class); |
74 | tableEntryService = handler().get(Bmv2TableEntryService.class); | 76 | tableEntryService = handler().get(Bmv2TableEntryService.class); |
75 | contextService = handler().get(Bmv2DeviceContextService.class); | 77 | contextService = handler().get(Bmv2DeviceContextService.class); |
76 | - if (controller == null) { | 78 | + return true; |
77 | - log.warn("Failed to get a BMv2 controller"); | 79 | + } catch (ServiceNotFoundException e) { |
78 | - return false; | 80 | + log.warn(e.getMessage()); |
79 | - } | ||
80 | - if (tableEntryService == null) { | ||
81 | - log.warn("Failed to get a BMv2 table entry service"); | ||
82 | - return false; | ||
83 | - } | ||
84 | - if (contextService == null) { | ||
85 | - log.warn("Failed to get a BMv2 device context service"); | ||
86 | return false; | 81 | return false; |
87 | } | 82 | } |
88 | - return true; | ||
89 | } | 83 | } |
90 | 84 | ||
91 | @Override | 85 | @Override |
... | @@ -140,9 +134,14 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement | ... | @@ -140,9 +134,14 @@ public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour implement |
140 | Bmv2FlowRuleWrapper frWrapper = tableEntryService.lookup(entryRef); | 134 | Bmv2FlowRuleWrapper frWrapper = tableEntryService.lookup(entryRef); |
141 | 135 | ||
142 | if (frWrapper == null) { | 136 | if (frWrapper == null) { |
143 | - log.warn("missing reference from table entry service, BUG? " + | 137 | + log.debug("Missing reference from table entry service. Deleting it. BUG? " + |
144 | "deviceId={}, tableName={}, matchKey={}", | 138 | "deviceId={}, tableName={}, matchKey={}", |
145 | deviceId, table.name(), entryRef.matchKey()); | 139 | deviceId, table.name(), entryRef.matchKey()); |
140 | + try { | ||
141 | + doRemove(deviceAgent, table.name(), parsedEntry.entryId(), parsedEntry.matchKey()); | ||
142 | + } catch (Bmv2RuntimeException e) { | ||
143 | + log.warn("Unable to remove inconsistent flow rule: {}", e.explain()); | ||
144 | + } | ||
146 | continue; // next entry | 145 | continue; // next entry |
147 | } | 146 | } |
148 | 147 | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | 16 | ||
17 | package org.onosproject.drivers.bmv2; | 17 | package org.onosproject.drivers.bmv2; |
18 | 18 | ||
19 | +import org.onlab.osgi.ServiceNotFoundException; | ||
19 | import org.onlab.util.ImmutableByteSequence; | 20 | import org.onlab.util.ImmutableByteSequence; |
20 | import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent; | 21 | import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent; |
21 | import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; | 22 | import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; |
... | @@ -78,9 +79,11 @@ public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements | ... | @@ -78,9 +79,11 @@ public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements |
78 | 79 | ||
79 | DeviceId deviceId = handler().data().deviceId(); | 80 | DeviceId deviceId = handler().data().deviceId(); |
80 | 81 | ||
81 | - Bmv2Controller controller = handler().get(Bmv2Controller.class); | 82 | + Bmv2Controller controller; |
82 | - if (controller == null) { | 83 | + try { |
83 | - log.error("Failed to get BMv2 controller"); | 84 | + controller = handler().get(Bmv2Controller.class); |
85 | + } catch (ServiceNotFoundException e) { | ||
86 | + log.warn(e.getMessage()); | ||
84 | return; | 87 | return; |
85 | } | 88 | } |
86 | 89 | ... | ... |
... | @@ -189,17 +189,18 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { | ... | @@ -189,17 +189,18 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { |
189 | (!Objects.equals(thisDescription, lastDescription) || | 189 | (!Objects.equals(thisDescription, lastDescription) || |
190 | !Objects.equals(thisDescription.annotations(), lastDescription.annotations())); | 190 | !Objects.equals(thisDescription.annotations(), lastDescription.annotations())); |
191 | if (descriptionChanged || !deviceService.isAvailable(did)) { | 191 | if (descriptionChanged || !deviceService.isAvailable(did)) { |
192 | - if (contextService.getContext(did) == null) { | 192 | + if (deviceService.getDevice(did) == null) { |
193 | // Device is a first timer. | 193 | // Device is a first timer. |
194 | log.info("Setting DEFAULT context for {}", did); | 194 | log.info("Setting DEFAULT context for {}", did); |
195 | + // It is important to do this before connecting the device so other | ||
196 | + // services won't find a null context. | ||
195 | contextService.setContext(did, contextService.defaultContext()); | 197 | contextService.setContext(did, contextService.defaultContext()); |
196 | - } else { | 198 | + } |
197 | resetDeviceState(did); | 199 | resetDeviceState(did); |
198 | initPortCounters(did); | 200 | initPortCounters(did); |
199 | providerService.deviceConnected(did, thisDescription); | 201 | providerService.deviceConnected(did, thisDescription); |
200 | updatePortsAndStats(did); | 202 | updatePortsAndStats(did); |
201 | } | 203 | } |
202 | - } | ||
203 | return thisDescription; | 204 | return thisDescription; |
204 | } else { | 205 | } else { |
205 | log.warn("Unable to get device description for {}", did); | 206 | log.warn("Unable to get device description for {}", did); |
... | @@ -272,7 +273,7 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { | ... | @@ -272,7 +273,7 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { |
272 | if (deviceService.isAvailable(did)) { | 273 | if (deviceService.isAvailable(did)) { |
273 | providerService.deviceDisconnected(did); | 274 | providerService.deviceDisconnected(did); |
274 | } | 275 | } |
275 | - activeDevices.put(did, null); | 276 | + activeDevices.remove(did); |
276 | } | 277 | } |
277 | 278 | ||
278 | /** | 279 | /** |
... | @@ -333,7 +334,7 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { | ... | @@ -333,7 +334,7 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { |
333 | } | 334 | } |
334 | 335 | ||
335 | /** | 336 | /** |
336 | - * Task that periodically trigger device probes to check for device status and update port informations. | 337 | + * Task that periodically trigger device probes to check for device status and update port information. |
337 | */ | 338 | */ |
338 | private class DevicePoller implements TimerTask { | 339 | private class DevicePoller implements TimerTask { |
339 | 340 | ... | ... |
-
Please register or login to post a comment