diff --git a/agent/src/core_utils.cc b/agent/src/core_utils.cc
new file mode 100644
index 0000000..f63ca52
--- /dev/null
+++ b/agent/src/core_utils.cc
@@ -0,0 +1,1221 @@
+/*
+ * Copyright 2018-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.
+ */
+
+#include "core_utils.h"
+
+std::string serial_number_to_str(bcmolt_serial_number* serial_number) {
+#define SERIAL_NUMBER_SIZE 12
+    char buff[SERIAL_NUMBER_SIZE+1];
+
+    sprintf(buff, "%c%c%c%c%1X%1X%1X%1X%1X%1X%1X%1X",
+            serial_number->vendor_id.arr[0],
+            serial_number->vendor_id.arr[1],
+            serial_number->vendor_id.arr[2],
+            serial_number->vendor_id.arr[3],
+            serial_number->vendor_specific.arr[0]>>4 & 0x0f,
+            serial_number->vendor_specific.arr[0] & 0x0f,
+            serial_number->vendor_specific.arr[1]>>4 & 0x0f,
+            serial_number->vendor_specific.arr[1] & 0x0f,
+            serial_number->vendor_specific.arr[2]>>4 & 0x0f,
+            serial_number->vendor_specific.arr[2] & 0x0f,
+            serial_number->vendor_specific.arr[3]>>4 & 0x0f,
+            serial_number->vendor_specific.arr[3] & 0x0f);
+
+    return buff;
+}
+
+std::string vendor_specific_to_str(char const * const vendor_specific) {
+    char buff[SERIAL_NUMBER_SIZE+1];
+
+    sprintf(buff, "%1X%1X%1X%1X%1X%1X%1X%1X",
+            vendor_specific[0]>>4 & 0x0f,
+            vendor_specific[0] & 0x0f,
+            vendor_specific[1]>>4 & 0x0f,
+            vendor_specific[1] & 0x0f,
+            vendor_specific[2]>>4 & 0x0f,
+            vendor_specific[2] & 0x0f,
+            vendor_specific[3]>>4 & 0x0f,
+            vendor_specific[3] & 0x0f);
+
+    return buff;
+}
+/**
+* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
+* Every NNI port and PON port have default scheduler.
+* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
+* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
+*
+* @param intf_id NNI or PON interface ID
+* @param direction "upstream" or "downstream"
+*
+* @return default scheduler ID for the given interface.
+*/
+
+uint16_t get_dev_id(void) {
+    return dev_id;
+}
+
+int get_default_tm_sched_id(int intf_id, std::string direction) {
+    if (direction.compare(upstream) == 0) {
+        return tm_upstream_sched_id_start + intf_id;
+    } else if (direction.compare(downstream) == 0) {
+        return tm_downstream_sched_id_start + intf_id;
+    }
+    else {
+        OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
+        return 0;
+    }
+}
+
+/**
+* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
+* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
+* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
+*
+* @param intf_id NNI or PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param gemport_id GEM Port ID
+* @param direction Upstream or downstream
+*
+* @return tm_sched_id
+*/
+uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+    sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+    int sched_id = -1;
+
+    std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
+    if (it != sched_map.end()) {
+        sched_id = it->second;
+    }
+    if (sched_id != -1) {
+        return sched_id;
+    }
+
+    bcmos_fastlock_lock(&data_lock);
+    // Complexity of O(n). Is there better way that can avoid linear search?
+    for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
+        if (tm_sched_bitset[sched_id] == 0) {
+            tm_sched_bitset[sched_id] = 1;
+            break;
+        }
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+
+    if (sched_id < MAX_TM_SCHED_ID) {
+        bcmos_fastlock_lock(&data_lock);
+        sched_map[key] = sched_id;
+        bcmos_fastlock_unlock(&data_lock, 0);
+        return sched_id;
+    } else {
+        return -1;
+    }
+}
+
+/**
+* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
+*
+* @param intf_id NNI or PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param gemport_id GEM Port ID
+* @param direction Upstream or downstream
+*/
+void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+    sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+    std::map<sched_map_key_tuple, int>::const_iterator it;
+    bcmos_fastlock_lock(&data_lock);
+    it = sched_map.find(key);
+    if (it != sched_map.end()) {
+        tm_sched_bitset[it->second] = 0;
+        sched_map.erase(it);
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+    sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+    std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
+    if (it != sched_map.end()) {
+        return true;
+    }
+    return false;
+}
+
+/**
+* Check whether given two tm qmp profiles are equal or not
+*
+* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
+* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
+*
+* @return boolean, true if given tmq_map_profiles are equal else false
+*/
+
+bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
+    for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
+        if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+/**
+* Modifies given queues_pbit_map to parsable format
+* e.g: Modifes "0b00000101" to "10100000"
+*
+* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
+* @param size Queue count
+*
+* @return string queues_pbit_map
+*/
+std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
+    for(uint32_t i=0; i < size; i++) {
+        /* Deletes 2 characters from index number 0 */
+        queues_pbit_map[i].erase(0, 2);
+        std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
+    }
+    return queues_pbit_map;
+}
+
+/**
+* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
+*
+* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
+* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
+* @param size Queue count
+*
+* @return <vector> TM QUEUE MAPPING PROFILE
+*/
+std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
+    std::vector<uint32_t> tmq_map_profile(8,0);
+
+    for(uint32_t i=0; i < size; i++) {
+        for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
+            if (queues_pbit_map[i][j]=='1') {
+                tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
+            }
+        }
+    }
+    return tmq_map_profile;
+}
+
+/**
+* Gets corresponding tm_qmp_id for a given tmq_map_profile
+*
+* @param <vector> TM QUEUE MAPPING PROFILE
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
+    int tm_qmp_id = -1;
+
+    std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
+    while(it != qmp_id_to_qmp_map.end()) {
+        if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
+            tm_qmp_id = it->first;
+            break;
+        }
+        it++;
+    }
+    return tm_qmp_id;
+}
+
+/**
+* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
+*/
+void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
+                             uint32_t uni_id, int tm_qmp_id) {
+   bcmos_fastlock_lock(&data_lock);
+   sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+   sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
+   bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+/**
+* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
+    sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+    int tm_qmp_id = -1;
+
+    std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
+    if (it != sched_qmp_id_map.end()) {
+        tm_qmp_id = it->second;
+    }
+    return tm_qmp_id;
+}
+
+/**
+* Gets a unique tm_qmp_id for a given tmq_map_profile
+* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
+* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param <vector> TM QUEUE MAPPING PROFILE
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
+                  std::vector<uint32_t> tmq_map_profile) {
+    int tm_qmp_id;
+
+    bcmos_fastlock_lock(&data_lock);
+    /* Complexity of O(n). Is there better way that can avoid linear search? */
+    for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
+        if (tm_qmp_bitset[tm_qmp_id] == 0) {
+            tm_qmp_bitset[tm_qmp_id] = 1;
+            break;
+        }
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+
+    if (tm_qmp_id < MAX_TM_QMP_ID) {
+        bcmos_fastlock_lock(&data_lock);
+        qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
+        bcmos_fastlock_unlock(&data_lock, 0);
+        update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
+        return tm_qmp_id;
+    } else {
+        return -1;
+    }
+}
+
+/**
+* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
+*
+* @return boolean, true if no more reference for TM QMP else false
+*/
+bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
+                    uint32_t uni_id, int tm_qmp_id) {
+    bool result;
+    sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+    std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
+    bcmos_fastlock_lock(&data_lock);
+    if (it != sched_qmp_id_map.end()) {
+        sched_qmp_id_map.erase(it);
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+
+    uint32_t tm_qmp_ref_count = 0;
+    std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
+    while(it2 != sched_qmp_id_map.end()) {
+        if(it2->second == tm_qmp_id) {
+            tm_qmp_ref_count++;
+        }
+        it2++;
+    }
+
+    if (tm_qmp_ref_count == 0) {
+        std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
+        if (it3 != qmp_id_to_qmp_map.end()) {
+            bcmos_fastlock_lock(&data_lock);
+            tm_qmp_bitset[tm_qmp_id] = 0;
+            qmp_id_to_qmp_map.erase(it3);
+            bcmos_fastlock_unlock(&data_lock, 0);
+            OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
+                        tm_qmp_id, tm_qmp_ref_count);
+            result = true;
+        }
+    } else {
+        OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
+                    tm_qmp_id, tm_qmp_ref_count);
+        result = false;
+    }
+    return result;
+}
+
+// Gets free ACL ID if available, else -1
+int get_acl_id() {
+    int acl_id;
+    bcmos_fastlock_lock(&data_lock);
+    /* Complexity of O(n). Is there better way that can avoid linear search? */
+    for (acl_id = 0; acl_id < MAX_ACL_ID; acl_id++) {
+        if (acl_id_bitset[acl_id] == 0) {
+            acl_id_bitset[acl_id] = 1;
+            break;
+        }
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+    if (acl_id < MAX_ACL_ID) {
+        return acl_id ;
+    } else {
+        return -1;
+    }
+}
+
+// Frees up the ACL ID.
+void free_acl_id (int acl_id) {
+    if (acl_id < MAX_ACL_ID) {
+        bcmos_fastlock_lock(&data_lock);
+        acl_id_bitset[acl_id] = 0;
+        bcmos_fastlock_unlock(&data_lock, 0);
+    }
+}
+
+/**
+* Returns qos type as string
+*
+* @param qos_type bcmolt_egress_qos_type enum
+*/
+std::string get_qos_type_as_string(bcmolt_egress_qos_type qos_type) {
+    switch (qos_type)
+    {
+        case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE: return "FIXED_QUEUE";
+        case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE: return "TC_TO_QUEUE";
+        case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC: return "PBIT_TO_TC";
+        case BCMOLT_EGRESS_QOS_TYPE_NONE: return "NONE";
+        case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE: return "PRIORITY_TO_QUEUE";
+        default: OPENOLT_LOG(ERROR, openolt_log_id, "qos-type-not-supported %d\n", qos_type);
+                 return "qos-type-not-supported";
+    }
+}
+
+/**
+* Gets/Updates qos type for given pon_intf_id, onu_id, uni_id
+*
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param queue_size TrafficQueues Size
+*
+* @return qos_type
+*/
+bcmolt_egress_qos_type get_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t queue_size) {
+    qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
+    bcmolt_egress_qos_type egress_qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
+    std::string qos_string;
+
+    std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
+    if (it != qos_type_map.end()) {
+        egress_qos_type = it->second;
+        qos_string = get_qos_type_as_string(egress_qos_type);
+        OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
+                    pon_intf_id, onu_id, uni_id, qos_string.c_str());
+    }
+    else {
+        /* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
+           associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
+           else Priority to Queue */
+        egress_qos_type = (queue_size > 1) ? \
+            BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
+        bcmos_fastlock_lock(&data_lock);
+        qos_type_map.insert(make_pair(key, egress_qos_type));
+        bcmos_fastlock_unlock(&data_lock, 0);
+        qos_string = get_qos_type_as_string(egress_qos_type);
+        OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
+                    pon_intf_id, onu_id, uni_id, qos_string.c_str());
+    }
+    return egress_qos_type;
+}
+
+/**
+* Clears qos type for given pon_intf_id, onu_id, uni_id
+*
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+*/
+void clear_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
+    qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
+    std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
+    bcmos_fastlock_lock(&data_lock);
+    if (it != qos_type_map.end()) {
+        qos_type_map.erase(it);
+        OPENOLT_LOG(INFO, openolt_log_id, "Cleared Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d\n", \
+                    pon_intf_id, onu_id, uni_id);
+    }
+    bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+/**
+* Returns Scheduler/Queue direction as string
+*
+* @param direction as specified in tech_profile.proto
+*/
+std::string GetDirection(int direction) {
+    switch (direction)
+    {
+        case tech_profile::Direction::UPSTREAM: return upstream;
+        case tech_profile::Direction::DOWNSTREAM: return downstream;
+        default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
+                 return "direction-not-supported";
+    }
+}
+
+// This method handles waiting for AllocObject configuration.
+// Returns error if the AllocObject is not in the appropriate state based on action requested.
+bcmos_errno wait_for_alloc_action(uint32_t intf_id, uint32_t alloc_id, AllocCfgAction action) {
+    Queue<alloc_cfg_complete_result> cfg_result;
+    alloc_cfg_compltd_key k(intf_id, alloc_id);
+    alloc_cfg_compltd_map[k] =  &cfg_result;
+    bcmos_errno err = BCM_ERR_OK;
+    #ifdef TEST_MODE
+    ALLOC_CFG_FLAG = true;
+    #endif
+
+    // Try to pop the result from BAL with a timeout of ALLOC_CFG_COMPLETE_WAIT_TIMEOUT ms
+    std::pair<alloc_cfg_complete_result, bool> result = cfg_result.pop(ALLOC_CFG_COMPLETE_WAIT_TIMEOUT);
+    if (result.second == false) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "timeout waiting for alloc cfg complete indication intf_id %d, alloc_id %d\n",
+                    intf_id, alloc_id);
+        // Invalidate the queue pointer.
+        bcmos_fastlock_lock(&alloc_cfg_wait_lock);
+        alloc_cfg_compltd_map[k] = NULL;
+        bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+        err = BCM_ERR_INTERNAL;
+        #ifdef TEST_MODE
+        ALLOC_CFG_FLAG = false;
+        #endif
+    }
+    else if (result.first.status == ALLOC_CFG_STATUS_FAIL) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "error processing alloc cfg request intf_id %d, alloc_id %d\n",
+                    intf_id, alloc_id);
+        err = BCM_ERR_INTERNAL;
+    }
+
+    if (err == BCM_ERR_OK) {
+        if (action == ALLOC_OBJECT_CREATE) {
+            if (result.first.state != ALLOC_OBJECT_STATE_ACTIVE) {
+                OPENOLT_LOG(ERROR, openolt_log_id, "alloc object not in active state intf_id %d, alloc_id %d alloc_obj_state %d\n",
+                            intf_id, alloc_id, result.first.state);
+               err = BCM_ERR_INTERNAL;
+            } else {
+                OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation success, intf_id %d, alloc_id %d\n",
+                            intf_id, alloc_id);
+            }
+        } else { // ALLOC_OBJECT_DELETE
+              if (result.first.state != ALLOC_OBJECT_STATE_NOT_CONFIGURED) {
+                  OPENOLT_LOG(ERROR, openolt_log_id, "alloc object is not reset intf_id %d, alloc_id %d alloc_obj_state %d\n",
+                              intf_id, alloc_id, result.first.state);
+                  err = BCM_ERR_INTERNAL;
+              } else {
+                  OPENOLT_LOG(INFO, openolt_log_id, "Remove alloc object success, intf_id %d, alloc_id %d\n",
+                              intf_id, alloc_id);
+              }
+        }
+    }
+
+    // Remove entry from map
+    bcmos_fastlock_lock(&alloc_cfg_wait_lock);
+    alloc_cfg_compltd_map.erase(k);
+    bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+    #ifdef TEST_MODE
+    ALLOC_CFG_FLAG = false;
+    #endif
+    return err;
+}
+
+char* openolt_read_sysinfo(const char* field_name, char* field_val)
+{
+   FILE *fp;
+   /* Prepare the command*/
+   char command[150];
+
+   snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
+   /* Open the command for reading. */
+   fp = popen(command, "r");
+   if (fp == NULL) {
+       /*The client has to check for a Null field value in this case*/
+       OPENOLT_LOG(INFO, openolt_log_id,  "Failed to query the %s\n", field_name);
+       return field_val;
+   }
+
+   /*Read the field value*/
+   if (fp) {
+       uint8_t ret;
+       ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
+       if (ret >= OPENOLT_FIELD_LEN)
+           OPENOLT_LOG(INFO, openolt_log_id,  "Read data length %u\n", ret);
+       pclose(fp);
+   }
+   return field_val;
+}
+
+Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
+{
+    openolt::Indication ind;
+    openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
+
+    intf_oper_ind->set_type(type);
+    intf_oper_ind->set_intf_id(intf_id);
+    intf_oper_ind->set_oper_state(state);
+    ind.set_allocated_intf_oper_ind(intf_oper_ind);
+    oltIndQ.push(ind);
+    return Status::OK;
+}
+
+#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
+
+/* Build CLI prompt */
+void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
+{
+    snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
+}
+
+int _bal_apiend_cli_thread_handler(long data)
+{
+    char init_string[]="\n";
+    bcmcli_session *sess = current_session;
+    bcmos_task_parm bal_cli_task_p_dummy;
+
+    /* Switch to interactive mode if not stopped in the init script */
+    if (!bcmcli_is_stopped(sess)) {
+        /* Force a CLI command prompt
+         * The string passed into the parse function
+         * must be modifiable, so a string constant like
+         * bcmcli_parse(current_session, "\n") will not
+         * work.
+         */
+        bcmcli_parse(sess, init_string);
+
+        /* Process user input until EOF or quit command */
+        bcmcli_driver(sess);
+    }
+    OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
+
+    /* Cleanup */
+    bcmcli_session_close(current_session);
+    bcmcli_token_destroy(NULL);
+    return 0;
+}
+
+/* Init API CLI commands for the current device */
+bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
+{
+    bcmos_errno rc;
+
+    api_parent_dir = parent_dir;
+
+    rc = bcm_api_cli_set_commands(session);
+
+#ifdef BCM_SUBSYSTEM_HOST
+    /* Subscribe for device change indication */
+    rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
+#endif
+
+    return rc;
+}
+
+bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmcli_stop(session);
+    bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
+    status_bcm_cli_quit = BCMOS_TRUE;
+
+    return BCM_ERR_OK;
+}
+
+int get_status_bcm_cli_quit(void) {
+     return status_bcm_cli_quit;
+}
+
+bcmos_errno bcmolt_apiend_cli_init() {
+    bcmos_errno ret;
+    bcmos_task_parm bal_cli_task_p = {};
+    bcmos_task_parm bal_cli_task_p_dummy;
+
+    /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
+    if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy)) {
+        /* Create BAL CLI thread */
+        bal_cli_task_p.name = bal_cli_thread_name;
+        bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
+        bal_cli_task_p.priority = TASK_PRIORITY_CLI;
+
+        ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
+        if (BCM_ERR_OK != ret) {
+            bcmos_printf("Couldn't create BAL API end CLI thread\n");
+            return ret;
+        }
+    }
+}
+
+bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
+    bcmos_errno err;
+    bcmolt_pon_interface_key pon_key;
+    bcmolt_pon_interface_cfg pon_cfg;
+    pon_key.pon_ni = pon_ni;
+
+    BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
+    BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
+    BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
+    #ifdef TEST_MODE
+    // It is impossible to mock the setting of pon_cfg.data.state because
+    // the actual bcmolt_cfg_get passes the address of pon_cfg.hdr and we cannot
+    // set the pon_cfg.data.state. So a new stub function is created and address
+    // of pon_cfg is passed. This is one-of case where we need to add test specific
+    // code in production code.
+    err = bcmolt_cfg_get__pon_intf_stub(dev_id, &pon_cfg);
+    #else
+    err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
+    #endif
+    *state = pon_cfg.data.state;
+    return err;
+}
+
+/* Same as bcmolt_cfg_get but with added logic of retrying the API
+   in case of some specific failures like timeout or object not yet ready
+*/
+bcmos_errno bcmolt_cfg_get_mult_retry(bcmolt_oltid olt, bcmolt_cfg *cfg) {
+    bcmos_errno err;
+    uint32_t current_try = 0;
+
+    while (current_try < MAX_BAL_API_RETRY_COUNT) {
+        err = bcmolt_cfg_get(olt, cfg);
+        current_try++;
+
+        if (err == BCM_ERR_STATE || err == BCM_ERR_TIMEOUT) {
+            OPENOLT_LOG(WARNING, openolt_log_id, "bcmolt_cfg_get: err = %s\n", bcmos_strerror(err));
+            bcmos_usleep(BAL_API_RETRY_TIME_IN_USECS);
+            continue;
+        }
+        else {
+           break;
+        }
+    }
+
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "bcmolt_cfg_get tried (%d) times with retry time(%d usecs) err = %s\n",
+                           current_try,
+                           BAL_API_RETRY_TIME_IN_USECS,
+                           bcmos_strerror(err));
+    }
+    return err;
+}
+
+
+unsigned NumNniIf_() {return num_of_nni_ports;}
+unsigned NumPonIf_() {return num_of_pon_ports;}
+
+bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
+    bcmos_errno err;
+    bcmolt_nni_interface_key nni_key;
+    bcmolt_nni_interface_cfg nni_cfg;
+    nni_key.id = id;
+
+    BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
+    BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
+    #ifdef TEST_MODE
+    // It is impossible to mock the setting of nni_cfg.data.state because
+    // the actual bcmolt_cfg_get passes the address of nni_cfg.hdr and we cannot
+    // set the nni_cfg.data.state. So a new stub function is created and address
+    // of nni_cfg is passed. This is one-of case where we need to add test specific
+    // code in production code.
+    err = bcmolt_cfg_get__nni_intf_stub(dev_id, &nni_cfg);
+    #else
+    err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
+    #endif
+    *state = nni_cfg.data.state;
+    return err;
+}
+
+Status install_gem_port(int32_t intf_id, int32_t onu_id, int32_t gemport_id) {
+    bcmos_errno err;
+    bcmolt_itupon_gem_cfg cfg; /* declare main API struct */
+    bcmolt_itupon_gem_key key = {}; /* declare key */
+    bcmolt_gem_port_configuration configuration = {};
+
+    key.pon_ni = intf_id;
+    key.gem_port_id = gemport_id;
+
+    BCMOLT_CFG_INIT(&cfg, itupon_gem, key);
+
+    bcmolt_gem_port_direction configuration_direction;
+    configuration_direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
+    BCMOLT_FIELD_SET(&configuration, gem_port_configuration, direction, configuration_direction);
+
+    bcmolt_gem_port_type configuration_type;
+    configuration_type = BCMOLT_GEM_PORT_TYPE_UNICAST;
+    BCMOLT_FIELD_SET(&configuration, gem_port_configuration, type, configuration_type);
+
+    BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, configuration, configuration);
+
+    BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, onu_id, onu_id);
+
+    bcmolt_control_state encryption_mode;
+    encryption_mode = BCMOLT_CONTROL_STATE_DISABLE;
+    BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, encryption_mode, encryption_mode);
+
+    bcmolt_us_gem_port_destination upstream_destination_queue;
+    upstream_destination_queue = BCMOLT_US_GEM_PORT_DESTINATION_DATA;
+    BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, upstream_destination_queue, upstream_destination_queue);
+
+    bcmolt_control_state control;
+    control = BCMOLT_CONTROL_STATE_ENABLE;
+    BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, control, control);
+
+    err = bcmolt_cfg_set(dev_id, &cfg.hdr);
+    if(err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "failed to install gem_port = %d\n", gemport_id);
+        return bcm_to_grpc_err(err, "Access_Control set ITU PON Gem port failed");
+    }
+
+    OPENOLT_LOG(INFO, openolt_log_id, "gem port installed successfully = %d\n", gemport_id);
+
+    return Status::OK;
+}
+
+Status remove_gem_port(int32_t intf_id, int32_t gemport_id) {
+    bcmolt_itupon_gem_cfg gem_cfg;
+    bcmolt_itupon_gem_key key = {
+        .pon_ni = (bcmolt_interface)intf_id,
+        .gem_port_id = (bcmolt_gem_port_id)gemport_id
+    };
+    bcmos_errno err;
+
+    BCMOLT_CFG_INIT(&gem_cfg, itupon_gem, key);
+    err = bcmolt_cfg_clear(dev_id, &gem_cfg.hdr);
+    if (err != BCM_ERR_OK)
+    {
+        OPENOLT_LOG(ERROR, openolt_log_id, "failed to remove gem_port = %d err=%s\n", gemport_id, gem_cfg.hdr.hdr.err_text);
+        return bcm_to_grpc_err(err, "Access_Control clear ITU PON Gem port failed");
+    }
+
+    OPENOLT_LOG(INFO, openolt_log_id, "gem port removed successfully = %d\n", gemport_id);
+
+    return Status::OK;
+}
+
+Status update_acl_interface(int32_t intf_id, bcmolt_interface_type intf_type, uint32_t access_control_id,
+                bcmolt_members_update_command acl_cmd) {
+    bcmos_errno err;
+    bcmolt_access_control_interfaces_update oper; /* declare main API struct */
+    bcmolt_access_control_key acl_key = {}; /* declare key */
+    bcmolt_intf_ref interface_ref_list_elem = {};
+    bcmolt_interface_type interface_ref_list_elem_intf_type;
+    bcmolt_interface_id interface_ref_list_elem_intf_id;
+    bcmolt_intf_ref_list_u8 interface_ref_list = {};
+
+    if (acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_ADD && acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "acl cmd = %d not supported currently\n", acl_cmd);
+        return bcm_to_grpc_err(BCM_ERR_PARM, "unsupported acl cmd");
+    }
+    interface_ref_list.arr = (bcmolt_intf_ref*)bcmos_calloc(sizeof(bcmolt_intf_ref)*1);
+
+    if (interface_ref_list.arr == NULL)
+         return bcm_to_grpc_err(BCM_ERR_PARM, "allocate interface_ref_list failed");
+    OPENOLT_LOG(INFO, openolt_log_id, "update acl interface received for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+            intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+            acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+
+    acl_key.id = access_control_id;
+
+    /* Initialize the API struct. */
+    BCMOLT_OPER_INIT(&oper, access_control, interfaces_update, acl_key);
+
+    bcmolt_members_update_command command;
+    command = acl_cmd;
+    BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, command, command);
+
+    interface_ref_list_elem_intf_type = intf_type;
+    BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_type, interface_ref_list_elem_intf_type);
+
+    interface_ref_list_elem_intf_id = intf_id;
+    BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_id, interface_ref_list_elem_intf_id);
+
+    interface_ref_list.len = 1;
+    BCMOLT_ARRAY_ELEM_SET(&interface_ref_list, 0, interface_ref_list_elem);
+
+    BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, interface_ref_list, interface_ref_list);
+
+    err =  bcmolt_oper_submit(dev_id, &oper.hdr);
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "update acl interface fail for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+            intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+            acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+        return bcm_to_grpc_err(err, "Access_Control submit interface failed");
+    }
+
+    bcmos_free(interface_ref_list.arr);
+    OPENOLT_LOG(INFO, openolt_log_id, "update acl interface success for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+            intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+            acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+
+    return Status::OK;
+}
+
+Status install_acl(const acl_classifier_key acl_key) {
+
+    bcmos_errno err;
+    bcmolt_access_control_cfg cfg;
+    bcmolt_access_control_key key = { };
+    bcmolt_classifier c_val = { };
+    // hardcode the action for now.
+    bcmolt_access_control_fwd_action_type action_type = BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST;
+
+    int acl_id = get_acl_id();
+    if (acl_id < 0) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "exhausted acl_id for eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d\n",
+                acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port);
+        bcmos_fastlock_unlock(&data_lock, 0);
+        return bcm_to_grpc_err(BCM_ERR_INTERNAL, "exhausted acl id");
+    }
+
+    key.id = acl_id;
+    /* config access control instance */
+    BCMOLT_CFG_INIT(&cfg, access_control, key);
+
+    if (acl_key.ether_type > 0) {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ether_type 0x%04x\n", acl_key.ether_type);
+        BCMOLT_FIELD_SET(&c_val, classifier, ether_type, acl_key.ether_type);
+    }
+
+    if (acl_key.ip_proto > 0) {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ip_proto %d\n", acl_key.ip_proto);
+        BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, acl_key.ip_proto);
+    }
+
+    if (acl_key.dst_port > 0) {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify dst_port %d\n", acl_key.dst_port);
+        BCMOLT_FIELD_SET(&c_val, classifier, dst_port, acl_key.dst_port);
+    }
+
+    if (acl_key.src_port > 0) {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify src_port %d\n", acl_key.src_port);
+        BCMOLT_FIELD_SET(&c_val, classifier, src_port, acl_key.src_port);
+    }
+
+    BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
+    BCMOLT_MSG_FIELD_SET(&cfg, priority, 10000);
+    BCMOLT_MSG_FIELD_SET(&cfg, statistics_control, BCMOLT_CONTROL_STATE_ENABLE);
+
+    BCMOLT_MSG_FIELD_SET(&cfg, forwarding_action.action, action_type);
+
+    err = bcmolt_cfg_set(dev_id, &cfg.hdr);
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control set configuration failed, Error %d\n", err);
+        // Free the acl_id
+        free_acl_id(acl_id);
+        return bcm_to_grpc_err(err, "Access_Control set configuration failed");
+    }
+
+    ACL_LOG(INFO, "ACL add ok", err);
+
+    // Update the map that we have installed an acl for the given classfier.
+    acl_classifier_to_acl_id_map[acl_key] = acl_id;
+    return Status::OK;
+}
+
+Status remove_acl(int acl_id) {
+    bcmos_errno err;
+    bcmolt_access_control_cfg cfg; /* declare main API struct */
+    bcmolt_access_control_key key = {}; /* declare key */
+
+    key.id = acl_id;
+
+    /* Initialize the API struct. */
+    BCMOLT_CFG_INIT(&cfg, access_control, key);
+    BCMOLT_FIELD_SET_PRESENT(&cfg.data, access_control_cfg_data, state);
+    err = bcmolt_cfg_get(dev_id, &cfg.hdr);
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control get state failed\n");
+        return bcm_to_grpc_err(err, "Access_Control get state failed");
+    }
+
+    if (cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
+        key.id = acl_id;
+        /* Initialize the API struct. */
+        BCMOLT_CFG_INIT(&cfg, access_control, key);
+
+        err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
+        if (err != BCM_ERR_OK) {
+            // Should we free acl_id here ? We should ideally never land here..
+            OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing Access_Control rule ID %d\n",
+                err, acl_id);
+            return Status(grpc::StatusCode::INTERNAL, "Failed to remove Access_Control");
+        }
+    }
+
+    // Free up acl_id
+    free_acl_id(acl_id);
+
+    OPENOLT_LOG(INFO, openolt_log_id, "acl removed successfully %d\n", acl_id);
+
+    return Status::OK;
+}
+
+// Formulates ACL Classifier Key based on the following fields
+// a. ether_type b. ip_proto c. src_port d. dst_port
+// If any of the field is not available it is populated as -1.
+void formulate_acl_classifier_key(acl_classifier_key *key, const ::openolt::Classifier& classifier) {
+
+        // TODO: Is 0 a valid value for any of the following classifiers?
+        // because in the that case, the 'if' check would fail and -1 would be filled as value.
+        //
+        if (classifier.eth_type()) {
+            OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
+            key->ether_type = classifier.eth_type();
+        } else key->ether_type = -1;
+
+        if (classifier.ip_proto()) {
+            OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
+            key->ip_proto = classifier.ip_proto();
+        } else key->ip_proto = -1;
+
+
+        if (classifier.src_port()) {
+            OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
+            key->src_port = classifier.src_port();
+        } else key->src_port = -1;
+
+
+        if (classifier.dst_port()) {
+            OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
+            key->dst_port = classifier.dst_port();
+        } else key->dst_port = -1;
+}
+
+Status handle_acl_rule_install(int32_t onu_id, uint32_t flow_id,
+                               const std::string flow_type, int32_t access_intf_id,
+                               int32_t network_intf_id, int32_t gemport_id,
+                               const ::openolt::Classifier& classifier) {
+    int acl_id;
+    int32_t intf_id = flow_type.compare(upstream) == 0? access_intf_id: network_intf_id;
+    const std::string intf_type = flow_type.compare(upstream) == 0? "pon": "nni";
+    bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
+
+    Status resp;
+
+    // few map keys we are going to use later.
+    flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
+    gem_id_intf_id gem_intf(gemport_id, access_intf_id);
+    acl_classifier_key acl_key;
+    formulate_acl_classifier_key(&acl_key, classifier);
+    const acl_classifier_key acl_key_const = {.ether_type=acl_key.ether_type, .ip_proto=acl_key.ip_proto,
+        .src_port=acl_key.src_port, .dst_port=acl_key.dst_port};
+
+    bcmos_fastlock_lock(&data_lock);
+
+    // Check if the acl is already installed
+    if (acl_classifier_to_acl_id_map.count(acl_key_const) > 0) {
+        // retreive the acl_id
+        acl_id = acl_classifier_to_acl_id_map[acl_key_const];
+        acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
+        if (flow_to_acl_map.count(fl_id_fl_dir)) {
+            // coult happen if same trap flow is received again
+            OPENOLT_LOG(INFO, openolt_log_id, "flow and related acl already handled, nothing more to do\n");
+            bcmos_fastlock_unlock(&data_lock, 0);
+            return Status::OK;
+        }
+
+        OPENOLT_LOG(INFO, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d already installed with acl id = %u\n",
+                flow_id, acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port, acl_id);
+
+        // The acl_ref_cnt is needed to know how many flows refer an ACL.
+        // When the flow is removed, we decrement the reference count.
+        // When the reference count becomes 0, we remove the ACL.
+        if (acl_ref_cnt.count(acl_id) > 0) {
+            acl_ref_cnt[acl_id] ++;
+        } else {
+            // We should ideally not land here. The acl_ref_cnt should have been
+            // initialized the first time acl was installed.
+            acl_ref_cnt[acl_id] = 1;
+        }
+
+    } else {
+        resp = install_acl(acl_key_const);
+        if (!resp.ok()) {
+            OPENOLT_LOG(ERROR, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d failed\n",
+                    flow_id, acl_key_const.ether_type, acl_key_const.ip_proto, acl_key_const.src_port, acl_key_const.dst_port);
+            bcmos_fastlock_unlock(&data_lock, 0);
+            return resp;
+        }
+
+        acl_id = acl_classifier_to_acl_id_map[acl_key_const];
+
+        // Initialize the acl reference count
+        acl_ref_cnt[acl_id] = 1;
+
+        OPENOLT_LOG(INFO, openolt_log_id, "acl add success for flow_id=%u with acl_id=%d\n", flow_id, acl_id);
+    }
+
+    // Register the interface for the given acl
+    acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
+    // This is needed to keep a track of which interface (pon/nni) has registered for an ACL.
+    // If it is registered, how many flows refer to it.
+    if (intf_acl_registration_ref_cnt.count(ac_id_inf_id_inf_type) > 0) {
+        intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]++;
+    } else {
+        // The given interface is not registered for the ACL. We need to do it now.
+        resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_ADD);
+        if (!resp.ok()){
+            OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
+            // TODO: Ideally we should return error from hear and clean up other other stateful
+            // counters we creaed earlier. Will leave it out for now.
+        } 
+        intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] = 1;
+    }
+
+
+    // Install the gem port if needed.
+    if (gemport_id > 0 && access_intf_id >= 0) {
+        if (gem_ref_cnt.count(gem_intf) > 0) {
+            // The gem port is already installed
+            // Increment the ref counter indicating number of flows referencing this gem port
+            gem_ref_cnt[gem_intf]++;
+            OPENOLT_LOG(DEBUG, openolt_log_id, "increment gem_ref_cnt in acl handler, ref_cnt=%d\n", gem_ref_cnt[gem_intf]);
+
+        } else {
+            // We should ideally never land here. The gem port should have been created the
+            // first time ACL was installed.
+            // Install the gem port
+            Status resp = install_gem_port(access_intf_id, onu_id, gemport_id);
+            if (!resp.ok()) {
+                // TODO: We might need to reverse all previous data, but leave it out for now.
+                OPENOLT_LOG(ERROR, openolt_log_id, "failed to install the gemport=%d for acl_id=%d, intf_id=%d\n", gemport_id, acl_id, access_intf_id);
+                bcmos_fastlock_unlock(&data_lock, 0);
+                return resp;
+            }
+            // Initialize the refence count for the gemport.
+            gem_ref_cnt[gem_intf] = 1;
+            OPENOLT_LOG(DEBUG, openolt_log_id, "intialized gem ref count in acl handler\n");
+        }
+    } else {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "not incrementing gem_ref_cnt in acl handler flow_id=%d, gemport_id=%d, intf_id=%d\n", flow_id, gemport_id, access_intf_id);
+    }
+
+    // Update the flow_to_acl_map
+    // This info is needed during flow remove. We need to which ACL ID and GEM PORT ID
+    // the flow was referring to.
+    // After retrieving the ACL ID and GEM PORT ID, we decrement the corresponding
+    // reference counters for those ACL ID and GEMPORT ID.
+    acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
+    flow_to_acl_map[fl_id_fl_dir] = ac_id_gm_id_if_id;
+
+    bcmos_fastlock_unlock(&data_lock, 0);
+
+    return Status::OK;
+}
+
+void clear_gem_port(int gemport_id, int access_intf_id) {
+    gem_id_intf_id gem_intf(gemport_id, access_intf_id);
+    if (gemport_id > 0 && access_intf_id >= 0 && gem_ref_cnt.count(gem_intf) > 0) {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+        gem_ref_cnt[gem_intf]--;
+        if (gem_ref_cnt[gem_intf] == 0) {
+            // For datapath flow this may not be necessary (to be verified)
+            remove_gem_port(access_intf_id, gemport_id);
+            gem_ref_cnt.erase(gem_intf);
+            OPENOLT_LOG(DEBUG, openolt_log_id, "removing gem_ref_cnt entry gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+        } else {
+            OPENOLT_LOG(DEBUG, openolt_log_id, "gem_ref_cnt  not zero yet gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+        }
+    } else {
+        OPENOLT_LOG(DEBUG, openolt_log_id, "not decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+    }
+}
+
+Status handle_acl_rule_cleanup(int16_t acl_id, int32_t gemport_id, int32_t intf_id, const std::string flow_type) {
+    const std::string intf_type= flow_type.compare(upstream) == 0 ? "pon": "nni";
+    acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
+    intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]--;
+    if (intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] == 0) {
+        bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
+        Status resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE);
+        if (!resp.ok()){
+            OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
+        }
+        intf_acl_registration_ref_cnt.erase(ac_id_inf_id_inf_type);
+    }
+
+    acl_ref_cnt[acl_id]--;
+    if (acl_ref_cnt[acl_id] == 0) {
+        remove_acl(acl_id);
+        acl_ref_cnt.erase(acl_id);
+        // Iterate acl_classifier_to_acl_id_map and delete classifier the key corresponding to acl_id
+        std::map<acl_classifier_key, uint16_t>::iterator it;
+        for (it=acl_classifier_to_acl_id_map.begin(); it!=acl_classifier_to_acl_id_map.end(); ++it)  {
+            if (it->second == acl_id) {
+                OPENOLT_LOG(INFO, openolt_log_id, "cleared classifier key corresponding to acl_id = %d\n", acl_id);
+                acl_classifier_to_acl_id_map.erase(it->first);
+                break;
+            }
+        }
+    }
+
+    clear_gem_port(gemport_id, intf_id);
+
+    return Status::OK;
+}
+
+Status check_bal_ready() {
+    bcmos_errno err;
+    int maxTrials = 30;
+    bcmolt_olt_cfg olt_cfg = { };
+    bcmolt_olt_key olt_key = { };
+
+    BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
+    BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
+
+    while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
+        if (--maxTrials == 0)
+            return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
+        sleep(5);
+        #ifdef TEST_MODE
+        // It is impossible to mock the setting of olt_cfg.data.bal_state because
+        // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
+        // set the olt_cfg.data.bal_state. So a new stub function is created and address
+        // of olt_cfg is passed. This is one-of case where we need to add test specific
+        // code in production code.
+        if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
+        #else
+        if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
+        #endif
+            continue;
+        }
+        else
+            OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
+    }
+
+    OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
+    return Status::OK;
+}
+
+Status check_connection() {
+    int maxTrials = 60;
+    while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
+        sleep(1);
+        if (--maxTrials == 0)
+            return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
+        else
+            OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
+    }
+    OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
+    return Status::OK;
+}
+
