[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();
-
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java
index 21c09de..5ef452b 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiEntityType.java
@@ -36,5 +36,10 @@
/**
* Action profile group member.
*/
- GROUP_MEMBER
+ GROUP_MEMBER,
+
+ /**
+ * Meter config.
+ */
+ METER_CELL_CONFIG
}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java
new file mode 100644
index 0000000..efa53ff
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java
@@ -0,0 +1,86 @@
+/*
+ * 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.pi.runtime;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Represents a band used within a meter.
+ */
+@Beta
+public class PiMeterBand {
+ private final long rate;
+ private final long burst;
+
+ /**
+ * Creates a band with rate and burst.
+ *
+ * @param rate rate of this band
+ * @param burst burst of this band
+ */
+ public PiMeterBand(long rate, long burst) {
+ this.rate = rate;
+ this.burst = burst;
+ }
+
+ /**
+ * Returns the rate of this band.
+ *
+ * @return rate of this band
+ */
+ public long rate() {
+ return rate;
+ }
+
+ /**
+ * Returns the burst of this band.
+ *
+ * @return burst of this band
+ */
+ public long burst() {
+ return burst;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rate, burst);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PiMeterBand) {
+ PiMeterBand that = (PiMeterBand) obj;
+ return Objects.equals(rate, that.rate) &&
+ Objects.equals(burst, that.burst);
+
+ }
+ return false;
+ }
+
+ public String toString() {
+ return toStringHelper(this)
+ .add("rate", rate)
+ .add("burst", burst).toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java
new file mode 100644
index 0000000..96ba124
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java
@@ -0,0 +1,152 @@
+/*
+ * 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.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration of a meter cell of a protocol-independent pipeline.
+ */
+@Beta
+public final class PiMeterCellConfig implements PiEntity {
+
+ private final PiMeterCellId cellId;
+ private final ImmutableList<PiMeterBand> piMeterBands;
+
+ /**
+ * Creates a new meter cell configuration for the given cell identifier and meter bands.
+ *
+ * @param cellId meter cell identifier
+ * @param piMeterBands meter bands
+ */
+ private PiMeterCellConfig(PiMeterCellId cellId, Collection<PiMeterBand> piMeterBands) {
+ this.cellId = cellId;
+ this.piMeterBands = ImmutableList.copyOf(piMeterBands);
+ }
+
+ /**
+ * Returns the cell identifier.
+ *
+ * @return cell identifier
+ */
+ public PiMeterCellId cellId() {
+ return cellId;
+ }
+
+ /**
+ * Returns the collection of bands of this cell.
+ *
+ * @return meter bands
+ */
+ public Collection<PiMeterBand> meterBands() {
+ return piMeterBands;
+ }
+
+ @Override
+ public PiEntityType piEntityType() {
+ return PiEntityType.METER_CELL_CONFIG;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PiMeterCellConfig)) {
+ return false;
+ }
+ PiMeterCellConfig that = (PiMeterCellConfig) o;
+
+ return piMeterBands.containsAll((that.piMeterBands)) &&
+ piMeterBands.size() == that.piMeterBands.size() &&
+ Objects.equal(cellId, that.cellId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(cellId, piMeterBands);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("cellId", cellId)
+ .add("meterBands", piMeterBands)
+ .toString();
+ }
+
+ /**
+ * Returns a meter cell configuration builder.
+ *
+ * @return a new builder
+ */
+ public static PiMeterCellConfig.Builder builder() {
+ return new PiMeterCellConfig.Builder();
+ }
+
+ public static final class Builder {
+ private PiMeterCellId cellId;
+ private List<PiMeterBand> bands = new ArrayList<>();
+
+
+ private Builder() {
+ // Hides constructor.
+ }
+
+ /**
+ * Sets the meter cell identifier for this meter.
+ *
+ * @param meterCellId meter cell identifier
+ * @return this
+ */
+ public PiMeterCellConfig.Builder withMeterCellId(PiMeterCellId meterCellId) {
+ this.cellId = meterCellId;
+ return this;
+ }
+
+
+ /**
+ * Sets a meter band of this meter.
+ *
+ * @param band meter band
+ * @return this
+ */
+ public PiMeterCellConfig.Builder withMeterBand(PiMeterBand band) {
+ this.bands.add(band);
+ return this;
+ }
+
+ /**
+ * Builds the meter cell configuration.
+ *
+ * @return a new meter cell configuration
+ */
+ public PiMeterCellConfig build() {
+ checkNotNull(cellId);
+ return new PiMeterCellConfig(cellId, bands);
+ }
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellId.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellId.java
new file mode 100644
index 0000000..09cf7bf
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellId.java
@@ -0,0 +1,141 @@
+/*
+ * 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.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.meter.MeterCellId;
+import org.onosproject.net.pi.model.PiMeterId;
+import org.onosproject.net.pi.model.PiMeterType;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Identifier of a meter cell in a protocol-independent pipeline.
+ */
+@Beta
+public final class PiMeterCellId implements MeterCellId {
+
+ private final PiMeterId meterId;
+ private final PiMeterType meterType;
+ private final long index;
+ private final PiTableEntry tableEntry;
+
+ private PiMeterCellId(PiMeterId meterId, PiMeterType meterType, long index,
+ PiTableEntry tableEntry) {
+ this.meterId = meterId;
+ this.meterType = meterType;
+ this.index = index;
+ this.tableEntry = tableEntry;
+ }
+
+ /**
+ * Returns the identifier of the meter instance where this cell is contained.
+ *
+ * @return meter identifier
+ */
+ public PiMeterId meterId() {
+ return meterId;
+ }
+
+ /**
+ * Returns the type of the meter identified.
+ *
+ * @return meter type
+ */
+ public PiMeterType meterType() {
+ return meterType;
+ }
+
+ /**
+ * Returns the meter index to which this cell ID is associated.
+ * Meaningful only if the meter is of type {@link PiMeterType#INDIRECT}.
+ *
+ * @return meter index
+ */
+ public long index() {
+ return index;
+ }
+
+ /**
+ * Returns the table entry to which this cell ID is associated.
+ * Meaningful only if the meter is of type {@link PiMeterType#DIRECT}, otherwise returns null.
+ *
+ * @return PI table entry or null
+ */
+ public PiTableEntry tableEntry() {
+ return tableEntry;
+ }
+
+ @Override
+ public MeterCellType type() {
+ return MeterCellType.PIPELINE_INDEPENDENT;
+ }
+
+ /**
+ * Return a direct meter cell ID for the given meter ID and table entry.
+ *
+ * @param meterId meter ID
+ * @param tableEntry table entry
+ * @return meter cell ID
+ */
+ public static PiMeterCellId ofDirect(PiMeterId meterId, PiTableEntry tableEntry) {
+ checkNotNull(meterId);
+ checkNotNull(tableEntry);
+ return new PiMeterCellId(meterId, PiMeterType.DIRECT, -1, tableEntry);
+ }
+
+ /**
+ * Return an indirect meter cell ID for the given meter ID and index.
+ *
+ * @param meterId meter ID
+ * @param index index
+ * @return meter cell ID
+ */
+ public static PiMeterCellId ofIndirect(PiMeterId meterId, long index) {
+ checkNotNull(meterId);
+ checkArgument(index >= 0, "Index must be a positive number");
+ return new PiMeterCellId(meterId, PiMeterType.INDIRECT, index, null);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final PiMeterCellId other = (PiMeterCellId) obj;
+ return Objects.equal(this.meterId, other.meterId)
+ && Objects.equal(this.meterType, other.meterType)
+ && Objects.equal(this.index, other.index)
+ && Objects.equal(this.tableEntry, other.tableEntry);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(meterId, meterType, index, tableEntry);
+ }
+
+ @Override
+ public String toString() {
+ return meterId.toString() + ':'
+ + (meterType == PiMeterType.DIRECT ? tableEntry.toString() : String.valueOf(index));
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterHandle.java
new file mode 100644
index 0000000..ad2af9d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterHandle.java
@@ -0,0 +1,74 @@
+/*
+ * 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.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Global identifier of a PI meter cell configuration applied to a device, uniquely defined
+ * by a device ID and meter cell ID.
+ */
+@Beta
+public final class PiMeterHandle extends PiHandle<PiMeterCellConfig> {
+
+ private PiMeterHandle(DeviceId deviceId, PiMeterCellConfig meterCellConfig) {
+ super(deviceId, meterCellConfig);
+ }
+
+ /**
+ * Creates a new handle for the given device ID and PI meter cell configuration.
+ *
+ * @param deviceId device ID
+ * @param meterCellConfig meter config
+ * @return PI meter handle
+ */
+ public static PiMeterHandle of(DeviceId deviceId,
+ PiMeterCellConfig meterCellConfig) {
+ return new PiMeterHandle(deviceId, meterCellConfig);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(deviceId(),
+ piEntity().cellId());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ PiMeterHandle that = (PiMeterHandle) o;
+ return Objects.equal(deviceId(), that.deviceId()) &&
+ Objects.equal(piEntity().cellId(),
+ that.piEntity().cellId());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("deviceId", deviceId())
+ .add("meterCellId", piEntity().cellId())
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslationStore.java
new file mode 100644
index 0000000..ddd6ab3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslationStore.java
@@ -0,0 +1,30 @@
+/*
+ * 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.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.pi.runtime.PiMeterCellConfig;
+
+/**
+ * A PI translation store that keeps track of which meters have been
+ * translated to which PI meters.
+ */
+@Beta
+public interface PiMeterTranslationStore
+ extends PiTranslationStore<Meter, PiMeterCellConfig> {
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslator.java
new file mode 100644
index 0000000..b52ad64
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiMeterTranslator.java
@@ -0,0 +1,29 @@
+/*
+ * 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.pi.service;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.pi.runtime.PiMeterCellConfig;
+
+/**
+ * A translator of meters to PI Meter Configs.
+ */
+@Beta
+public interface PiMeterTranslator
+ extends PiTranslator<Meter, PiMeterCellConfig> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
index c7a95c3..20cef35 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java
@@ -38,4 +38,11 @@
* @return group translator
*/
PiGroupTranslator groupTranslator();
+
+ /**
+ * Returns a meter translator.
+ *
+ * @return meter translator
+ */
+ PiMeterTranslator meterTranslator();
}