[ONOS-5310] FullMetersAvailable

For cases in which MeterFeatures are not available but device supports Meters

Change-Id: Ie10ca85643ea35a43df1f76d92cd3931a15b32c8
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MeterQuery.java b/core/api/src/main/java/org/onosproject/net/behaviour/MeterQuery.java
new file mode 100644
index 0000000..8364d78
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MeterQuery.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * A HandlerBehaviour to check the capability of Meter.
+ */
+public interface MeterQuery extends HandlerBehaviour {
+    /**
+     * Get maximum meters available for the device.
+     *
+     * @return the maximum number of meters
+     */
+    long getMaxMeters();
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/query/FullMetersAvailable.java b/drivers/default/src/main/java/org/onosproject/driver/query/FullMetersAvailable.java
new file mode 100644
index 0000000..ab5a28e
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/query/FullMetersAvailable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.query;
+
+import org.onosproject.net.behaviour.MeterQuery;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+
+/**
+ * Driver which always responds that all Meters are available for the Device.
+ */
+public class FullMetersAvailable extends AbstractHandlerBehaviour implements MeterQuery {
+
+    private static final long MAX_METER = 0x00000FFF;
+
+    @Override
+    public long getMaxMeters() {
+        return MAX_METER;
+    }
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java
index db5cff0..9aed99b 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java
@@ -25,6 +25,9 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.TriConsumer;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.MeterQuery;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.meter.DefaultMeter;
 import org.onosproject.net.meter.Meter;
 import org.onosproject.net.meter.MeterEvent;
@@ -76,6 +79,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected MeterStore store;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
     private Map<DeviceId, AtomicCounter> meterIdCounters
             = Maps.newConcurrentMap();
 
@@ -173,8 +179,21 @@
         return store.getAllMeters();
     }
 
+    private long queryMeters(DeviceId device) {
+            DriverHandler handler = driverService.createHandler(device);
+            if (handler == null || !handler.hasBehaviour(MeterQuery.class)) {
+                return 0L;
+            }
+            MeterQuery query = handler.behaviour(MeterQuery.class);
+            return query.getMaxMeters();
+    }
+
     private MeterId allocateMeterId(DeviceId deviceId) {
         long maxMeters = store.getMaxMeters(MeterFeaturesKey.key(deviceId));
+        if (maxMeters == 0L) {
+            // MeterFeatures couldn't be retrieved, trying with queryMeters
+            maxMeters = queryMeters(deviceId);
+        }
 
         if (maxMeters == 0L) {
             throw new IllegalStateException("Meters not supported by device " + deviceId);