[VOL-4707] Expose programmed subscribers via REST and move classes and interfaces to the API.

Change-Id: Ibfb9caa48455fd349932297cb9191ee0f0341ffa
Signed-off-by: Gustavo Silva <gsilva@furukawalatam.com>
diff --git a/api/pom.xml b/api/pom.xml
index bbfea8e..4a6fa6d 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -32,6 +32,14 @@
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
     </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.opencord</groupId>
+            <artifactId>sadis-api</artifactId>
+            <version>${sadis.api.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
     <build>
         <plugins>
             <plugin>
diff --git a/api/src/main/java/org/opencord/olt/AccessDevicePort.java b/api/src/main/java/org/opencord/olt/AccessDevicePort.java
new file mode 100644
index 0000000..13275c5
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/AccessDevicePort.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+
+import java.util.Objects;
+
+/**
+ * OLT device port.
+ */
+public class AccessDevicePort {
+
+    private ConnectPoint cp;
+    private String name;
+
+    /**
+     * Creates an AccessDevicePort with given ONOS port.
+     *
+     * @param port ONOS port
+     */
+    public AccessDevicePort(Port port) {
+        this.cp = ConnectPoint.deviceConnectPoint(port.element().id() + "/" + port.number().toLong());
+        this.name = getPortName(port);
+    }
+
+    /**
+     * Creates an AccessDevicePort with given ONOS connectPoint and name.
+     *
+     * @param cp ONOS connect point
+     * @param name OLT port name
+     */
+    public AccessDevicePort(ConnectPoint cp, String name) {
+        this.cp = cp;
+        this.name = name;
+    }
+
+    /**
+     * Get ONOS ConnectPoint object.
+     *
+     * @return ONOS connect point
+     */
+    public ConnectPoint connectPoint() {
+        return this.cp;
+    }
+
+    /**
+     * Get OLT port name which is combination of serial number and uni index.
+     *
+     * @return OLT port name (ex: BBSM00010001-1)
+     */
+    public String name() {
+        return this.name;
+    }
+
+    @Override
+    public String toString() {
+        return cp.toString() + '[' + name + ']';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        AccessDevicePort that = (AccessDevicePort) o;
+        return Objects.equals(cp, that.cp) &&
+                Objects.equals(name, that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(cp, name);
+    }
+
+    private String getPortName(Port port) {
+        String name = port.annotations().value(AnnotationKeys.PORT_NAME);
+        return name == null ? "" : name;
+    }
+}
diff --git a/api/src/main/java/org/opencord/olt/DiscoveredSubscriber.java b/api/src/main/java/org/opencord/olt/DiscoveredSubscriber.java
new file mode 100644
index 0000000..8d837f4
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/DiscoveredSubscriber.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.opencord.sadis.SubscriberAndDeviceInformation;
+
+import java.util.Objects;
+
+/**
+ * Contains a subscriber's information and status for a specific device and port.
+ */
+public class DiscoveredSubscriber {
+
+    /**
+     * Describe whether the subscriber needs to be added or removed.
+     */
+    public enum Status {
+        ADDED,
+        REMOVED,
+        // Used for the remove subscriber calls from REST/CLI
+        ADMIN_REMOVED,
+    }
+
+    public Port port;
+    public Device device;
+    public Enum<Status> status;
+    public boolean hasSubscriber;
+    public SubscriberAndDeviceInformation subscriberAndDeviceInformation;
+
+    /**
+     * Creates the class with the proper information.
+     *
+     * @param device        the device of the subscriber
+     * @param port          the port
+     * @param status        the status for this specific subscriber
+     * @param hasSubscriber is the subscriber present
+     * @param si            the information about the tags/dhcp and other info.
+     */
+    public DiscoveredSubscriber(Device device, Port port, Status status, boolean hasSubscriber,
+                                SubscriberAndDeviceInformation si) {
+        this.device = device;
+        this.port = port;
+        this.status = status;
+        this.hasSubscriber = hasSubscriber;
+        subscriberAndDeviceInformation = si;
+    }
+
+    /**
+     * Returns the port name for the subscriber.
+     *
+     * @return the port name.
+     */
+    public String portName() {
+        return getPortName(port);
+    }
+
+    @Override
+    public String toString() {
+
+        return String.format("%s (status: %s, provisionSubscriber: %s)",
+                portWithName(this.port),
+                this.status, this.hasSubscriber
+        );
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        DiscoveredSubscriber that = (DiscoveredSubscriber) o;
+        return hasSubscriber == that.hasSubscriber &&
+                port.equals(that.port) &&
+                device.equals(that.device) &&
+                status.equals(that.status);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(port, device, status, hasSubscriber, subscriberAndDeviceInformation);
+    }
+
+    private String portWithName(Port port) {
+        return port.element().id().toString() + '/' +
+                port.number() + '[' +
+                getPortName(port) + ']';
+    }
+    private String getPortName(Port port) {
+        String name = port.annotations().value(AnnotationKeys.PORT_NAME);
+        return name == null ? "" : name;
+    }
+}
diff --git a/api/src/main/java/org/opencord/olt/FlowDirection.java b/api/src/main/java/org/opencord/olt/FlowDirection.java
new file mode 100644
index 0000000..839e967
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/FlowDirection.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022-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.opencord.olt;
+
+/**
+ * Enumerates the flow directions.
+ */
+public enum FlowDirection {
+    /**
+     * Upstream direction.
+     */
+    UPSTREAM,
+    /**
+     * Downstream direction.
+     */
+    DOWNSTREAM,
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/olt/FlowOperation.java b/api/src/main/java/org/opencord/olt/FlowOperation.java
new file mode 100644
index 0000000..3ad25a5
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/FlowOperation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022-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.opencord.olt;
+
+/**
+ * Enumerates the flow operations.
+ */
+public enum FlowOperation {
+    /**
+     * Flow addition op.
+     */
+    ADD,
+    /**
+     * Flow removal op.
+     */
+    REMOVE;
+
+    @Override
+    public String toString() {
+        return super.toString().toLowerCase();
+    }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/olt/MeterData.java b/api/src/main/java/org/opencord/olt/MeterData.java
new file mode 100644
index 0000000..510b617
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/MeterData.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.meter.MeterCellId;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterState;
+
+import java.util.Objects;
+
+/**
+ * Class containing Meter Data.
+ */
+public class MeterData {
+    private MeterCellId meterCellId;
+    private MeterState meterStatus;
+    private String bandwidthProfileName;
+
+    /**
+     * Creates a MeterData for a given cellid, status and bandwidth profile.
+     *
+     * @param meterCellId       the cell id
+     * @param meterStatus       the status
+     * @param bandwidthProfile  the bandwidth profile
+     */
+    public MeterData(MeterCellId meterCellId, MeterState meterStatus, String bandwidthProfile) {
+        this.meterCellId = meterCellId;
+        this.meterStatus = meterStatus;
+        this.bandwidthProfileName = bandwidthProfile;
+    }
+
+    /**
+     * Sets the meter cell id.
+     *
+     * @param meterCellId the meter cell id.
+     */
+    public void setMeterCellId(MeterCellId meterCellId) {
+        this.meterCellId = meterCellId;
+    }
+
+    /**
+     * Sets the meter status.
+     *
+     * @param meterStatus the meter status.
+     */
+    public void setMeterStatus(MeterState meterStatus) {
+        this.meterStatus = meterStatus;
+    }
+
+    /**
+     * Gets the meter id.
+     *
+     * @return Meter id.
+     */
+    public MeterId getMeterId() {
+        return (MeterId) meterCellId;
+    }
+
+    /**
+     * Gets the meter cell id.
+     *
+     * @return Meter cell id.
+     */
+    public MeterCellId getMeterCellId() {
+        return meterCellId;
+    }
+
+    /**
+     * Gets the meter status.
+     *
+     * @return Meter status.
+     */
+    public MeterState getMeterStatus() {
+        return meterStatus;
+    }
+
+    /**
+     * Gets the bandwidth profile name.
+     *
+     * @return Bandwidth profile name.
+     */
+    public String getBandwidthProfileName() {
+        return bandwidthProfileName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        MeterData meterData = (MeterData) o;
+        return Objects.equals(meterCellId, meterData.meterCellId) &&
+                meterStatus == meterData.meterStatus &&
+                Objects.equals(bandwidthProfileName, meterData.bandwidthProfileName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(meterCellId, meterStatus, bandwidthProfileName);
+    }
+
+    @Override
+    public String toString() {
+        return "MeterData{" +
+                "meterCellId=" + meterCellId +
+                ", meterStatus=" + meterStatus +
+                ", bandwidthProfile='" + bandwidthProfileName + '\'' +
+                '}';
+    }
+}
diff --git a/api/src/main/java/org/opencord/olt/OltDeviceServiceInterface.java b/api/src/main/java/org/opencord/olt/OltDeviceServiceInterface.java
new file mode 100644
index 0000000..d6a4827
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/OltDeviceServiceInterface.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+
+import java.util.Optional;
+
+/**
+ * Service for olt device handling.
+ */
+public interface OltDeviceServiceInterface {
+    /**
+     * Returns true if the device is a known OLT to sadis/config.
+     * @param device the device
+     * @return true if a configured olt
+     */
+    boolean isOlt(Device device);
+
+    /**
+     * Returns true if the port is an NNI port of the OLT device.
+     * @param device the device
+     * @param port the port
+     * @return true if an NNI port of that OLT
+     */
+    boolean isNniPort(Device device, PortNumber port);
+
+    /**
+     * Returns the NNi port fo the OLT device if present.
+     * @param device the device
+     * @return the nni Port, if present
+     */
+    Optional<Port> getNniPort(Device device);
+
+    /**
+     * Returns true if the instance is leader for the OLT device.
+     * @param deviceId the device
+     * @return true if master, false otherwise.
+     */
+    boolean isLocalLeader(DeviceId deviceId);
+}
diff --git a/api/src/main/java/org/opencord/olt/OltFlowServiceInterface.java b/api/src/main/java/org/opencord/olt/OltFlowServiceInterface.java
new file mode 100644
index 0000000..c28d63b
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/OltFlowServiceInterface.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.opencord.sadis.UniTagInformation;
+
+import java.util.Map;
+
+/**
+ * Interface for flow installation/removal methods for different types of traffic.
+ */
+public interface OltFlowServiceInterface {
+    /**
+     * Installs or removes default flows for the port to trap to controller.
+     * @param sub the information about the port
+     * @param defaultBpId the default bandwidth profile
+     * @param oltBandwidthProfile the olt bandwidth profile.
+     * @return true if successful
+     */
+    boolean handleBasicPortFlows(
+            DiscoveredSubscriber sub, String defaultBpId, String oltBandwidthProfile);
+
+    /**
+     * Installs or removes subscriber specific flows.
+     * @param sub the information about the subscriber
+     * @param defaultBpId the default bandwidth profile
+     * @param multicastServiceName the multicast service name.
+     * @return true if successful
+     */
+    boolean handleSubscriberFlows(DiscoveredSubscriber sub, String defaultBpId, String multicastServiceName);
+
+    /**
+     * Installs or removes flows on the NNI port.
+     * @param device the OLT
+     * @param port the NNI port
+     * @param action the operatio, ADD or REMOVE.
+     */
+    void handleNniFlows(Device device, Port port, FlowOperation action);
+
+    /**
+     * Checks if the default eapol flow is already installed.
+     * @param port the port
+     * @return true if installed, false otherwise.
+     */
+    boolean hasDefaultEapol(Port port);
+
+    /**
+     * Checks if the dhcp flows are installed.
+     * @param port the port
+     * @param uti the UniTagInformation to check for
+     * @return true if installed, false otherwise.
+     */
+    boolean hasDhcpFlows(Port port, UniTagInformation uti);
+
+    /**
+     * Checks if the pppoe flows are installed.
+     * @param port the port
+     * @param uti the UniTagInformation to check for
+     * @return true if installed, false otherwise.
+     */
+    boolean hasPppoeFlows(Port port, UniTagInformation uti);
+
+    /**
+     * Checks if the subscriber flows are installed.
+     * @param port the port
+     * @param uti the UniTagInformation to check for
+     * @return true if installed, false otherwise.
+     */
+    boolean hasSubscriberFlows(Port port, UniTagInformation uti);
+
+    /**
+     * Removes all device flows.
+     * @param deviceId the olt.
+     */
+    void purgeDeviceFlows(DeviceId deviceId);
+
+    /**
+     * Return the status of installation on the connect points.
+     * @return the status map
+     */
+    Map<ServiceKey, OltPortStatus> getConnectPointStatus();
+
+    /**
+     * Returns all the programmed subscribers.
+     * @return the subscribers
+     */
+    Map<ServiceKey, UniTagInformation> getProgrammedSubscribers();
+
+    /**
+     * Returns the list of requested subscribers to be installed with status.
+     * @return the list
+     */
+    Map<ServiceKey, Boolean> getRequestedSubscribers();
+
+    /**
+     * Returns if a subscriber on a port is provisioned or not.
+     * @param cp the port
+     * @return true if any service on that port is provisioned, false otherwise
+     */
+    boolean isSubscriberServiceProvisioned(AccessDevicePort cp);
+
+    /**
+     * Returns if a subscriber on a port is provisioned or not.
+     * @param sk the SubscriberKey
+     * @return true if provisioned, false otherwise
+     */
+    boolean isSubscriberServiceProvisioned(ServiceKey sk);
+
+    /**
+     * Updates the subscriber provisioning status.
+     * @param sk the SubscriberKey
+     * @param status the next status
+     */
+    void updateProvisionedSubscriberStatus(ServiceKey sk, Boolean status);
+}
diff --git a/api/src/main/java/org/opencord/olt/OltFlowsStatus.java b/api/src/main/java/org/opencord/olt/OltFlowsStatus.java
new file mode 100644
index 0000000..b002d57
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/OltFlowsStatus.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022-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.opencord.olt;
+/**
+ * Enumerates the flow status.
+ */
+public enum OltFlowsStatus {
+    /**
+     * None status.
+     */
+    NONE,
+    /**
+     * Flow is pending add.
+     */
+    PENDING_ADD,
+    /**
+     * Flow is added.
+     */
+    ADDED,
+    /**
+     * Flow is pending remove.
+     */
+    PENDING_REMOVE,
+    /**
+     * Flow is removed.
+     */
+    REMOVED,
+    /**
+     * An error occurred.
+     */
+    ERROR
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/olt/OltMeterServiceInterface.java b/api/src/main/java/org/opencord/olt/OltMeterServiceInterface.java
new file mode 100644
index 0000000..14cd0c5
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/OltMeterServiceInterface.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.MeterId;
+import org.opencord.sadis.SubscriberAndDeviceInformation;
+
+import java.util.Map;
+
+/**
+ * Interface for meter installation/removal methods
+ * for different types of bandwidth profiles.
+ */
+public interface OltMeterServiceInterface {
+    /**
+     * Checks for a meter, if not present it will create it and return false.
+     * @param deviceId DeviceId
+     * @param bandwidthProfile Bandwidth Profile Id
+     * @return boolean
+     */
+    boolean createMeter(DeviceId deviceId, String bandwidthProfile);
+
+    /**
+     * Checks for all the meters specified in the sadis uniTagList,
+     * if not present it will create them and return false.
+     * @param deviceId DeviceId
+     * @param si SubscriberAndDeviceInformation
+     * @param multicastServiceName The multicast service name
+     * @return boolean
+     */
+    boolean createMeters(DeviceId deviceId, SubscriberAndDeviceInformation si, String multicastServiceName);
+
+    /**
+     * Checks if a meter for the specified bandwidthProfile exists
+     * and is in ADDED state.
+     * @param deviceId DeviceId
+     * @param bandwidthProfileId bandwidth profile id
+     * @return true if present and in ADDED state
+     */
+    boolean hasMeterByBandwidthProfile(DeviceId deviceId, String bandwidthProfileId);
+
+    /**
+     * Checks if a meter for the specified bandwidthProfile exists
+     * and is in PENDING_ADD state.
+     * @param deviceId DeviceId
+     * @param bandwidthProfileId bandwidth profile id
+     * @return true if present and in PENDING_ADD state
+     */
+    boolean hasPendingMeterByBandwidthProfile(DeviceId deviceId, String bandwidthProfileId);
+
+    /**
+     * Creates a meter on a device for the given BandwidthProfile Id.
+     * @param deviceId the device id
+     * @param bandwidthProfileId the bandwidth profile Id
+     */
+    void createMeterForBp(DeviceId deviceId, String bandwidthProfileId);
+
+    /**
+     * Returns the meter Id for a given bandwidth profile Id.
+     * @param deviceId the device id
+     * @param bandwidthProfileId the bandwidth profile Id
+     * @return the meter Id
+     */
+    MeterId getMeterIdForBandwidthProfile(DeviceId deviceId, String bandwidthProfileId);
+
+    /**
+     * Purges all the meters on a device.
+     * @param deviceId the device
+     */
+    void purgeDeviceMeters(DeviceId deviceId);
+
+    /**
+     * Return all programmed meters for all OLTs controlled by this ONOS cluster.
+     * @return a map, with the device keys, and entry of map with bp Id and corresponding meter
+     */
+    Map<DeviceId, Map<String, MeterData>> getProgrammedMeters();
+
+}
diff --git a/api/src/main/java/org/opencord/olt/OltPortStatus.java b/api/src/main/java/org/opencord/olt/OltPortStatus.java
new file mode 100644
index 0000000..6c2c908
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/OltPortStatus.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import java.util.Objects;
+
+/**
+ * OltPortStatus is used to keep track of the flow status for a subscriber service.
+ */
+public class OltPortStatus {
+    // TODO consider adding a lastUpdated field, it may help with debugging
+    public OltFlowsStatus defaultEapolStatus;
+    public OltFlowsStatus subscriberEapolStatus;
+    public OltFlowsStatus subscriberFlowsStatus;
+    // NOTE we need to keep track of the DHCP status as that is installed before the other flows
+    // if macLearning is enabled (DHCP is needed to learn the MacAddress from the host)
+    public OltFlowsStatus dhcpStatus;
+    public OltFlowsStatus pppoeStatus;
+
+    /**
+     * Creates a OltPortStatus from a group of OltFlowsStatus.
+     *
+     * @param defaultEapolStatus     the default
+     * @param subscriberEapolStatus  the status
+     * @param subscriberFlowsStatus  the bandwidth profile
+     * @param dhcpStatus             the bandwidth profile
+     * @param pppoeStatus            the bandwidth profile
+     */
+    public OltPortStatus(OltFlowsStatus defaultEapolStatus,
+                         OltFlowsStatus subscriberEapolStatus,
+                         OltFlowsStatus subscriberFlowsStatus,
+                         OltFlowsStatus dhcpStatus,
+                         OltFlowsStatus pppoeStatus) {
+        this.defaultEapolStatus = defaultEapolStatus;
+        this.subscriberEapolStatus = subscriberEapolStatus;
+        this.subscriberFlowsStatus = subscriberFlowsStatus;
+        this.dhcpStatus = dhcpStatus;
+        this.pppoeStatus = pppoeStatus;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        OltPortStatus that = (OltPortStatus) o;
+        return defaultEapolStatus == that.defaultEapolStatus
+                && subscriberEapolStatus == that.subscriberEapolStatus
+                && subscriberFlowsStatus == that.subscriberFlowsStatus
+                && dhcpStatus == that.dhcpStatus;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(defaultEapolStatus, subscriberEapolStatus,
+                            subscriberFlowsStatus, dhcpStatus);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("OltPortStatus{");
+        sb.append("defaultEapolStatus=").append(defaultEapolStatus);
+        sb.append(", subscriberEapolStatus=").append(subscriberEapolStatus);
+        sb.append(", subscriberFlowsStatus=").append(subscriberFlowsStatus);
+        sb.append(", dhcpStatus=").append(dhcpStatus);
+        sb.append('}');
+        return sb.toString();
+    }
+}
diff --git a/api/src/main/java/org/opencord/olt/ServiceKey.java b/api/src/main/java/org/opencord/olt/ServiceKey.java
new file mode 100644
index 0000000..07089e4
--- /dev/null
+++ b/api/src/main/java/org/opencord/olt/ServiceKey.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021-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.opencord.olt;
+
+import org.opencord.sadis.UniTagInformation;
+
+import java.util.Objects;
+
+/**
+ * SubscriberKey is used to identify the combination of a subscriber and a service.
+ */
+public class ServiceKey {
+    private AccessDevicePort port;
+    private UniTagInformation service;
+
+
+    public ServiceKey(AccessDevicePort port, UniTagInformation service) {
+        this.port = port;
+        this.service = service;
+    }
+
+    public AccessDevicePort getPort() {
+        return port;
+    }
+
+    public void setPort(AccessDevicePort port) {
+        this.port = port;
+    }
+
+    public UniTagInformation getService() {
+        return service;
+    }
+
+    public void setService(UniTagInformation service) {
+        this.service = service;
+    }
+
+    @Override
+    public String toString() {
+        return this.port.toString() + " - " + this.service.getServiceName();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        ServiceKey that = (ServiceKey) o;
+        boolean isPortEqual = Objects.equals(port, that.port);
+        boolean isServiceEqual = Objects.equals(service, that.service);
+
+        return isPortEqual && isServiceEqual;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(port, service);
+    }
+}