Fix pipeline not marked as READY after device reboot
Since Stratum persists pipeline config across reboots, the
GeneralDeviceProvider was marking the device available as the device
had a pipeline config set right after the connection open event, but we
had to wait for the periodic PipeconfWatchdog check to mark the pipeline
as READY. Now we trigger a PipeconfWatchdog check after every device
availability change event.
Change-Id: I11a6f52ff5ea5304aa26dbe39786a25055b828aa
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfWatchdogManager.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfWatchdogManager.java
index eafb778..0503d9a 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfWatchdogManager.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfWatchdogManager.java
@@ -55,18 +55,15 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
-import java.util.Collections;
import java.util.Dictionary;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
+import static java.util.Collections.singleton;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.OsgiPropertyConstants.PWM_PROBE_INTERVAL;
import static org.onosproject.net.OsgiPropertyConstants.PWM_PROBE_INTERVAL_DEFAULT;
@@ -91,9 +88,6 @@
private final Logger log = getLogger(getClass());
private static final long SECONDS = 1000L;
- // Long enough to allow for network delay (e.g. to transfer large pipeline
- // binaries over slow network).
- private static final long PIPECONF_SET_TIMEOUT = 60; // Seconds.
@Reference(cardinality = ReferenceCardinality.MANDATORY)
private PiPipeconfMappingStore pipeconfMappingStore;
@@ -185,7 +179,7 @@
public void triggerProbe(DeviceId deviceId) {
final Device device = deviceService.getDevice(deviceId);
if (device != null) {
- filterAndTriggerTasks(Collections.singleton(device));
+ filterAndTriggerTasks(singleton(device));
}
}
@@ -206,8 +200,7 @@
}
final PiPipeconfId pipeconfId = pipeconfMappingStore.getPipeconfId(device.id());
- if (pipeconfId == null
- || !device.is(PiPipelineProgrammable.class)) {
+ if (pipeconfId == null || !device.is(PiPipelineProgrammable.class)) {
return;
}
@@ -256,21 +249,7 @@
pipeconf.id(), device.id());
return true;
}
- try {
- return pipelineProg.setPipeconf(pipeconf)
- .get(PIPECONF_SET_TIMEOUT, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- log.error("Thread interrupted while setting pipeconf on {}",
- device.id());
- Thread.currentThread().interrupt();
- } catch (ExecutionException e) {
- log.error("Exception while setting pipeconf on {}",
- device.id(), e.getCause());
- } catch (TimeoutException e) {
- log.error("Operation TIMEOUT while setting pipeconf on {}",
- device.id());
- }
- return false;
+ return Futures.getUnchecked(pipelineProg.setPipeconf(pipeconf));
}
private Runnable withLock(Runnable task, Object object) {
@@ -307,7 +286,7 @@
}
private void startProbeTask() {
- synchronized (timer) {
+ synchronized (this) {
log.info("Starting pipeline probe thread with {} seconds interval...", probeInterval);
task = new InternalTimerTask();
timer.scheduleAtFixedRate(task, probeInterval * SECONDS,
@@ -317,7 +296,7 @@
private void stopProbeTask() {
- synchronized (timer) {
+ synchronized (this) {
log.info("Stopping pipeline probe thread...");
task.cancel();
task = null;
@@ -326,7 +305,7 @@
private synchronized void rescheduleProbeTask() {
- synchronized (timer) {
+ synchronized (this) {
stopProbeTask();
startProbeTask();
}
@@ -353,6 +332,14 @@
case DEVICE_AVAILABILITY_CHANGED:
if (!deviceService.isAvailable(device.id())) {
signalStatusUnknown(device.id());
+ } else {
+ // The GeneralDeviceProvider marks online devices that
+ // have ANY pipeline config set. Here we make sure the
+ // one configured in the pipeconf service is the
+ // expected one. Clearly, it would be better to let the
+ // GDP do this check and avoid sending twice the same
+ // message to the switch.
+ filterAndTriggerTasks(singleton(device));
}
break;
case DEVICE_REMOVED: