[ONOS-7051] Support for P4Runtime meters

Change-Id: Id71374af65aeb84b71636b4ec230dc6001a77a8b
diff --git a/core/api/src/main/java/org/onosproject/net/meter/Band.java b/core/api/src/main/java/org/onosproject/net/meter/Band.java
index 5b75ab7..9f9479c 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/Band.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/Band.java
@@ -45,7 +45,14 @@
         /**
          * Defines an experimental meter band.
          */
-        EXPERIMENTAL
+        EXPERIMENTAL,
+
+        /**
+         * Defines a meter band with no action, used to mark
+         * packets internally in the pipeline, i.e. without
+         * modifying the packet headers.
+         */
+        NONE,
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
index 7be5e90..ad0256e 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
@@ -25,6 +25,7 @@
 import static com.google.common.base.MoreObjects.toStringHelper;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.meter.MeterCellId.MeterCellType.INDEX;
 
 /**
  * A default implementation of a meter.
@@ -32,7 +33,7 @@
 public final class DefaultMeter implements Meter, MeterEntry  {
 
 
-    private final MeterId id;
+    private final MeterCellId cellId;
     private final ApplicationId appId;
     private final Unit unit;
     private final boolean burst;
@@ -45,11 +46,10 @@
     private long packets;
     private long bytes;
 
-    private DefaultMeter(DeviceId deviceId, MeterId id, ApplicationId appId,
-                        Unit unit, boolean burst,
-                        Collection<Band> bands) {
+    private DefaultMeter(DeviceId deviceId, MeterCellId cellId, ApplicationId appId,
+                         Unit unit, boolean burst, Collection<Band> bands) {
         this.deviceId = deviceId;
-        this.id = id;
+        this.cellId = cellId;
         this.appId = appId;
         this.unit = unit;
         this.burst = burst;
@@ -63,7 +63,16 @@
 
     @Override
     public MeterId id() {
-        return id;
+        // Workaround until we remove this method. Deprecated in 1.13.
+        // Should use meterCellId() instead.
+        return cellId.type() == INDEX
+                ? (MeterId) cellId
+                : MeterId.meterId((cellId.hashCode()));
+    }
+
+    @Override
+    public MeterCellId meterCellId() {
+        return cellId;
     }
 
     @Override
@@ -144,7 +153,7 @@
     public String toString() {
         return toStringHelper(this)
                 .add("device", deviceId)
-                .add("id", id)
+                .add("cellId", cellId)
                 .add("appId", appId.name())
                 .add("unit", unit)
                 .add("isBurst", burst)
@@ -161,7 +170,7 @@
             return false;
         }
         DefaultMeter that = (DefaultMeter) o;
-        return Objects.equal(id, that.id) &&
+        return Objects.equal(cellId, that.cellId) &&
                 Objects.equal(appId, that.appId) &&
                 Objects.equal(unit, that.unit) &&
                 Objects.equal(deviceId, that.deviceId);
@@ -169,19 +178,18 @@
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(id, appId, unit, deviceId);
+        return Objects.hashCode(cellId, appId, unit, deviceId);
     }
 
     public static final class Builder implements Meter.Builder {
 
-        private MeterId id;
+        private MeterCellId cellId;
         private ApplicationId appId;
         private Unit unit = Unit.KB_PER_SEC;
         private boolean burst = false;
         private Collection<Band> bands;
         private DeviceId deviceId;
 
-
         @Override
         public Meter.Builder forDevice(DeviceId deviceId) {
             this.deviceId = deviceId;
@@ -190,7 +198,13 @@
 
         @Override
         public Meter.Builder withId(MeterId id) {
-            this.id = id;
+            this.withCellId(id);
+            return this;
+        }
+
+        @Override
+        public Meter.Builder withCellId(MeterCellId cellId) {
+            this.cellId = cellId;
             return this;
         }
 
@@ -224,8 +238,8 @@
             checkNotNull(bands, "Must have bands.");
             checkArgument(!bands.isEmpty(), "Must have at least one band.");
             checkNotNull(appId, "Must have an application id");
-            checkNotNull(id, "Must specify a meter id");
-            return new DefaultMeter(deviceId, id, appId, unit, burst, bands);
+            checkArgument(cellId != null, "Must specify a cell id.");
+            return new DefaultMeter(deviceId, cellId, appId, unit, burst, bands);
         }
 
 
diff --git a/core/api/src/main/java/org/onosproject/net/meter/Meter.java b/core/api/src/main/java/org/onosproject/net/meter/Meter.java
index 3cb4511..3d7544e 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/Meter.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/Meter.java
@@ -17,13 +17,14 @@
 
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.service.PiTranslatable;
 
 import java.util.Collection;
 
 /**
- * Represents a generalized meter to be deployed on a device.
+ * Represents a generalized meter cell configuration to be deployed on a device.
  */
-public interface Meter {
+public interface Meter extends PiTranslatable {
 
     enum Unit {
         /**
@@ -48,10 +49,19 @@
      * This meters id.
      *
      * @return a meter id
+     * @deprecated in Nightingale release (version 1.13.0). Use {@link #meterCellId()} instead.
      */
+    @Deprecated
     MeterId id();
 
     /**
+     * Returns the meter cell identifier of this meter.
+     *
+     * @return a meter identifier
+     */
+    MeterCellId meterCellId();
+
+    /**
      * The id of the application which created this meter.
      *
      * @return an application id
@@ -132,10 +142,21 @@
          *
          * @param id a e
          * @return this
+         * @deprecated in Nightingale release (version 1.13.0). Use {@link
+         * #withCellId(MeterCellId)} instead.
          */
+        @Deprecated
         Builder withId(MeterId id);
 
         /**
+         * Assigns the id to this meter cell.
+         *
+         * @param meterId a meter cell identifier
+         * @return this
+         */
+        Builder withCellId(MeterCellId meterId);
+
+        /**
          * Assigns the application that built this meter.
          *
          * @param appId an application id
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterCellId.java b/core/api/src/main/java/org/onosproject/net/meter/MeterCellId.java
new file mode 100644
index 0000000..900b79c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterCellId.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.meter;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A representation of a meter cell identifier.
+ * Uniquely identifies a meter cell in the scope of a single device.
+ */
+@Beta
+public interface MeterCellId {
+
+    /**
+     * Types of meter cell identifier.
+     */
+    enum MeterCellType {
+        /**
+         * Signifies that the meter cell can be identified with an integer index.
+         * Valid for pipelines that defines one global meter table, e.g. as with
+         * OpenFlow meters.
+         */
+        INDEX,
+
+        /**
+         * Signifies that the meter cell identifier is pipeline-independent.
+         */
+        PIPELINE_INDEPENDENT
+    }
+
+    /**
+     * Return the type of this meter cell identifier.
+     *
+     * @return type
+     */
+    MeterCellType type();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterId.java b/core/api/src/main/java/org/onosproject/net/meter/MeterId.java
index e735984..7c28880 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterId.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterId.java
@@ -20,15 +20,26 @@
 import static com.google.common.base.Preconditions.checkArgument;
 
 /**
- * A representation of a meter identifier.
- * Uniquely identifies a meter in the scope of a single device.
+ * A representation of a meter cell identifier. Uniquely identifies a meter cell
+ * in the scope of a single device.
  * <p>
- * The meter_id field uniquely identifies a meter within a switch. Meters are
- * defined starting with meter_id=1 up to the maximum number of meters that the
- * switch can support. The OpenFlow protocol also defines some additional
- * virtual meters that can not be associated with flows:
+ * This ID uniquely identifies a meter cell within in a switch that maintains
+ * only one meter instance. If a switch supports multiple meter instances (like
+ * in P4), then {@link org.onosproject.net.pi.runtime.PiMeterCellId} should be
+ * used. In this case, meter cells are defined starting with id=1 up to the
+ * maximum number of cells that the switch can support. The OpenFlow protocol
+ * also defines some additional virtual meter cells that can not be associated
+ * with flows.
  */
-public final class MeterId extends Identifier<Long> {
+public final class MeterId extends Identifier<Long> implements MeterCellId {
+
+    // TODO: should rename this class to SimpleMeterCellId to distinguish it
+    // from PiMeterId and PiMeterCellId. From ONOS-7051, to follow the P4
+    // abstraction there can be multiple instances of a meter in a data plane,
+    // each meter instance is made of multiple cells. This class is based on the
+    // OpenFlow abstraction where, following P4 terminology, the data plane
+    // maintains only one meter instance. What is described here as a MeterId is
+    // indeed the identifier of a meter cell.
 
     /**  Flow meters can use any number up to MAX. */
     public static final long MAX = 0xFFFF0000L;
@@ -63,4 +74,9 @@
         checkArgument(id <= MAX, "id cannot be larger than {}", MAX);
         return new MeterId(id);
     }
+
+    @Override
+    public MeterCellType type() {
+        return MeterCellType.INDEX;
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterProgrammable.java b/core/api/src/main/java/org/onosproject/net/meter/MeterProgrammable.java
index 06a303f..4b8ea07 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterProgrammable.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterProgrammable.java
@@ -42,6 +42,4 @@
      * @return completable future with the collection of meters
      */
     CompletableFuture<Collection<Meter>> getMeters();
-}
-
-
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java b/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
index bba2388..9060b95 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
@@ -141,7 +141,6 @@
          * @return a meter request
          */
         MeterRequest remove();
-
     }
 
 }