BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bal_release/src/lib/librscmgr/Makefile b/bal_release/src/lib/librscmgr/Makefile
new file mode 100644
index 0000000..d94cd45
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/Makefile
@@ -0,0 +1,37 @@
+###############################################################################
+#
+#  <:copyright-BRCM:2016:DUAL/GPL:standard
+#  
+#     Copyright (c) 2016 Broadcom
+#     All Rights Reserved
+#  
+#  Unless you and Broadcom execute a separate written software license
+#  agreement governing use of this software, this software is licensed
+#  to you under the terms of the GNU General Public License version 2
+#  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+#  with the following added to such license:
+#  
+#     As a special exception, the copyright holders of this software give
+#     you permission to link this software with independent modules, and
+#     to copy and distribute the resulting executable under terms of your
+#     choice, provided that you also meet, for each linked independent
+#     module, the terms and conditions of the license of that module.
+#     An independent module is a module which is not derived from this
+#     software.  The special exception does not apply to any modifications
+#     of the software.
+#  
+#  Not withstanding the above, under no circumstances may you combine
+#  this software in any way with any other Broadcom software provided
+#  under a license other than the GPL, without Broadcom's express prior
+#  written consent.
+#  
+#  :>
+#
+###############################################################################
+MOD_NAME = rscmgr
+MOD_TYPE = lib
+MOD_DEPS = dev_log cli os_cli bal_api 
+srcs = rsc_mgr.c rsc_mgr_common.c rsc_mgr_cli.c
+
+# XXX To break a circular dependency, we should avoid adding bal_core to MOD_DEPS
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../core/main
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr.c b/bal_release/src/lib/librscmgr/rsc_mgr.c
new file mode 100644
index 0000000..bd8afec
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr.c
@@ -0,0 +1,922 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#include <bcmolt_host_api.h>
+#include <bcm_dev_log.h>
+#include <bal_objs.h>
+#include <bal_api.h>
+#include <bal_cli.h>
+#include <bcmolt_math.h>
+#include <bcm_topo.h>
+#include "rsc_mgr_common.h"
+#include "rsc_mgr.h"
+
+#define GPON_NUM_OF_ALLOC_IDS 1024
+#define XGPON_NUM_OF_ALLOC_IDS 2048
+
+#define GPON_NUM_OF_GEM_PORT_IDS_PER_PON 4096
+#define XGPON_NUM_OF_GEM_PORT_IDS_PER_PON 8192
+
+#define RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id) \
+    ((first_data_alloc_id) + (bcmolt_pon_alloc_id)(RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids - 1))
+#define RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id) ( \
+    ((alloc_id) >= (first_data_alloc_id) && (alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id)))
+#define RSC_MGR_ALLOC_ID_IS_VALID(pon_id, alloc_id, first_data_alloc_id) ( \
+    ((alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DEFAULT(pon_id)) || \
+    RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id))
+
+#define RSC_MGR_GEM_PORT_ID_LAST_DEFAULT(pon_id) ((bcmolt_pon_gem_port_id)(bcm_topo_pon_get_max_num_of_onus(pon_id) - 1))
+#define RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id) \
+    ((first_data_port_id) + (bcmolt_pon_gem_port_id)(RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports - bcm_topo_pon_get_max_num_of_onus(pon_id) - 1))
+#define RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id) ( \
+    ((gem_port_id) >= (first_data_port_id) && (gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id)))
+#define RSC_MGR_GEM_PORT_ID_IS_VALID(pon_id, gem_port_id, first_data_port_id) ( \
+    ((gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DEFAULT(pon_id)) || \
+    RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id))
+
+#define RSC_MGR_FOR_EACH_ALLOC_INDEX(pon_id, alloc_index) \
+    for (alloc_index = (bcmolt_pon_alloc_index)0; alloc_index < (bcmolt_pon_alloc_index)RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids; alloc_index++)
+
+#define RSC_MGR_FOR_EACH_GEM_INDEX(pon_id, gem_port_index) \
+    for (gem_port_index = 0; (bcmolt_pon_gem_port_index)gem_port_index < (bcmolt_pon_gem_port_index)RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports; gem_port_index++)
+
+#define RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(tm_sched_auto_index) \
+		for (tm_sched_auto_index = 0; (bcmbal_tm_sched_id_index)tm_sched_auto_index < (bcmbal_tm_sched_id_index)tm_context.num_of_tm_sched_auto_key_ids; tm_sched_auto_index++)
+
+/* Because GEM port 0 .. 127 are used for OMCI, we can start allocating from 128. But due to a bug in Maple A0, 128 .. 159 must not be used. So we start from 256. */
+#define MIN_BASE_GEM_PORT_ID_GPON 256
+
+#define NUM_OF_TM_SCHED_AUTO_KEY_IDS	2048
+#define MIN_BASE_TM_SCHED_AUTO_ID 2048
+
+
+rsc_mgr_context_t rsc_mgr_context;
+rsc_mgr_tm_context tm_context;
+
+
+static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id);
+static bcmos_errno rsc_mgr_obj_get(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_obj **obj, dev_log_id log_id);
+static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data);
+static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data);
+
+
+static bcmos_bool rsc_mgr_is_valid_data_alloc_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_alloc_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return (rsc_mgr_obj_id)(bcmolt_pon_alloc_id)RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, min_data_obj_id);
+}
+
+static bcmos_bool rsc_mgr_is_valid_data_gem_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_gem_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return (rsc_mgr_obj_id)(bcmolt_pon_gem_port_id)RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, min_data_obj_id);
+}
+static bcmos_bool rsc_mgr_is_valid_data_tm_sched_auto_id(rsc_mgr_obj_id id)
+{
+    return (id >= MIN_BASE_TM_SCHED_AUTO_ID && id < MIN_BASE_TM_SCHED_AUTO_ID + NUM_OF_TM_SCHED_AUTO_KEY_IDS);
+}
+
+static bcmos_bool rsc_mgr_is_valid_data_tm_sched_auto_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return rsc_mgr_is_valid_data_tm_sched_auto_id(id);
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_tm_sched_auto_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+    return (rsc_mgr_obj_id)(min_data_obj_id + NUM_OF_TM_SCHED_AUTO_KEY_IDS - 1);
+}
+
+
+static bcmos_errno rsc_mgr_obj_alloc(bcmbal_intf_id access_int_id, rsc_mgr_obj_id *obj_id, uint32_t range_size, rsc_mgr_obj_type type, rsc_mgr_obj_rsc *obj_rsc, void *user_data, dev_log_id log_id)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+
+    if (range_size < RSC_MGR_MIN_RANGE_SIZE || range_size > RSC_MGR_MAX_RANGE_SIZE)
+    {
+        BCM_LOG(ERROR, log_id, "Range size must be in the range %u .. %u\n", RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE);
+        return BCM_ERR_PARM;
+    }
+  
+    if (*obj_id)
+    {
+        rc = rsc_mgr_obj_get(access_int_id, *obj_id, obj_rsc, &obj, log_id);
+        if (rc != BCM_ERR_OK)
+            return rc;
+
+        if (obj->range_size != range_size)
+        {
+            BCM_LOG(ERROR, log_id, "When reusing a range of %ss, range size (%d) must be exactly the same as the range from creation (%u)\n",
+                obj_rsc->obj_name, range_size, obj->range_size);
+            return BCM_ERR_PARM;
+        }
+
+        if (obj->type != type)
+        {
+            BCM_LOG(ERROR, log_id, "When reusing %ss, type (%d) must be exactly the same as the type from creation (%u)\n",
+                obj_rsc->obj_name, type, obj->type);
+            return BCM_ERR_PARM;
+        }
+    }
+    else
+    {
+        rsc_mgr_obj *base_obj;
+        rsc_mgr_obj *last_obj;
+        rsc_mgr_obj *obj_iter;
+        
+        /* Find the first free range that fits ("first-fit" algorithm). */
+        TAILQ_FOREACH(obj_iter, &obj_rsc->free_objs, list)
+        {
+            if (range_size <= obj_iter->range_size)
+                break;
+        }
+        if (!obj_iter)
+        {
+            BCM_LOG(ERROR, log_id, "No free %ss\n", obj_rsc->obj_name);
+            return BCM_ERR_NORES;
+        }
+        *obj_id = obj_iter->id;
+
+        if (range_size < obj_iter->range_size)
+        {
+            /* Insert a smaller range (decrease by 'range_size') to the list of free objects. It will replace the old free range. */
+            base_obj = &obj_iter[range_size];
+            last_obj = &obj_iter[obj_iter->range_size - 1];
+            TAILQ_INSERT_HEAD(&obj_rsc->free_objs, base_obj, list);
+            base_obj->range_size = obj_iter->range_size - range_size;
+            last_obj->base_obj = base_obj;
+        }
+
+        /* Move 'range_size' objects from the list of free objects to the list of allocated objects. */
+        base_obj = obj_iter;
+        last_obj = &obj_iter[range_size - 1];
+        TAILQ_REMOVE(&obj_rsc->free_objs, base_obj, list);
+        TAILQ_INSERT_HEAD(&obj_rsc->allocated_objs, base_obj, list);
+        base_obj->range_size = range_size;
+        base_obj->type = type;
+        last_obj->base_obj = base_obj;
+
+        obj = obj_iter;
+        /* since new object, initialize the user data list */
+        TAILQ_INIT(&obj->user_data_list);
+
+    }
+    obj->ref_count++;
+
+    /** store user data (flow entry pointer) in a linked list inside the object */
+    rsc_mgr_obj_store_user_data(obj, user_data);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_obj_free(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, void *user_data, dev_log_id log_id)
+{
+    rsc_mgr_obj *obj;
+    rsc_mgr_obj *last_obj;
+    bcmos_errno rc;
+
+    rc = rsc_mgr_obj_get(access_int_id, obj_id, obj_rsc, &obj, log_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    obj->ref_count--;
+    /** remove user data (flow entry pointer) from the linked list inside the object */
+    rsc_mgr_obj_remove_user_data(obj, user_data);
+
+    if (!obj->ref_count)
+    {
+        rsc_mgr_obj *next_obj = NULL;
+        rsc_mgr_obj *prev_obj = NULL;
+
+        /* Validate that going to the next object won't overflow the array. */
+        if (obj < &obj_rsc->objs[obj_rsc->num_of_objs - 1] && &obj[obj->range_size] <= &obj_rsc->objs[obj_rsc->num_of_objs - 1])
+        {
+            /* Check if the next ID is in the free list (according to its reference count).
+             * If true -> we can merge obj's range with the next range. */
+            if (!obj[obj->range_size].ref_count)
+                next_obj = &obj[obj->range_size];
+        }
+
+        /* Validate that going to the base of the previous range won't underflow the array. */
+        if (obj > obj_rsc->objs)
+        {
+            /* Check if the base ID of the previous range is in the free list (according to the base ID's reference count).
+             * If true -> we can merge obj's range with the previous range. */
+            if (obj[-1].base_obj && !obj[-1].base_obj->ref_count)
+                prev_obj = obj[-1].base_obj;
+        }
+
+        /* First remove the object from the allocated linked list. */
+        TAILQ_REMOVE(&obj_rsc->allocated_objs, obj, list);
+        last_obj = &obj[obj->range_size - 1];
+        obj->type = RSC_MGR_OBJ_TYPE_INVALID; /* Clear type. */
+        if (next_obj && !prev_obj)
+        {
+            /* Merge only with next range. */
+            TAILQ_INSERT_BEFORE(next_obj, obj, list);
+            TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
+            obj->range_size += next_obj->range_size;
+            last_obj->base_obj = NULL;
+            next_obj->range_size = 0;
+            last_obj = &obj[obj->range_size - 1];
+            last_obj->base_obj = obj;
+        }
+        else if (!next_obj && prev_obj)
+        {
+            /* Merge only with previous range. */
+            prev_obj->range_size += obj->range_size;
+            obj->range_size = 0;
+            last_obj->base_obj = prev_obj;
+        }
+        else if (next_obj && prev_obj)
+        {
+            /* Merge with both next and previous ranges. */
+            prev_obj->range_size += obj->range_size + next_obj->range_size;
+            obj->range_size = 0;
+            next_obj->range_size = 0;
+            TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
+            last_obj->base_obj = NULL;
+            last_obj = &prev_obj[prev_obj->range_size - 1];
+            last_obj->base_obj = prev_obj;
+        }
+        else
+        {
+            /* No merge at all. */
+            TAILQ_INSERT_TAIL(&obj_rsc->free_objs, obj, list);
+        }
+    }
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_obj_get(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_obj **obj, dev_log_id log_id)
+{
+    bcmos_errno rc;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    if (!obj_rsc->is_valid_data_obj_id_cb(access_int_id, obj_id, obj_rsc->min_data_obj_id))
+    {
+        BCM_LOG(ERROR, log_id, "%s must be in the range %u .. %u\n",
+            obj_rsc->obj_name, obj_rsc->min_data_obj_id, obj_rsc->get_last_data_obj_id_cb(access_int_id, obj_rsc->min_data_obj_id));
+        return BCM_ERR_PARM;
+    }
+
+    *obj = &obj_rsc->objs[obj_id - obj_rsc->min_data_obj_id];
+    /* Only base object must have its reference count > 0. */
+    if (!(*obj)->ref_count)
+    {
+        BCM_LOG(ERROR, log_id, "%s hasn't been allocated before\n", obj_rsc->obj_name);
+        return BCM_ERR_PARM;
+    }
+
+    return BCM_ERR_OK;
+}
+
+/** @brief stores user passed in data in the linked list inside the obj */
+static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data)
+{
+    rsc_mgr_user_data_entry *user_data_entry = NULL;
+
+    if (NULL == user_data)
+        return BCM_ERR_OK;
+
+    user_data_entry = bcmos_calloc(sizeof(rsc_mgr_user_data_entry));
+    user_data_entry->user_data = user_data;
+    TAILQ_INSERT_HEAD(&obj->user_data_list, user_data_entry, next);
+
+    return BCM_ERR_OK;
+}
+
+/** @brief removes user data from the linked list inside the obj */
+static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data)
+{
+    rsc_mgr_user_data_entry *user_data_entry = NULL, *user_data_entry_tmp;
+
+    if (NULL == user_data)
+        return BCM_ERR_OK;
+
+    TAILQ_FOREACH_SAFE(user_data_entry, &obj->user_data_list, next, user_data_entry_tmp)
+    {
+        if (user_data == user_data_entry->user_data)
+            break;
+    }
+    TAILQ_REMOVE(&obj->user_data_list, user_data_entry, next);
+
+    user_data_entry->user_data = NULL;
+    bcmos_free(user_data_entry);
+
+    return BCM_ERR_OK;
+}
+
+/** @brief iterator to iterate through the user data list in obj 
+ * @note the assumption is if a NULL is returned, then caller code stop the iteration.
+ * */
+static void *rsc_mgr_obj_get_next_user_data(rsc_mgr_obj *obj, void **curr_user_data_entry, void **next_user_data_entry)
+{
+    if (NULL == *curr_user_data_entry)
+    {
+        *curr_user_data_entry = TAILQ_FIRST(&obj->user_data_list);
+        if (*curr_user_data_entry)
+        {
+            *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*curr_user_data_entry), next);
+            return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
+        }
+    }
+    else
+    {
+        *curr_user_data_entry = *next_user_data_entry;
+        if (*next_user_data_entry)
+        {
+            *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*next_user_data_entry), next);
+            return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
+        }
+    }
+
+    return NULL;
+}
+
+
+/* Alloc ID (aggregation port ID) */
+static bcmos_errno _rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id)
+{
+    bcmolt_pon_alloc_index alloc_index;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
+    {
+        bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
+        bcmolt_gpon_ni_cfg_id failed_prop;
+
+        BCMOLT_CFG_PROP_SET(&gpon_ni_cfg, gpon_ni, min_data_alloc_id, min_data_agg_port_id);
+        if (!bcmolt_gpon_ni_cfg_data_bounds_check(&gpon_ni_cfg.data, (1ULL << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
+        {
+            BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
+            return BCM_ERR_PARM;
+        }
+    }
+    else
+    {
+        bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+        bcmolt_xgpon_ni_cfg_id failed_prop;
+
+        BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_alloc_id, min_data_agg_port_id);
+        if (!bcmolt_xgpon_ni_cfg_data_bounds_check(&xgpon_ni_cfg.data, (1ULL << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
+        {
+            BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
+            return BCM_ERR_PARM;
+        }
+    }
+    
+    if (!TAILQ_EMPTY(&topo_context->alloc_ids.allocated_objs))
+    {
+        BCM_LOG(ERROR, topo_context->log_id, "Minimal alloc ID cannot be set when there are allocated alloc IDs\n");
+        return BCM_ERR_STATE;
+    }
+
+    topo_context->alloc_ids.min_data_obj_id = (rsc_mgr_obj_id)min_data_agg_port_id;
+    RSC_MGR_FOR_EACH_ALLOC_INDEX(access_int_id, alloc_index)
+        topo_context->alloc_ids.objs[alloc_index].id = topo_context->alloc_ids.min_data_obj_id + alloc_index;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id)
+{
+    bcmos_errno rc;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    return _rsc_mgr_access_int_base_alloc_id_set(access_int_id, min_data_agg_port_id);
+}
+
+
+static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id)
+{
+    bcmos_errno rc;
+
+    rc = rsc_mgr_init_validate();
+    if (rc != BCM_ERR_OK)
+    {
+        BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+        return rc;
+    }
+
+    if (!bcm_topo_pon_is_valid(access_int_id))
+        return BCM_ERR_PARM;
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_alloc_validate_non_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id topo_context_gem_port, 
+                                                        bcmbal_service_port_id req_gem_port, uint32_t range_size, rsc_mgr_obj_type type, 
+                                                        dev_log_id log_id)
+{
+    if (topo_context_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID && req_gem_port && req_gem_port != topo_context_gem_port)
+    {
+        BCM_LOG(ERROR, log_id, "Access interface already has %s service port ID=%u configured\n", RSC_MGR_OBJ_TYPE_STR(type), topo_context_gem_port);
+        return BCM_ERR_ALREADY;
+    }
+
+    if (range_size > 1)
+    {
+        BCM_LOG(ERROR, log_id, "Range bigger than 1 for %s GEM port is not allowed\n", RSC_MGR_OBJ_TYPE_STR(type));
+        return BCM_ERR_PARM;
+    }
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_alloc_id_alloc(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id *agg_port_id, uint32_t range_size, void *user_data)
+{
+    bcmos_errno rc;
+    rsc_mgr_obj_id obj_id = *agg_port_id;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_ALLOC_ID, &topo_context->alloc_ids, user_data, topo_context->log_id);
+    *agg_port_id = obj_id;
+
+    return rc;
+}
+
+bcmos_errno rsc_mgr_alloc_id_free(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void *user_data)
+{
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    if (!bcm_topo_pon_is_valid(access_int_id))
+        return BCM_ERR_PARM;
+
+    return rsc_mgr_obj_free(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, user_data, topo_context->log_id);
+}
+
+bcmos_errno rsc_mgr_alloc_id_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, uint32_t *ref_count)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    *ref_count = obj->ref_count;
+
+    return BCM_ERR_OK;
+}
+
+/** @brief iterates through user data list of an alloc id object */
+void *rsc_mgr_alloc_id_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void **curr_user_data_entry, void **next_user_data_entry)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
+    if (rc != BCM_ERR_OK)
+        return NULL;
+
+    return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry); 
+}
+
+/* GEM (service port ID) */
+static bcmos_errno _rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
+{
+    bcmolt_pon_gem_port_index gem_index;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
+    {
+        bcmolt_gpon_gem_port_cfg gpon_gem_port_cfg = { .key.gem_port_id = min_data_svc_port_id };
+        bcmolt_gpon_gem_port_key_id failed_prop;
+
+        if (!bcmolt_gpon_gem_port_key_bounds_check(&gpon_gem_port_cfg.key, 1ULL << BCMOLT_GPON_GEM_PORT_KEY_ID_GEM_PORT_ID, &failed_prop) ||
+            min_data_svc_port_id < MIN_BASE_GEM_PORT_ID_GPON)
+        {
+            BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
+            return BCM_ERR_PARM;
+        }
+    }
+    else
+    {
+        bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+        bcmolt_xgpon_ni_cfg_id failed_prop;
+
+        BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_gem_port_id, min_data_svc_port_id);
+        if (!bcmolt_xgpon_ni_cfg_data_bounds_check(&xgpon_ni_cfg.data, 1ULL << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_GEM_PORT_ID, &failed_prop))
+        {
+            BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
+            return BCM_ERR_PARM;
+        }
+    }
+
+    if (!TAILQ_EMPTY(&topo_context->gems.allocated_objs))
+    {
+        BCM_LOG(ERROR, topo_context->log_id, "Minimal GEM port cannot be set when there are allocated GEM ports\n");
+        return BCM_ERR_STATE;
+    }
+
+    topo_context->gems.min_data_obj_id = (rsc_mgr_obj_id)min_data_svc_port_id;
+    RSC_MGR_FOR_EACH_GEM_INDEX(access_int_id, gem_index)
+        topo_context->gems.objs[gem_index].id = topo_context->gems.min_data_obj_id + gem_index;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
+{
+    bcmos_errno rc;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    return _rsc_mgr_access_int_base_gem_set(access_int_id, min_data_svc_port_id);
+}
+
+static bcmos_errno _rsc_mgr_base_tm_sched_auto_id_set (bcmbal_tm_sched_id min_tm_sched_auto_id)
+{
+	bcmbal_tm_sched_id_index i;
+
+
+	if (!TAILQ_EMPTY(&tm_context.tm_sched_auto_key_ids.allocated_objs))
+	{
+		BCM_LOG(ERROR, tm_context.log_id, "Minimal tm node auto id cannot be set when there are allocated ids \n");
+		return BCM_ERR_STATE;
+	}
+
+	tm_context.tm_sched_auto_key_ids.min_data_obj_id = (rsc_mgr_obj_id)min_tm_sched_auto_id;
+	RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(i)
+	{
+		tm_context.tm_sched_auto_key_ids.objs[i].id = tm_context.tm_sched_auto_key_ids.min_data_obj_id + i;
+	}
+
+	return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_gem_alloc_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = NULL;
+    rsc_mgr_obj_id obj_id = *svc_port_id;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST, &topo_context->gems, user_data, topo_context->log_id);
+    *svc_port_id = obj_id;
+
+    return rc;
+}
+
+
+bcmos_errno rsc_mgr_gem_alloc_multicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = NULL;
+    rsc_mgr_obj_id obj_id = *svc_port_id;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    rc = rsc_mgr_alloc_validate_non_unicast(access_int_id, topo_context->multicast_gem_port, *svc_port_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST, topo_context->log_id);
+
+    if (topo_context->multicast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
+        obj_id = topo_context->multicast_gem_port; /* This will cause the reference count of the multicast GEM to increase. */
+#endif
+
+    rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST, &topo_context->gems, user_data, topo_context->log_id);
+    *svc_port_id = obj_id;
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    if (!rc)
+        RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = *svc_port_id;
+#endif
+
+    return rc;
+}
+
+bcmos_errno rsc_mgr_gem_alloc_broadcast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = NULL;
+    rsc_mgr_obj_id obj_id = *svc_port_id;
+
+    rc = rsc_mgr_alloc_validate_common(access_int_id);
+    if (BCM_ERR_OK != rc)
+        return rc;
+
+    topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+    rc = rsc_mgr_alloc_validate_non_unicast(access_int_id, topo_context->broadcast_gem_port, *svc_port_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST, topo_context->log_id);
+
+    if (topo_context->broadcast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
+        obj_id = topo_context->broadcast_gem_port; /* This will cause the reference count of the broadcast GEM to increase. */
+#endif
+
+    rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST, &topo_context->gems, user_data, topo_context->log_id);
+    *svc_port_id = obj_id;
+
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+    if (!rc)
+        RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->broadcast_gem_port = *svc_port_id;
+#endif
+
+    return rc;
+}
+
+bcmos_errno rsc_mgr_gem_free(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void *user_data)
+{
+    bcmos_errno rc;
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    rsc_mgr_topo_pon_context *topo_context;
+#endif
+
+    if (!bcm_topo_pon_is_valid(access_int_id))
+        return BCM_ERR_PARM;
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#endif
+
+    rc = rsc_mgr_obj_free(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, user_data, topo_context->log_id);
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    if (!rc && topo_context->multicast_gem_port == svc_port_id)
+        RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+#endif
+
+    return rc;
+}
+
+bcmos_errno rsc_mgr_gem_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, uint32_t *ref_count)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    *ref_count = obj->ref_count;
+
+    return BCM_ERR_OK;
+}
+
+/** @brief iterates through user data list of a gem object */
+void *rsc_mgr_gem_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void **curr_user_data_entry, void **next_user_data_entry)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+    rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
+    if (rc != BCM_ERR_OK)
+        return NULL;
+
+    return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry); 
+}
+
+
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_alloc(bcmbal_tm_sched_id *tm_sched_id)
+{
+    bcmos_errno rc;
+    rsc_mgr_obj_id obj_id = *tm_sched_id;
+
+    rc = rsc_mgr_init_validate();
+    if (rc != BCM_ERR_OK)
+    {
+        BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+        return rc;
+    }
+
+    /* Allocate a new object. */
+    rc = rsc_mgr_obj_alloc(0, &obj_id, 1, RSC_MGR_OBJ_TYPE_TM_SCHED, &tm_context.tm_sched_auto_key_ids, NULL, tm_context.log_id);
+    *tm_sched_id = obj_id;
+
+    return rc;
+}
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_free(bcmbal_tm_sched_id tm_sched_id)
+{
+    bcmos_errno rc;
+
+    rc = rsc_mgr_obj_free(0, (rsc_mgr_obj_id)tm_sched_id, &tm_context.tm_sched_auto_key_ids, NULL, tm_context.log_id);
+
+    return rc;
+}
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_get_ref_count(bcmbal_tm_sched_id tm_sched_id, uint32_t *ref_count)
+{
+    rsc_mgr_obj *obj;
+    bcmos_errno rc;
+
+    rc = rsc_mgr_obj_get(0, (rsc_mgr_obj_id)tm_sched_id, &tm_context.tm_sched_auto_key_ids, &obj, tm_context.log_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    *ref_count = obj->ref_count;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_bool _rsc_mgr_tm_sched_id_validate(bcmbal_tm_sched_id tm_sched_key_id)
+{
+	return (!rsc_mgr_is_valid_data_tm_sched_auto_id(tm_sched_key_id));
+}
+
+static void rsc_mgr_init_obj_rsc(rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_is_valid_data_obj_id_cb_t is_valid_data_obj_id_cb,
+    rsc_mgr_get_last_data_obj_id_cb_t get_last_data_obj_id_cb, uint32_t num_of_objs, const char *obj_name)
+{
+    rsc_mgr_obj *obj;
+
+    obj_rsc->obj_name = obj_name;
+    obj_rsc->is_valid_data_obj_id_cb = is_valid_data_obj_id_cb;
+    obj_rsc->get_last_data_obj_id_cb = get_last_data_obj_id_cb;
+    TAILQ_INIT(&obj_rsc->free_objs);
+    TAILQ_INIT(&obj_rsc->allocated_objs);
+    obj_rsc->objs = bcmos_calloc(num_of_objs * sizeof(*obj_rsc->objs));
+    obj_rsc->num_of_objs = num_of_objs;
+
+    /* Insert a first entry to the list of free objects. */
+    obj = &obj_rsc->objs[0];
+    obj->range_size = num_of_objs;
+    TAILQ_INSERT_HEAD(&obj_rsc->free_objs, obj, list);
+}
+
+static void rsc_mgr_uninit_obj_rsc(rsc_mgr_obj_rsc *obj_rsc)
+{
+    bcmos_free(obj_rsc->objs);
+}
+
+bcmos_errno rsc_mgr_mac_init(void)
+{
+    bcmos_errno rc = BCM_ERR_OK;
+    bcmolt_devid device_id;
+    uint32_t pon_id;
+    rsc_mgr_topo_pon_context *topo_context, *old_topo_context;
+
+    do
+    {
+        rc = rsc_mgr_init_validate();
+        if (rc != BCM_ERR_OK)
+        {
+            BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was not initialized");   	    
+            break;
+        }
+        BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
+        {
+            old_topo_context = bcm_topo_pon_get_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR);
+            if (old_topo_context)
+            {
+                bcmos_free(old_topo_context);
+            }
+            topo_context = bcmos_calloc(sizeof(*topo_context));
+            if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
+			{
+				topo_context->num_of_alloc_ids = GPON_NUM_OF_ALLOC_IDS;
+				topo_context->num_of_gem_ports = GPON_NUM_OF_GEM_PORT_IDS_PER_PON;
+			}
+			else
+			{
+				topo_context->num_of_alloc_ids = XGPON_NUM_OF_ALLOC_IDS;
+				topo_context->num_of_gem_ports = XGPON_NUM_OF_GEM_PORT_IDS_PER_PON;
+			}
+			topo_context->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+			topo_context->broadcast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+			bcm_topo_pon_set_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR, topo_context);
+#ifdef ENABLE_LOG
+			snprintf(topo_context->log_id_name, sizeof(topo_context->log_id_name), "RSC_MGR%u", pon_id);
+			topo_context->log_id = bcm_dev_log_id_register(topo_context->log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+			BUG_ON(topo_context->log_id == DEV_LOG_INVALID_ID);
+#endif	    
+			rsc_mgr_init_obj_rsc(&topo_context->alloc_ids, rsc_mgr_is_valid_data_alloc_id_cb, rsc_mgr_get_last_data_alloc_id_cb,
+				RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids, "alloc ID");
+			rsc_mgr_init_obj_rsc(&topo_context->gems, rsc_mgr_is_valid_data_gem_cb, rsc_mgr_get_last_data_gem_cb,
+				RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports, "GEM port");
+			
+			if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
+			{
+				bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
+				
+				bcmolt_gpon_ni_cfg_data_set_default(&gpon_ni_cfg.data, 1 << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
+				_rsc_mgr_access_int_base_alloc_id_set(pon_id, gpon_ni_cfg.data.min_data_alloc_id);
+				
+				_rsc_mgr_access_int_base_gem_set(pon_id, MIN_BASE_GEM_PORT_ID_GPON);
+			}
+			else
+			{
+				bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+				
+				bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
+				_rsc_mgr_access_int_base_alloc_id_set(pon_id, xgpon_ni_cfg.data.min_data_alloc_id);
+				
+				bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_GEM_PORT_ID);
+				_rsc_mgr_access_int_base_gem_set(pon_id, xgpon_ni_cfg.data.min_data_gem_port_id);
+			}
+		}	
+        
+    }while(0);
+    return rc;
+}
+
+bcmos_errno rsc_mgr_init(void)
+{
+    if (rsc_mgr_init_validate() == BCM_ERR_OK)
+   	{
+        BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was already initialized");   	    
+        return BCM_ERR_OK;
+   	}
+
+#ifdef ENABLE_LOG
+    if (rsc_mgr_log_id == DEV_LOG_INVALID_ID)
+    {
+        rsc_mgr_log_id = bcm_dev_log_id_register("RSC_MGR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+        BUG_ON(rsc_mgr_log_id == DEV_LOG_INVALID_ID);
+    }
+#endif
+
+    /*Init the tm object*/
+    tm_context.num_of_tm_sched_auto_key_ids = NUM_OF_TM_SCHED_AUTO_KEY_IDS;
+    snprintf(tm_context.log_id_name , sizeof(tm_context.log_id_name) , "RSC_MGR_TM");
+	tm_context.log_id = bcm_dev_log_id_register(tm_context.log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+    BUG_ON(tm_context.log_id == DEV_LOG_INVALID_ID);
+	
+	rsc_mgr_init_obj_rsc(&tm_context.tm_sched_auto_key_ids, rsc_mgr_is_valid_data_tm_sched_auto_id_cb, rsc_mgr_get_last_data_tm_sched_auto_id_cb,
+		tm_context.num_of_tm_sched_auto_key_ids, "TM node auto id");
+
+	_rsc_mgr_base_tm_sched_auto_id_set(MIN_BASE_TM_SCHED_AUTO_ID);
+	
+    rsc_mgr_context.is_initialized = BCMOS_TRUE;
+    return BCM_ERR_OK;
+}
+
+void rsc_mgr_uninit(void)
+{
+    bcmolt_devid device_id;
+    uint32_t pon_id;
+
+    if (!rsc_mgr_context.is_initialized)
+        return;
+
+    BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
+    {
+        rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(pon_id);
+
+        rsc_mgr_uninit_obj_rsc(&topo_context->gems);
+        rsc_mgr_uninit_obj_rsc(&topo_context->alloc_ids);
+    }
+    rsc_mgr_context.is_initialized = BCMOS_FALSE;
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr.h b/bal_release/src/lib/librscmgr/rsc_mgr.h
new file mode 100644
index 0000000..072d37e
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#ifndef _RSC_MGR_H_
+#define _RSC_MGR_H_
+
+#include <bal_objs.h>
+
+/* Alloc ID (aggregation port ID) */
+bcmos_errno rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id);
+bcmos_errno rsc_mgr_alloc_id_alloc(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id *agg_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_alloc_id_free(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void *user_data);
+bcmos_errno rsc_mgr_alloc_id_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, uint32_t *ref_count);
+void* rsc_mgr_alloc_id_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void **curr_user_data_entry, void **next_user_data_entry);
+
+
+/* GEM (service port ID) */
+bcmos_errno rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id);
+bcmos_errno rsc_mgr_gem_alloc_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_alloc_multicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_alloc_broadcast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_free(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void *user_data);
+bcmos_errno rsc_mgr_gem_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, uint32_t *ref_count);
+void* rsc_mgr_gem_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void **curr_user_data_entry, void **next_user_data_entry);
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_alloc(bcmbal_tm_sched_id *tm_sched_key_id);
+bcmos_errno _rsc_mgr_tm_sched_auto_id_free(bcmbal_tm_sched_id tm_sched_key_id);
+bcmos_errno _rsc_mgr_tm_sched_auto_id_get_ref_count(bcmbal_tm_sched_id tm_sched_key_id, uint32_t *ref_count);
+bcmos_bool _rsc_mgr_tm_sched_id_validate(bcmbal_tm_sched_id tm_sched_key_id);
+
+bcmos_errno rsc_mgr_mac_init(void);
+bcmos_errno rsc_mgr_init(void);
+void rsc_mgr_uninit(void);
+
+#endif
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_cli.c b/bal_release/src/lib/librscmgr/rsc_mgr_cli.c
new file mode 100644
index 0000000..7584741
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_cli.c
@@ -0,0 +1,315 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#include <bcm_dev_log.h>
+#include <bcmcli.h>
+#include <bal_objs.h>
+#include <bal_api.h>
+#include <bcm_topo.h>
+#include "rsc_mgr.h"
+#include "rsc_mgr_common.h"
+#include "rsc_mgr_cli.h"
+
+static bcmos_errno rsc_mgr_cli_cmd_init(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return rsc_mgr_init();
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_base_alloc_id_set(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmbal_aggregation_port_id min_data_agg_port_id = (bcmbal_aggregation_port_id)bcmcli_find_named_parm(session, "min_data_agg_port_id")->value.unumber;
+
+    return rsc_mgr_access_int_base_alloc_id_set(access_int_id, min_data_agg_port_id);
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_base_gem_set(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmbal_service_port_id min_data_svc_port_id = (bcmbal_service_port_id)bcmcli_find_named_parm(session, "min_data_svc_port_id")->value.unumber;
+
+    return rsc_mgr_access_int_base_gem_set(access_int_id, min_data_svc_port_id);
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_alloc_id_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmcli_cmd_parm *agg_port_id_parm = bcmcli_find_named_parm(session, "agg_port_id");
+    bcmbal_aggregation_port_id agg_port_id = 0;
+    uint32_t range_size = (uint32_t)bcmcli_find_named_parm(session, "range_size")->value.unumber;
+    uint32_t ref_count;
+    bcmos_errno rc;
+
+    if (agg_port_id_parm)
+        agg_port_id = (bcmbal_aggregation_port_id)agg_port_id_parm->value.unumber;
+
+    rc = rsc_mgr_alloc_id_alloc(access_int_id, &agg_port_id, range_size, NULL);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    rc = rsc_mgr_alloc_id_get_ref_count(access_int_id, agg_port_id, &ref_count);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    bcmcli_session_print(session, "Allocated alloc ID=%u (ref_count=%u)\n", agg_port_id, ref_count);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_alloc_id_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmbal_aggregation_port_id agg_port_id = (bcmbal_aggregation_port_id)bcmcli_find_named_parm(session, "agg_port_id")->value.unumber;
+    uint32_t ref_count;
+    bcmos_errno rc;
+
+    rc = rsc_mgr_alloc_id_get_ref_count(access_int_id, agg_port_id, &ref_count);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    rc = rsc_mgr_alloc_id_free(access_int_id, agg_port_id, NULL);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    bcmcli_session_print(session, "Freed alloc ID=%u (ref_count=%u)\n", agg_port_id, ref_count - 1);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_gem_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmcli_cmd_parm *svc_port_id_parm = bcmcli_find_named_parm(session, "svc_port_id");
+    bcmbal_service_port_id svc_port_id = 0;
+    uint32_t range_size = (uint32_t)bcmcli_find_named_parm(session, "range_size")->value.unumber;
+    rsc_mgr_obj_type gem_type = (rsc_mgr_obj_type)bcmcli_find_named_parm(session, "gem_type")->value.enum_val;
+    uint32_t ref_count;
+    bcmos_errno rc;
+
+    if (svc_port_id_parm)
+        svc_port_id = (bcmbal_service_port_id)svc_port_id_parm->value.unumber;
+
+    if (RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST == gem_type)
+        rc = rsc_mgr_gem_alloc_multicast(access_int_id, &svc_port_id, range_size, NULL);
+    else if (RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST == gem_type)
+        rc = rsc_mgr_gem_alloc_broadcast(access_int_id, &svc_port_id, range_size, NULL);
+    else
+        rc = rsc_mgr_gem_alloc_unicast(access_int_id, &svc_port_id, range_size, NULL);
+
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    rc = rsc_mgr_gem_get_ref_count(access_int_id, svc_port_id, &ref_count);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    bcmcli_session_print(session, "Allocated GEM port=%u (ref_count=%u)\n", svc_port_id, ref_count);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_gem_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+    bcmbal_service_port_id svc_port_id = (bcmbal_service_port_id)bcmcli_find_named_parm(session, "svc_port_id")->value.unumber;
+    uint32_t ref_count;
+    bcmos_errno rc;
+
+    rc = rsc_mgr_gem_get_ref_count(access_int_id, svc_port_id, &ref_count);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    rc = rsc_mgr_gem_free(access_int_id, svc_port_id, NULL);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    bcmcli_session_print(session, "Freed GEM port=%u (ref_count=%u)\n", svc_port_id, ref_count - 1);
+
+    return BCM_ERR_OK;
+}
+/*allocates a new tm node auto id 
+no inputs parameters are used */
+static bcmos_errno rsc_mgr_cli_cmd_tm_sched_auto_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_tm_sched_id tm_sched_auto_id = 0;
+    bcmos_errno rc;
+
+    rc = _rsc_mgr_tm_sched_auto_id_alloc(&tm_sched_auto_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+
+    bcmcli_session_print(session, "Allocated TM SCHED AUTO ID %u \n", tm_sched_auto_id);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_tm_sched_auto_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_tm_sched_id tm_sched_auto_id = (bcmbal_tm_sched_id)bcmcli_find_named_parm(session, "tm_sched_auto_id")->value.unumber;
+    uint32_t ref_count;
+    bcmos_errno rc;
+
+    rc = _rsc_mgr_tm_sched_auto_id_get_ref_count(tm_sched_auto_id, &ref_count);
+
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    rc = _rsc_mgr_tm_sched_auto_id_free(tm_sched_auto_id);
+    if (rc != BCM_ERR_OK)
+        return rc;
+
+    bcmcli_session_print(session, "Freed TM NODE AUTO ID %u (ref_count=%u)\n", tm_sched_auto_id, ref_count - 1);
+
+    return BCM_ERR_OK;
+}
+
+static void rsc_mgr_show_objs_list(bcmcli_session *session, bcmbal_intf_id access_int_id, rsc_mgr_obj_rsc *obj_rsc,
+    rsc_mgr_obj_list *obj_list)
+{
+    rsc_mgr_obj *obj_iter;
+
+    TAILQ_FOREACH(obj_iter, obj_list, list)
+    {
+        if (obj_iter->range_size == 1)
+        {
+            bcmcli_session_print(session, "\t%s=%u (obj_type=%s, ref_count=%u)\n", 
+                    obj_rsc->obj_name, obj_iter->id, RSC_MGR_OBJ_TYPE_STR(obj_iter->type), obj_iter->ref_count);
+        }
+        else
+        {
+            bcmcli_session_print(session, "\t%s=%u .. %u (obj_type=%s, ref_count=%u)\n",
+                obj_rsc->obj_name, obj_iter->id, obj_iter->id + obj_iter->range_size - 1, RSC_MGR_OBJ_TYPE_STR(obj_iter->type), obj_iter->ref_count);
+        }
+    }
+}
+
+static void rsc_mgr_show_objs(bcmcli_session *session, bcmbal_intf_id access_int_id, rsc_mgr_obj_rsc *obj_rsc)
+{
+    bcmcli_session_print(session, "Base data %s=%u\n", obj_rsc->obj_name, obj_rsc->min_data_obj_id);
+    bcmcli_session_print(session, "Allocated %ss:\n", obj_rsc->obj_name);
+    rsc_mgr_show_objs_list(session, access_int_id, obj_rsc, &obj_rsc->allocated_objs);
+    bcmcli_session_print(session, "Free %ss:\n", obj_rsc->obj_name);
+    rsc_mgr_show_objs_list(session, access_int_id, obj_rsc, &obj_rsc->free_objs);
+}
+
+static bcmos_errno rsc_mgr_show(bcmcli_session *session, bcmbal_intf_id access_int_id)
+{
+    bcmos_errno rc;
+    rsc_mgr_topo_pon_context *topo_context;
+
+    rc = rsc_mgr_init_validate();
+    if (rc != BCM_ERR_OK)
+    {
+        BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+        return rc;
+    }
+
+    if (!bcm_topo_pon_is_valid(access_int_id))
+        return BCM_ERR_PARM;
+
+    topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+    rsc_mgr_show_objs(session, access_int_id, &topo_context->alloc_ids);
+    rsc_mgr_show_objs(session, access_int_id, &topo_context->gems);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_show(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+
+    return rsc_mgr_show(session, access_int_id);
+}
+
+void rsc_mgr_cli_init(bcmcli_entry *cli_dir)
+{
+    bcmcli_entry *dbg_dir;
+
+    static bcmcli_enum_val rsc_mgr_cli_enum_gem_type_table[] =
+    {
+        { .name = "unicast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST },
+        { .name = "multicast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST },
+        { .name = "broadcast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST },
+        BCMCLI_ENUM_LAST
+    };
+
+    dbg_dir = bcmcli_dir_add(cli_dir, "rsc_mgr", "BAL resource manager API access", BCMCLI_ACCESS_ADMIN, NULL);
+
+    BCMCLI_MAKE_CMD(dbg_dir, "init", "Initialize resource manager for a specific access terminal", rsc_mgr_cli_cmd_init,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "base_alloc_id_set", "Set the base alloc ID for an access interface", rsc_mgr_cli_cmd_base_alloc_id_set,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("min_data_agg_port_id", "minimal data aggregation port ID", BCMCLI_PARM_UNUMBER, 0));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "base_gem_set", "Set the base GEM port for an access interface", rsc_mgr_cli_cmd_base_gem_set,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("min_data_svc_port_id", "minimal data service port ID", BCMCLI_PARM_UNUMBER, 0));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "alloc_id_alloc", "Allocate an alloc ID range or reuse an existing alloc ID range", rsc_mgr_cli_cmd_alloc_id_alloc,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("agg_port_id", "aggregation port ID (if omitted a new alloc ID is allocated, otherwise we reuse an existing alloc ID)",
+        BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL),
+        BCMCLI_MAKE_PARM_RANGE("range_size", "range size", BCMCLI_PARM_UNUMBER, 0, RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "alloc_id_free", "Free an alloc ID range", rsc_mgr_cli_cmd_alloc_id_free,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("agg_port_id", "base of alloc ID range", BCMCLI_PARM_UNUMBER, 0));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "gem_alloc", "Allocate a GEM port range or reuse an existing GEM port range", rsc_mgr_cli_cmd_gem_alloc,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("svc_port_id", "service port ID (if omitted a new GEM port is allocated, otherwise we reuse an existing GEM port)",
+        BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL),
+        BCMCLI_MAKE_PARM_RANGE("range_size", "range size", BCMCLI_PARM_UNUMBER, 0, RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE),
+        BCMCLI_MAKE_PARM_ENUM("gem_type", "GEM type", rsc_mgr_cli_enum_gem_type_table, 0));
+
+    BCMCLI_MAKE_CMD(dbg_dir, "gem_free", "Free a GEM port range", rsc_mgr_cli_cmd_gem_free,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+        BCMCLI_MAKE_PARM("svc_port_id", "base of GEM port range", BCMCLI_PARM_UNUMBER, 0));
+
+    BCMCLI_MAKE_CMD_NOPARM(dbg_dir, "tm_sched_auto_id_alloc", "Allocate a tm node auto id or reuse an existing id", rsc_mgr_cli_cmd_tm_sched_auto_alloc);
+
+    BCMCLI_MAKE_CMD(dbg_dir, "tm_sched_auto_id_free", "Free a tm node auto id", rsc_mgr_cli_cmd_tm_sched_auto_free,
+        BCMCLI_MAKE_PARM("tm_sched_auto_id", "tm node auto id to be free", BCMCLI_PARM_UNUMBER, 0));
+
+
+    BCMCLI_MAKE_CMD(dbg_dir, "show", "Show the database of the resource manager", rsc_mgr_cli_cmd_show,
+        BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+        BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0));
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_cli.h b/bal_release/src/lib/librscmgr/rsc_mgr_cli.h
new file mode 100644
index 0000000..7d9085c
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_cli.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#ifndef _RSC_MGR_CLI_H_
+#define _RSC_MGR_CLI_H_
+
+#include <bcmcli.h>
+
+void rsc_mgr_cli_init(bcmcli_entry *cli_dir);
+
+#endif
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_common.c b/bal_release/src/lib/librscmgr/rsc_mgr_common.c
new file mode 100644
index 0000000..71bcee9
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_common.c
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#include <bcm_topo.h>
+#include "rsc_mgr_common.h"
+
+#ifdef ENABLE_LOG
+dev_log_id rsc_mgr_log_id = DEV_LOG_INVALID_ID;
+#endif
+
+bcmos_errno rsc_mgr_init_validate(void)
+{
+    if (!rsc_mgr_context.is_initialized)
+    {
+#ifdef ENABLE_LOG
+        if (rsc_mgr_log_id == DEV_LOG_INVALID_ID)
+        {
+            rsc_mgr_log_id = bcm_dev_log_id_register("RSC_MGR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+            BUG_ON(rsc_mgr_log_id == DEV_LOG_INVALID_ID);
+        }
+#endif
+        return BCM_ERR_STATE;
+    }
+
+    if (!bcm_topo_is_initialized())
+    {
+        BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager cannot be called before topology is initialized\n");
+        return BCM_ERR_STATE;
+    }
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_common.h b/bal_release/src/lib/librscmgr/rsc_mgr_common.h
new file mode 100644
index 0000000..4d19176
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_common.h
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ *  <:copyright-BRCM:2016:DUAL/GPL:standard
+ *  
+ *     Copyright (c) 2016 Broadcom
+ *     All Rights Reserved
+ *  
+ *  Unless you and Broadcom execute a separate written software license
+ *  agreement governing use of this software, this software is licensed
+ *  to you under the terms of the GNU General Public License version 2
+ *  (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ *  with the following added to such license:
+ *  
+ *     As a special exception, the copyright holders of this software give
+ *     you permission to link this software with independent modules, and
+ *     to copy and distribute the resulting executable under terms of your
+ *     choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module.
+ *     An independent module is a module which is not derived from this
+ *     software.  The special exception does not apply to any modifications
+ *     of the software.
+ *  
+ *  Not withstanding the above, under no circumstances may you combine
+ *  this software in any way with any other Broadcom software provided
+ *  under a license other than the GPL, without Broadcom's express prior
+ *  written consent.
+ *  
+ *  :>
+ *
+ *****************************************************************************/
+ 
+#ifndef _RSC_MGR_COMMON_H_
+#define _RSC_MGR_COMMON_H_
+ 
+#include <bcmolt_host_api.h>
+#include <bcm_dev_log.h>
+#include <bal_objs.h>
+#include <bcmolt_math.h>
+
+#define RSC_MGR_MIN_RANGE_SIZE 1
+#define RSC_MGR_MAX_RANGE_SIZE 8
+
+#define RSC_MGR_PON_TOPO_CONTEXT(pon_id) ((rsc_mgr_topo_pon_context *)bcm_topo_pon_get_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR))
+
+typedef enum rsc_mgr_obj_type
+{
+    RSC_MGR_OBJ_TYPE_INVALID = 0,
+    RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST,
+    RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST,
+    RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST,
+    RSC_MGR_OBJ_TYPE_ALLOC_ID,
+    RSC_MGR_OBJ_TYPE_TM_SCHED,
+} rsc_mgr_obj_type;
+
+#define RSC_MGR_OBJ_TYPE_STR(_type) \
+    ((_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST ? "gem_port_unicast":\
+        (_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST ? "gem_port_multicast":\
+            (_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST ? "gem_port_broadcast":\
+                (_type) == RSC_MGR_OBJ_TYPE_ALLOC_ID ? "alloc_id":\
+                    (_type) == RSC_MGR_OBJ_TYPE_TM_SCHED ? "tm_sched":"invalid")
+
+
+typedef struct
+{
+    bcmos_bool is_initialized;
+} rsc_mgr_context_t;
+
+extern rsc_mgr_context_t rsc_mgr_context;
+
+/** @brief container for storing user data */
+typedef struct rsc_mgr_user_data_entry
+{
+    TAILQ_ENTRY(rsc_mgr_user_data_entry) next;
+    void *user_data;
+} rsc_mgr_user_data_entry;
+
+/** @brief linked list of flow entries sharing the same GEM port or Alloc Id */
+typedef TAILQ_HEAD(, rsc_mgr_user_data_entry) shared_obj_user_data_list;
+
+/* An object ID can be either alloc ID or GEM port. */
+typedef uint32_t rsc_mgr_obj_id;
+
+/* An element for an object linked list. */
+typedef struct rsc_mgr_obj
+{
+    TAILQ_ENTRY(rsc_mgr_obj) list;
+    struct rsc_mgr_obj *base_obj; /* The last object of a range points to the base object of the range. */
+    rsc_mgr_obj_id id;
+    uint32_t ref_count;
+    uint32_t range_size;
+    rsc_mgr_obj_type type;
+    shared_obj_user_data_list user_data_list; /* this stores a list of flows sharing the same gem or alloc id object */
+} rsc_mgr_obj;
+
+typedef TAILQ_HEAD(, rsc_mgr_obj) rsc_mgr_obj_list;
+
+typedef bcmos_bool (*rsc_mgr_is_valid_data_obj_id_cb_t)(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id);
+typedef rsc_mgr_obj_id (*rsc_mgr_get_last_data_obj_id_cb_t)(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id);
+
+typedef struct
+{
+    const char *obj_name;
+    rsc_mgr_is_valid_data_obj_id_cb_t is_valid_data_obj_id_cb;
+    rsc_mgr_get_last_data_obj_id_cb_t get_last_data_obj_id_cb;
+    rsc_mgr_obj_list free_objs;
+    rsc_mgr_obj_list allocated_objs;
+    rsc_mgr_obj *objs; /* Dynamically allocated */
+    uint32_t num_of_objs;
+    rsc_mgr_obj_id min_data_obj_id;
+} rsc_mgr_obj_rsc;
+
+typedef struct
+{
+    rsc_mgr_obj_rsc alloc_ids;
+    rsc_mgr_obj_rsc gems;
+    uint16_t num_of_alloc_ids;
+    uint16_t num_of_gem_ports;
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+    uint16_t multicast_gem_port; /* For validation purposes (validate there is no more than a single multicast GEM port per PON). */
+#endif
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+    uint16_t broadcast_gem_port; /* For validation purposes (validate there is no more than a single broadcast GEM port per PON). */
+#endif
+#ifdef ENABLE_LOG
+    dev_log_id log_id;
+    char log_id_name[MAX_DEV_LOG_ID_NAME];
+#endif
+} rsc_mgr_topo_pon_context;
+
+typedef struct
+{
+    rsc_mgr_obj_rsc tm_sched_auto_key_ids;
+    uint16_t num_of_tm_sched_auto_key_ids;
+#ifdef ENABLE_LOG
+    dev_log_id log_id;
+    char log_id_name[MAX_DEV_LOG_ID_NAME];
+#endif
+
+} rsc_mgr_tm_context;
+#ifdef ENABLE_LOG
+extern dev_log_id rsc_mgr_log_id;
+#endif
+
+bcmos_errno rsc_mgr_init_validate(void);
+
+#endif
+