Few core changes in preparation of P4Runtime subsystem refactoring

Refactoring aims at providing a more robust connection procedure of
P4Runtime-based devices.

Refactoring requires devices to be registered to the core with
available=false (i.e. offline), and marked online only when the P4
pipeline has been deployed to the device. Also, it leaves the duty of
handling pipeconf-specific drivers to the driver subsystem, instead of
having the GeneralDeviceProvider take care of it, which resulted to be
brittle.

Changes include:
- Choose not to mark device online when re-asserting mastership role by
declaring special device annotation.
- Lookup drivers in device projectable model unsing driver service
device-based method, which is consistent with the way other subsystems
look for device drivers.
- In DriverManager, when looking for device drivers, consider the case
of pipeconf-programmable devices, in which case a special "merged"
driver needs to instantiated at runtime.
- In PacketManager, push flow objectives only if device is available
(i.e. after pipeline has been deployed).

Change-Id: I80f78a4f40730a06cb82fa55fefab08a91a89268
diff --git a/core/net/src/main/java/org/onosproject/net/driver/impl/DriverManager.java b/core/net/src/main/java/org/onosproject/net/driver/impl/DriverManager.java
index 1dd8f7b..f2ece6b 100644
--- a/core/net/src/main/java/org/onosproject/net/driver/impl/DriverManager.java
+++ b/core/net/src/main/java/org/onosproject/net/driver/impl/DriverManager.java
@@ -36,6 +36,8 @@
 import org.onosproject.net.driver.DriverListener;
 import org.onosproject.net.driver.DriverRegistry;
 import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.service.PiPipeconfService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,6 +73,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetworkConfigService networkConfigService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PiPipeconfService pipeconfService;
+
     @Activate
     protected void activate() {
         AbstractProjectableModel.setDriverService(null, this);
@@ -113,9 +118,25 @@
     public Driver getDriver(DeviceId deviceId) {
         checkPermission(DRIVER_READ);
 
+        Driver driver;
+
         // Primary source of driver configuration is the network config.
+        if (pipeconfService.ofDevice(deviceId).isPresent()) {
+            // Device has pipeconf associated, look for merged driver.
+            // Implementation of PiPipeconfService is expected to look for a
+            // base driver in network config.
+            PiPipeconfId pipeconfId = pipeconfService.ofDevice(deviceId).get();
+            String mergedDriver = pipeconfService.getMergedDriver(deviceId, pipeconfId);
+            driver = mergedDriver != null ? lookupDriver(mergedDriver) : null;
+            if (driver != null) {
+                return driver;
+            } else {
+                log.error("Merged driver for {} with pipeconf {} not found, falling back.",
+                          deviceId, pipeconfId);
+            }
+        }
         BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
-        Driver driver = lookupDriver(cfg != null ? cfg.driver() : null);
+        driver = lookupDriver(cfg != null ? cfg.driver() : null);
         if (driver != null) {
             return driver;
         }