Refactor P4Runtime subsystem to implement async connection procedure

This patch is an attempt to solve issues observed when restarting both
switches and ONOS nodes. Most of the issues seemed to depend on a
brittle mastership handling when deploying the pipeline.

With this patch, GDP registers devices to the core with available=false
(i.e. offline) and marks them online only when the P4 pipeline has been
deployed to the device. A new PiPipeconfWatchdogService takes care of
deploying pipelines and producing event when devices are ready.

Moreover, we fix a race condition where pipeconf-related behaviors
were not found. This was caused by GDP enforcing the merged
driver name in the network config, while external entities (e.g.
Mininet) were pushing a JSON blob with the base driver name. This patch
removes the need to rely on such a trick and instead uses
pipeconf-aware logic directly in the driver manager (change #19622).

Finally, we fix issues in P4RuntimeClientImpl that were causing the
stream channel not detecting unreachable devices. The solution is to
follow gRPC APIs and re-instantiate a new channel once the first fails.

Change-Id: I6fbc91859c0fb58a6db3bc197b7081a8fe9f97f7
diff --git a/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java b/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java
index bc870d3..bceaeff 100644
--- a/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java
+++ b/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java
@@ -19,6 +19,7 @@
 import com.google.common.annotations.Beta;
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.driver.DeviceConnect;
+import org.onosproject.net.provider.ProviderId;
 
 import java.util.concurrent.CompletableFuture;
 
@@ -48,21 +49,32 @@
     void roleChanged(MastershipRole newRole);
 
     /**
-     * Adds a device agent listener.
+     * Returns the last known mastership role agreed by the device for this
+     * node.
      *
-     * @param listener device agent listener
+     * @return mastership role
      */
-    default void addDeviceAgentListener(DeviceAgentListener listener) {
+    MastershipRole getRole();
+
+    /**
+     * Adds a device agent listener for the given provider ID.
+     *
+     * @param providerId provider ID
+     * @param listener   device agent listener
+     */
+    default void addDeviceAgentListener(
+            ProviderId providerId, DeviceAgentListener listener) {
         throw new UnsupportedOperationException(
                 "Device agent listener registration not supported");
     }
 
     /**
-     * Removes a device agent listener.
+     * Removes a device agent listener previously registered for the given
+     * provider ID.
      *
-     * @param listener device agent listener
+     * @param providerId provider ID
      */
-    default void removeDeviceAgentListener(DeviceAgentListener listener) {
+    default void removeDeviceAgentListener(ProviderId providerId) {
         throw new UnsupportedOperationException(
                 "Device agent listener removal not supported");
     }