Add support for enabling/disabling ports for gNMI devices

This change also includes:
- Refactoring of gNMI protocol+driver to take advantage of the recent
changes to the gRPC protocol subsystem (e.g. no more locking, start RPC
with timeouts, etc.).
- Fixed Stratum driver to work after GeneralDeviceProvider refactoring
- Updated bmv2.py to generate ChassisConfig for stratum_bmv2
- Fixed portstate command to use the same port name as in the store

Change-Id: I0dad3bc73e4b6d907b5cf6b7b9a2852943226be7
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
index 0ffe615..a967c70 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
@@ -726,7 +726,8 @@
                                                              deviceId,
                                                              portDescription);
             if (event != null) {
-                log.info("Device {} port {} status changed", deviceId, event.port().number());
+                log.info("Device {} port {} status changed (enabled={})",
+                         deviceId, event.port().number(), portDescription.isEnabled());
                 post(event);
             }
         }
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
index 9653091..29deb4f 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
@@ -25,6 +25,7 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.NetworkConfigRegistry;
 import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.device.PortStatisticsDiscovery;
 import org.onosproject.net.driver.Behaviour;
 import org.onosproject.net.driver.DefaultDriver;
 import org.onosproject.net.driver.Driver;
@@ -283,6 +284,20 @@
                 new HashMap<>();
         pipeconf.behaviours().forEach(
                 b -> behaviours.put(b, pipeconf.implementation(b).get()));
+
+        // FIXME: remove this check when stratum_bmv2 will be open source and we
+        //  will no longer need to read port counters from the p4 program. Here
+        //  we ignore the PortStatisticsDiscovery behaviour from the pipeconf if
+        //  the base driver (e.g. stratum with gnmi) already has it. But in
+        //  general, we should give higher priority to pipeconf behaviours.
+        if (baseDriver.hasBehaviour(PortStatisticsDiscovery.class)
+                && behaviours.remove(PortStatisticsDiscovery.class) != null) {
+            log.warn("Ignoring {} behaviour from pipeconf {}, but using " +
+                             "the one provided by {} driver...",
+                     PortStatisticsDiscovery.class.getSimpleName(), pipeconfId,
+                     baseDriver.name());
+        }
+
         final Driver piPipeconfDriver = new DefaultDriver(
                 newDriverName, baseDriver.parents(),
                 baseDriver.manufacturer(), baseDriver.hwVersion(),
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
index de778a0..6dd861d 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
@@ -35,6 +35,7 @@
 import org.onosproject.net.device.DeviceDescription;
 import org.onosproject.net.device.DeviceDescriptionDiscovery;
 import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.PortStatisticsDiscovery;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.driver.Behaviour;
 import org.onosproject.net.driver.Driver;
@@ -160,7 +161,13 @@
         Set<Class<? extends Behaviour>> expectedBehaviours = Sets.newHashSet();
         expectedBehaviours.addAll(BASIC_PIPECONF.behaviours());
         expectedBehaviours.addAll(baseDriver.behaviours());
-        assertEquals("The driver contains wrong behaviours", expectedBehaviours, driver.behaviours());
+
+        // FIXME: remove when stratum_bmv2 will be open source
+        //  (see PiPipeconfManager)
+        // expectedBehaviours.remove(PortStatisticsDiscovery.class);
+
+        assertEquals("The driver contains wrong behaviours",
+                     expectedBehaviours, driver.behaviours());
     }
 
     private class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
@@ -256,7 +263,8 @@
 
         @Override
         public Set<Class<? extends Behaviour>> behaviours() {
-            return ImmutableSet.of(DeviceDescriptionDiscovery.class);
+            return ImmutableSet.of(DeviceDescriptionDiscovery.class,
+                                   PortStatisticsDiscovery.class);
         }
 
         @Override